[open] other ways to draw items on canvas?
Hello again!
I'm in the process of optimizing my opensesame script for a faster display with a Surface3 tablet (with atom CPU at 2.4Ghz and IntelHD graphics)
What I see is that it's very slow while using the various canvas functions, such as copy() and show() or simply adding a rect() or image() to an already existing canvas.
So I was wondering if there is another way to simply draw rectangles/ellipse/whatever to a sketchpad withouth redrawing the screen.
here is a piece of code I am running using the expyriment backend:
from math import sqrt coordsAge= [(-800,-365),(-800,-282),(-800,-193),(-800,-109),(-800,-22),(-800,63)] coordsAgeErr=[50,20] #pixels massimi di errore rispetto al centro del rettangolo ellipseAge=[(-901,-395,167,52),(-901,-310,167,52),(-901,-225,167,52),(-901,-145,167,52),(-901,-59,167,52),(-901,23,167,52)] colorAge="#eaffff" x=y=w=h=0 previousAgeIndex=-1 sketchpadname = "sketchInfo%s" % exp.get('languageSpoken') # name of the sketchpad in which you present your picture no_click=True print "--before copying sketchpad: %d" % self.experiment.time() cnvs_Info.copy(exp.items[sketchpadname].canvas) #canvas is defined in the PRE section of the script print "--after copying sketchpad: %d," % (self.experiment.time()) while no_click: print "---------------------------------------running WhileLoop time=%d --------------------------------------" % self.experiment.time() # wait for buttonpress click,clickpos,clicktime = my_mouse.get_click(timeout=5000) # if button is clicked... if click != None: print "mouse_CLICKcoord: %d,%d" % (clickpos[0]-xc,clickpos[1]-yc) # now we check if the click was inside a column and later if iw's inside a row # we check if we have clicked into a specific column +/- some jitter # if yes we check if we have clicked inside a specific row +/- some jitter # if no then we have clicked outside and we loop again for another mouseClick if abs(clickpos[0]-xc-coordsAge[0][0]) <= coordsAgeErr[0] : print "let's check if we are in Age %d" % self.experiment.time() for indexOfAge,(xvar,yvar) in enumerate(coordsAge): #errX= abs(clickpos[0]-xc-xvar) errY= abs(clickpos[1]-yc-yvar) if errY<=coordsAgeErr[1]: print "-----> clicked Age's item #%d <-----------------" % indexOfAge #now we check if we have already selected an item and maybe we want to click to another inside the same column # so let's simply draw another ellipse with the same background to hide the previous one if previousAgeIndex >=0: x,y,w,h=ellipseAge[previousAgeIndex] print "---- time before deleting the previous ellipse %d" % self.experiment.time() cnvs_Info.ellipse(x+xc,y+yc,w,h,color=colorAge,penwidth=5) print "---- time after deleting the previous ellipse %d" % self.experiment.time() previousAgeIndex=indexOfAge x,y,w,h=ellipseAge[indexOfAge] #coords of an ellipse around the Age's item (coords are predefined at beginning of script) print "time before inserting a new ellipse %d" % self.experiment.time() cnvs_Info.ellipse(x+xc,y+yc,w,h,color='red',penwidth=5) print "time before inserting a new ellipse %d" % self.experiment.time() cnvs_Info.show() print "---- time after showing the updated canvas %d" % self.experiment.time() foundAge=True break #let's go out from the FOR loop and maybe to another While loop print "time needed for loop FORAge %d" % self.experiment.time() else: print "we did'nt click inside any columns, let's wait for another click time: %d" % self.experiment.time() else: #no click within a time, so let's set some vars for a timeout popup no_click =False exp.set('timeout_occurred','yes')
So basically I have a sketchpad with many texts inside. When a subject click over a text an ellipse is drawn to select the choice. This step of selecting/drawing takes 700ms on this surface while on PC takes 350ms. The most of the time is taken by the canvas.show().
Disabling openGL the script goes faster a lot, but I don;t know what I am missing. I need precision in other task where the user has to click on image-button over a sketchpad.
thanks!
Comments
Hell0 elaci0,
What would make your experiment the fastest is to create all possible canvases beforehand in the prepare phase of an inline_script. In the run phase, you could put some if-statements, saying e.g. "if mouseresponse_coordinate == this: show that_canvas". The more you can possibly put in the prepare phase, the better - the idea is that everything will be ready when you actually run the experiment.
Good luck!
CHeers,
Josh
Yes, but many vars are assigned at runtime, such those inside a Block (for the running trial) or in my case when the user clicks into a sketchpad and unfortunately I cannot prepare all the cavnas in the PRE stage because I have 25! combinations.
thanks!
Even if you have 25 combinations, wouldn't it be possible to create all canvases in a for-loop for instance? If there is any logic in the variance among canvases you could create all possible combinations in a loop. Although I'll admit it becomes a bit more technical and requires some programming
Cheers,
Josh
Ehm no, it was 25! all possible combinations.
it's a kind of form but I needed I timeout, so I had to draw everything on a sketchpad. The sketchpad is kind of static, same text but with updated selections.
then I have 25 text divided in categories, one could choose one item per category and STILL see what had already choosen, and in case change idea and choose another item inside the category.
Now this works fine except that each canvas.show() rquires times to redraw everything. Using e-Prime, for example, I would have been able to draw items directly on the sketchapd.
Hi,
To answer your actual question, no, there is no other way of drawing onto a
canvas
(except of course using asketchpad
, but that one won't by of any help for you).Therefore, you have to try to optimize your drawings as much as possible. I have to admit, I haven't yet understand completely what exactly it is that you're trying to do, but if some of your drawings are done at runtime, it is still possible, but a lot more difficult to "outsource" some parts to the
prepare phase
.Btw. Here some information on OpenGL: http://osdoc.cogsci.nl/back-ends/opengl/
Have you checked the timings in the other parts of your experiment? If they're also fine there (when OpenGL is disabled), you should be good, right?
Eduard
@Josh
I tried your suggestion of drawing all my RECTs and TEXTs into a canvas one by one (into a PRE section) but this part takes 20 seconds so it's not good at all for my purposes (also because I have three parts likes this).
I tried moving all this PRE stuff into another inlineScript at the beginning of my experiment and tried to call that canvas later in my loop/sequence, but it's empty, perhaps I cannot save a canvas like a global variable.
@Eduard
One of the things I'm trying to do is to draw a sketchpad on the screen filled with many TEXT divided by category. During the experiment the subject clicks on some of this text and a ELLIPSE is drawn to "highlight" his choice. The subject can always change idea and click on another item, so the previous ELLIPSE (in the same category) has to be "cleared".
So I was looking for a solution for this problem because redrawing the screen with a lot of RECTS,TEXT,ELLIPSES takes longer than I expected. Moreover, these sketchapds (one for each languages) are kept inside a sequence, so if the user does not respond within a certain time, the sequence is repeated; so you may understand the frustaration of waiting so long because the PRE fase takes too much time (and I have only 3 sketchs, 2 inlines)
At the moment, my last idea which I am trying with, is to have a sketchpad with a PNG (the image is a 'snapshot' of the sketchpad filled with RECTs/TEXTs) and at runtime I will draw only ELLIPSEs when needed. I'm attaching images of my sketchpad, with and without "user's choice"
This is really odd. None of the operations (drawing ellipses, text or rectangles) should take that much time. 20seconds is really humongous. Would you mind sharing your experiment with us? You could upload it somewhere and post the link here. I'd like to have a look on it, if you don't object.
I start to understand your design better now (not fully though). Are the list of words the same for one trial? That is, for one iteration of a
sequence
? If so, you could draw all this static stuff only once and use this canvas as a starting point for all the dynamic updating of the participants' choice. As far as I see, the maximum number of drawing operation that need to be done during runtime would then be five, or do I miss anything?Sorry if I still don't get it...
Eduard
I don't object at all.. I'm only shy because of errors on programming, which is not my main job in my life :P
So I extracted a piece (loop) from my whole experiment. The piece of code includes some of the possible solutions to my problem. Inside I put also some note to describe better the task.
Here is the link to download it with the pool included
http://www.filedropper.com/demographichpartopensesametar
and here is the code:
http://pastebin.com/sGssDLks
again, forgive me for any programing error, I''m totally new to python and opensesame :P
thanks!
Hi Elacio,
Your idea of making everything in an inline_script at the beginning of the experiment was a good one. But you have to make sure to call your canvas something like "exp.canvas", i.e. start with "exp.". This makes the item available everywhere in your experiment. Further, the idea would be that you have multiple canvases - they cannot have the same name. During a trial, you would then have an inline script that says: "if this happens, display this canvas, if that happens, display that canvas", etc. If there is alot of response possiblities (such as mouse click coordinates) this can be tedious; but again the canvases can contain coordinate values in their names, so that a response can automatically refer to a specific canvas. This is the only way I see to make your experiment really really fast at least.
Cheers,
Josh
Hi Elacio,
Unfortunately, I can't open your experiment and neither can I paste your code into
opensesame
. (Just from looking at it, I'm not able so the structure of your experiment). Not sure what exactly is wrong, but could you double check that you upload a usable file?OpenSesame
throws a file format error.Thanks,
Eduard