Nuke Python get knob value for if statement - python

I am relatively new to Python and I need some help. This is also my first post on this site. I am trying to change the value of the colorspace knob in Read Node I have labeled "Plate". I would like to use that value later on. Here is my code so far:
def LabelPlate():
n = nuke.thisNode()
if n != None:
label = n['label'].value()
n['label'].setValue('Plate')
def LabelLook():
name= "Plate"
for node in nuke.allNodes():
if name == node.knob("label").value():
return True
def LabelLookTwo():
name= "Plate"
for node in nuke.allNodes():
if name == node.knob("label").value():
return node.knob("name").value()
def PlateColorspaceSet():
n = LabelLookTwo()
if nuke.toNode("n")["colorspace"].value() == "default (sRGB)":
nuke.toNode("n")["colorspace"].setValue("sRGB")
def LabelQuestion():
if LabelLook() != True:
if nuke.ask('Is this Read your main Plate?'):
LabelPlate()
PlateColorspaceSet()
nuke.addOnUserCreate(LabelQuestion, nodeClass = 'Read')
So order of events:
Bring in Read node
Ask if Read node is your main plate
a. If yes, label node as "Plate", proceed to step 3
b. If no, bring in unlabeled Read node
Change colorspace in node labeled "Plate" from default to an actual value.
So far, I can get the first 2 steps to work. But on step 3, I get
"'NoneType' object has no attribute 'getitem'"
Any ideas why? Is there a better way to get the colorspace value?

I figured out the problem.
nuke.addOnUserCreate is where I was calling the function on the creation of the read node. Problem is, it runs the script before everything exists. So not everything works because not everything is there in Nuke yet, so things, like my variable n = LabelLookTwo(), return as None.
Using addOnCreate instead runs the script after the node and it's defaults have been set and created. So using this, the rest of the script runs exactly as originally written.
Where I found the answer

Related

Database column in a while loop isn't getting changed

So I am changing a value inside my database on my website. I am sure it is getting changed. I am printing the value
computer.directory_response = "example" # not the actual value it's always changing
db.session.commit()
print(computer.directory_response)
I can see the printed value in the console. meanwhile, I have a program that sends a request to /computers/1/ajax-dir. the problem in the code is when I am doing a while loop to check if the value is example (to be sure I just implemented the if statement inside the while loop)
while(computer.directory_response == ""):
if computer.directory_response != "":
break
else:
pass
at the beginning it's empty. Yes. But even when I change the value in the first part of code I showed you it's still in the while loop. I don't understand why it doesn't change I am using flask as a backend language
It seems that you aren't adding the computer to the db.session.
As that's the case you should add this before the db.commit():
db.session.add(computer)

Access an attribute of the same object in two functions running at the same time

Hello i am having a weird issue maybe some one can help,
I start by running 2 different function with the same argument which is an object that is already instantiated :
iotComponent.connectedSensors=sensorList
iotComponent.connectedHUIs=HUIList
Coap = multiprocessing.Process(target=runCoapSync,args=(iotComponent,))
huis = multiprocessing.Process(target=runHuis,args=(iotComponent,))
huis.start()
Coap.start()
then here are both functions :
async def runCoap(iotDevice):
context = await Context.create_client_context()
sensor=iotDevice.connectedSensors[0]
while True:
await asyncio.sleep(1)
sensor.sense()
lightMsg = iotDevice.applicationInterface.createMsg( sensor, iotDevice.communicationProtocol.name)
await iotDevice.communicationProtocol.sendMsg(context,lightMsg,"light")
def runHuis(iotDevice):
print("----------------1---------------")
LCD=iotDevice.connectedHUIs[0]
while True:
LCD.alertHuman(iotDevice.connectedSensors[0].data.value)
in the first function when sensor.sense() is called the value attribute inside data attribute of the sensor is updated.
But in the second function, iotDevice.connectedSensors[0].data.value is always equals to Zero. I find this behavior weird because this is the same object. Moreover if i add a line sensor.sense() in the second function the value gets updated but it is not the same as the value printed in first function.
EDIT 0 :
here is the sense() method :
def sense(self):
pinMode(self.pinNumber, "INPUT")
lightSensorValue = analogRead(self.pinNumber)
self.data.timestamp=str(round(time.time(), 3))
self.data.value=lightSensorValue
If someone as an idea that would be great !
SOLUTION : as said in the accepted answer i tried with threading and it worked like a charm :
Coap = threading.Thread(target=runCoapSync,args=(iotComponent,))
huis = threading.Thread(target=runHuis,args=(iotComponent,))
huis.start()
Coap.start()
See this answer. Essentially what's happening is that your data is "pickled" before being sent to the processes to have work done. When the objects are received, they're unpacked. Therefore, the objects are more cloned than passed around. Therefore, you're actually working with two separate copies of iotComponent, which explains why you can't actually see any change happening on one even though you "know" work is being done. There might be a way to do this, given this. However, it might be better to not use Process, but use Thread instead, see here. The difference is that, according to this, threads are better for I/O-bound operations, which your sensor certainly is.

How to prevent a repeat of a program call within a while loop

I am trying to prevent this switch function from constantly repeating within the probability while loop, i want it to be called once promoting an input and then using the return of that input for each time in the while loop instead of asking every time
Click here to see screenshot of code
(it won't let me add a second picture of the switch function so ill just copy and paste it)
def switch_door():
switch=raw_input("Switch doors?:")
if switch!="y" and switch!="n":
return "Incorrect inputs"
elif switch=='y':
return True
elif switch=='n':
return False
You may set a variable e.g.if_switch=switch_door() in the probability() function before your while loop and pass that variable to your simulation function as a parameter.
Note that you will need to change your simulation definition to e.g. def simulation(doors, if_switch):; you will also need to change these two lines:
if switch_door()==True: to if if_switch==True:
elif switch_door()==False: to simply else:
Now your problem should solved.

Accept optional input at runtime

currently I am writing a robot operating system (ros) node in python. I want to create a while loop which accepts user input on the one hand but is able to continue if no user input is available.
The idea of the following snippet is, that this python-script offers always 'start' or 'stop'. Another node is listening what string gets published. The user should be able to type in 0 or 1 at runtime to toggle the flag.
Here is my python code:
def main():
pub = rospy.Publisher('/start_stop', String, queue_size=10)
rospy.init_node('start_stop', anonymous = True);
rate=rospy.Rate(10) # 10hz
pubStr = "Start"
while not rospy.is_shutdown():
try:
input = raw_input()
if input == "0":
pubStr = "Stop"
elif input == "1":
pubStr = "Start"
except:
rospy.sleep(0.1)
rospy.loginfo(pubStr)
pub.publish(pubStr)
rate.sleep()
if __name__ == '__main__':
main();
In case you don't find a way to do this directly in Python, an easy solution would be to move the user input to another node:
The first node (let's call it "user input node") looks basically like the code you posted, but publishes directly the value of input to a topic /user_input.
The second node ("start/stop node") publishes the "Start"/"Stop" in a loop, depending on the flag. This flag is set by a callback listening to /user_input.
This way, the start/stop node always publishes depending on the user input, without waiting for new input, while the user can always change the flag by sending a new value via the user input node.
This solution would be easy to implement but has the downside of an additional node in your setup.

How to make a WX Python For Loop for updating a series of text boxes

I was asked to make a Subnet Scanner App for a summer class. The app is complete but its ugly as sin because the code is extremely lengthy.
It is lengthy because the app requirements called for a gui with 8 ip addresses on them and whether or not there had been a return at that IP.
Since it required a GUI, I created a series of static text fields to represent the individual IPs it was scanning.
That app has a scanner button and once that button is pressed and the scan resolves, it goes to update the board with the appropriate values.
To make it easier, I set up a global placeholder value to just increment by 8 each time I needed to see a new set.
So heres what I'd like to do
I'd like to make a for loop that updates the static text of each of the eight fields without having to write each one out individually.
What I have that works is below:
self.XValue0.SetLabel(str(placeholder))
self.XValue1.SetLabel(str(placeholder1))
self.XValue2.SetLabel(str(placeholder2))
self.XValue3.SetLabel(str(placeholder3))
self.XValue4.SetLabel(str(placeholder4))
self.XValue5.SetLabel(str(placeholder5))
self.XValue6.SetLabel(str(placeholder6))
self.XValue7.SetLabel(str(placeholder7))
XValue is in reference to 192.168.1.X where X is the value being changed since the first part of the Subnet stays the same anyway.
The placeholder with a number is in reference to a global value that adds the number (1-7) to the placeholder to populate the field.
For instance, if the GUI starts at 192.168.1.0, it would populate down to 192.168.1.7 and display the yes or no for all positions in that range.
What I would like to do is something more similar to this:
for x in range(0,7):
PlaceholderValue = str(placeholder + x)
XValue = 'XValue' + PlaceholderValue
self.XValue.setLabel(PlaceholderValue)
However, when I do that, the console gives me an error saying it can't find "XValue".
My question is this. Is there a way to make that for loop work the way I want it to, or is it by necessity the longer code based on how I wrote it. Thanks all. Sorry for the long post, its my first question after lurking for ages. Please let me know if you all need anymore info.
When you create your static text objects, save the references in a list as well as (or instead of) the XValue attributes.
self.XValues = []
for x in range(8):
self.XValues.append(wx.StaticText(...))
then it makes it much easier to loop over and update later
for i, xvalue in enumerate(self.XValues):
xvalue.SetLabel(placeholder + i)
You can still access the labels individually too, for instance to access XValue4 you had before, you can do self.XValues[4].
Also, you could have done it like you tried, except you need to use getattr to dynamically get attributes of objects, but you're better off storing the labels in a list.
for x in range(8):
PlaceholderValue = str(placeholder + x)
XValue = 'XValue' + PlaceholderValue
getattr(self, XValue).setLabel(PlaceholderValue)

Categories