Sikulli: Passing Regions to setROI() function - python

Lets say that in Sikulli I create a region called myRegion and pass it to setROI().Would using find(pictureIWantToFind) be just as fast as if I didn't use setROI() and instead called find(myRegion.inside().exists(pictureIWantToFind))?
Also, setROI() will continue to use that region of interest until you tell it otherwise such as with setROI(SCREEN)?

As you have it stated, yes, I believe that using SetROI() would be slightly faster than find(myRegion.inside().exists(PictureYouWantToFind)--just marginally.
-BUT-
Because the find() operation is a method of the Region class, instead of calling find(myRegion.inside().exists(myPic)), you can accomplish the same thing a little more simply this way: myRegion.find(myPic)
The default ROI is the whole screen referenced with the reserve word "SCREEN". So, find(myPic) is the same as SCREEN.find(myPic). Passing myRegion to setROI(), as in setROI(myRegion), redefines SCREEN so that now SCREEN = myRegion. If you choose to use setROI() be aware--all following Region operations (such as wait() or exists()) would act on myRegion and not on the whole screen, until you redefine it as such, as per this answer in the Sikuli forums.
In sum, myRegion.find(myPic) will allow you to search the smaller ROI, without renaming SCREEN.

Related

LLDB Python scripting create variable

I am using LLDB Python scripting support to add custom Variable Formatting for a complex C++ class type in XCode.
This is working well for simple situations, but I have hit a wall when I need to call a method which uses a pass-by-reference parameter, which it populates with results. This would require me to create a variable to pass here, but I can't find a way to do this?
I have tried using the target's CreateValueFromData method, as below, but this doesn't seem to work.
import lldb
def MyClass(valobj, internal_dict):
class2_type = valobj.target.FindFirstType('class2')
process = valobj.process
class2Data = [0]
data = lldb.SBData.CreateDataFromUInt32Array(process.GetByteOrder(), process.GetAddressByteSize(), class2Data)
valobj.target.CreateValueFromData("testClass2", data, class2_type)
valobj.EvaluateExpression("getType(testClass2)")
class2Val = valobj.frame.FindVariable("testClass2")
if not class2Val.error.success:
return class2Val.error.description
return class2Val.GetValueAsUnsigned()
Is there some way to be able to achieve what I'm trying to do?
SBValue names are just labels for the SBValue, they aren't guaranteed to exist as symbols in the target. For instance if the value you are formatting is an ivar of some other object, it's name will be the ivar name... And lldb does not inject new SBValue's names into the symbol table - that would end up causing lots of name collisions. So they don't exist in the namespace the expression evaluator queries when looking up names.
If the variable you are formatting is a pointer, you can get the pointer value and cons up an expression that casts the pointer value to the appropriate type for your getType function, and pass that to your function. If the value is not a pointer, you can still use SBValue.AddressOf to get the memory location of the value. If the value exists only in lldb (AddressOf will return an invalid address) then you would have to push it to the target with SBProcess.AllocateMemory/WriteMemory, but that should only happen if you have another data formatter that makes these objects out of whole cloth for its own purposes.
It's better not to call functions in formatters if you can help it. But if you really must call a function in your data formatter, you should to do that judiciously.
They can cause performance problems (if you have an array of 100 elements of this type, your formatter will require 100 function calls in the target to render the array... That's 200 context switches between your process and the debugger, plus a bunch of memory reads and writes) for every step operation.
Also, since you can't ensure that the data in your value is correct (it might represent a variable that has not been initialized yet, or already deallocated) you either need to have your function handle bad data, or at least be prepared for the expression to crash. lldb can clean up the stack and suppress the exception from crashes, but it can't undo any side-effects the expression might have had before crashing.
For instance, if the function you called took some lock before crashing that it was expecting to release on the way out, your formatter will damage the state of the program. So you have to be careful what you call...
And by default, EvaluateExpression will allow all threads to run so that expressions don't deadlock against a lock held by another thread. You probably don't want that to happen, since that means looking at the locals of one thread will "change" the state of another thread. So you really should only call functions you are sure don't take locks. And use the version of EvaluateExpression that takes an SBExpressionOption, in which you set the SBExpressionOptions.StopOthers to True, and SetTryAllThreads to False.

Python Kivy, need help to understanding a strange technique. self._object.clear() etc

I feel guilty for asking question I can not properly name because I can not name the pattern used in the code.
There is a code on github I'm trying to understand and failing to do so.
https://github.com/kivy-garden/speedmeter/blob/master/kivy_garden/speedmeter/init.py
Pattern I don't understand is in lines 128,129 and 181, 182 and many other places.
Big picture is.
There a class
class MyClassName(Widget):
there are methods e.g.
def _draw_this_and_that(self):
self._someName.clear()
add = self._someName.add
add(Color(rgba=get_color_from_hex(color)))
This "_someName" found in whole code only in those 2 places as my code sample.
I understand that
add = self._someName.add
creates function "add" but why that is needed? why not calling
self._someName.add
instead?
I guess that
self._someName.clear()
does erase whatever was added to "_someName", right?
I completely do not understand how
add(Color(rgba=get_color_from_hex(color)))
does it job (but it does) and then whatever is drawn will be with that color.
Do I guess it right that if I need to change color (if some condition met) then I could just add different color?
add(Color(rgba=get_color_from_hex(different_color)))
and don't stress that adding will cause memory leak because
self._someName.clear()
will take care of it?
I never seen such pattern. I'd be very happy if someone could explain how it works and why.
Thank you in advance!
The _somenameIG are canvas instruction groups that are created in the __init__() method:
add = self.canvas.add
for instructionGroupName in _ig:
ig = InstructionGroup()
setattr(self, '_%sIG' % instructionGroupName, ig)
add(ig)
So, the self._someName.clear() is clearing a canvas instruction group, and the add() method adds instructions to the group.
In addition to the other answer I would like to address the following:
Pattern I don't understand is in lines 128,129 and...
According to its documentation the attr. sectors in line 130 is a list of alternating values and colors a copy of which is stored locally by l and then the color value(s) is(are) passed to the InstructionGroup. Since it is used as a redrawing mechanism, the instruction groups are removed from canvas by the method clear before drawing again.
creates function "add" but why that is needed? why not calling...
This is done mainly to prevent the re-evaluation process.

call a variable from a string

I am working on a python hangman game and have my graphics based on a variable, lives, so when you have 1 lives, the corresponding picture appears. i put my graphics into definitions and want to call them from that. Here's my code so far:
if life== 1:
graphics1()
if life==2:
graphics2()
if life==3:
graphics3()
if life==4:
graphics4()
if life==5:
graphics5()
if life==6:
graphics6()
if life==7:
graphics7()
if life==8:
graphics8()
if life==9:
graphics9()
if life==10:
graphics10()
and so on, so is there a command which would allow me to shorten this to one or two lines?
I highly discourage it, but it could be accomplished by doing:
globals()["graphics" + str(life)]()
However there's most definitely a better solution. Presuming that the contents of each graphics*() is similar to one another.
Well, multiple if branches can be expressed via lookup table as
lt = {"1":graphics1(), "2":graphics2()}
and so on.
Accès to if branch via (and provide a fallback function)
lt.get(life, graphics1())
If you want to create the dict dynamically use the dict comprehension and use the getattr to get the function.
Or, as stated above, generalize the function graphics passing the "ith" param to it.

Why are python generator frames' (gi_frame) f_back attribute always none?

The title is pretty self-explanatory. I'm doing something like:
gen = obj #some generator instance running
frame = obj.gi_frame
prevframe = frame.f_back
But I always get None for prevframe. Why is this the case. Also, is there some workaround for this?
CONTEXT: I'm trying to write a simple call stack method to determine what called a particular function. I'm using twisted manhole and telnetting into a running process, where I then execute these commands but I can't seem to access the previous frames.
To the best of my knowledge, this is both intentional and cannot be worked around. The code in cpython responsible for it is here, which indicates that the reference to the previous frame is broken as soon as the generator yields (or excepts out) in order to prevent issues with reference counting. It also appears that the intended behavior is that the generator's previous frame is swapped out every time it's entered, so while it's not running, the notion of "the parent frame" doesn't make much sense.
The correct way to do this, at least in the post-mortem context, is to use traceback objects, which have their frame lists linked in the reverse order, tb_next instead of f_back.

How to apply a modifier in Python, creating a new mesh?

Let's say I have a bpy.types.Object containing a bpy.types.Mesh data field; how can I apply one of the modifiers associated with the object, in order to obtain a NEW bpy.types.Mesh, possibly contained within a NEW bpy.types.Object, thus leaving the original scene unchaged?
I'm interested in applying the EdgeSplit modifier right before exporting vertex data to my custom format; the reason why I want to do this is to have Blender automatically and transparently duplicate the vertices shared by two faces with very different orientations.
I suppose you're using the 2.6 API.
bpy.ops.object.modifier_apply (modifier='EdgeSplit')
...applies to the currently active object its Edge Split modifier. Note that it's object.modifier_apply (...)
You can use
bpy.context.scene.objects.active = my_object
to set the active object. Note that it's objects.active.
Also, check the modifier_apply docs. Lot's of stuff you can only do with bpy.ops.*.
EDIT: Just saw you need a new (presumably temporary) mesh object. Just do
bpy.ops.object.duplicate()
after you set the active object and the new active object then becomes the duplicate (it retains any added modifier; if it was an object named 'Cube', it duplicates it, makes it active and names it 'Cube.001') to which you can then apply the modifier. Hope this was clear enough :)
EDIT: Note, that bpy.ops.object.duplicate() uses not active object, but selected. To ensure the correct object is selected and duplicated do this
bpy.ops.object.select_all(action = 'DESELECT')
object.select = True
There is another way, which seems better suited for custom exporters: Call the to_mesh method on the object you want to export. It gives you a copy of the object's mesh with all the modifiers applied. Use it like this:
mesh = your_object.to_mesh(scene = bpy.context.scene, apply_modifiers = True, settings = 'PREVIEW')
Then use the returned mesh to write any data you need into your custom format. The original object (including it's data) will stay unchanged and the returned mesh can be discarded after the export is finished.
Check the Blender Python API Docs for more info.
There is one possible issue with this method. I'm not sure you can use it to apply only one specific modifier, if you have more than one defined. It seems to apply all of them, so it might not be useful in your case.

Categories