Use mouse in different routines causes a long delay

**Win10:
PsychoPy version (e.g. 1.85.4):

Hi! I’m working in a program for an experiment about choice (in pigeons). The animal has forced and choice trials. In a choice trial the animal can choose between two alternatives -A and B- (one ‘click’), if the animal choose A, two different images can appear (one each trial) for 30s (images have a different probability of occurrence and a different probability of reinforcement). The same is true for alternative B.
Because what happen is conditional to the initial choice, I attached an excel file with all the conditions. So, I have 4 routines after the choice routine (one per image).

Depending of the choice and the probability, the program skip the other routines. For instance: if the animal chooses B, and it’s selected S4 (routine in the picture), the program skip Splus, Sminus, and S3 routines. So far so good.

I need to record all the pecks of the animal during the images (‘clicking’ for the program). The code added to that works just fine. The problem is that, when I added a mouse in each routine (Splus, Sminus, S3 and S4) there is a long delay (around 10s) between the presentation of routine S3 or S4 and the next routine (foodreward). It does not happen if the image (and therefore routine) presented is Splus or Sminus.

I though it was the code to register clicks, but when I remove it, I still have the delay. But for instance, if I remove the mouse in S3, the delay after S3 and foodreward disappeares.

I don’t know how to fix it :frowning:

Well done, it seems like you have most of your trial procedure implemented. To find the cause of this unexpected delay, though, we’ll probably need to see your Builder .psyexp file, to be able to see the settings of your various mouse components and the effects of the custom code.

blockSelection.xlsx (8.4 KB)
CH IL1 IL2 RH sub_opt_choice.xlsx (9.5 KB)
sub_opt_TEST.psyexp (101.1 KB)
SV tl1.xlsx (9.9 KB)
TV

Hi,

Sorry for the long delay. From only a quick look at your code, I can’t pretend to understand all of the logic, but would make a recommendation that you remove anything like this from your code components:

while mouseS3.isPressedIn(S3_) and not (mouseS3.isPressedIn(background_5)):
        continue

In general Python programming terms, a tight loop like this will completely consume your CPU, strangling any other processes. This can cause unexpected delays as other processes (outside PsychoPy) finally jump in and wrest control of the CPU from you. The normal Builder drawing loop (of effectively pausing for a few milliseconds on every screen refresh) allows PsychoPy to be a good citizen and give other processes some access to the CPU.

So the consequences of these sorts of loop are two-fold:

  • you cause bottlenecks for other programs, which can then cause poor performance as they try to compete.
  • you’re also stopping Builder’s natural drawing cycle. If the conditions of your test aren’t met for a while, your effectively pausing all drawing and anything else other than this specific check for mouse presses. This means everything else that Builder normally intends to do on a frequenct cycle (checking the keyboard, redrawing the screen, checking the onset and offset time of stimuli, and so on, is being put on ice.

As a general rule, avoid putting any indefinite loops or pauses in Builder code components, as they disrupt Builder’s inherent event/draw loop cycle.

But I guess that loop is there for some reason, so you need to restructure your code to achieve the same result. Again, I’m not too sure of the required logic here, so can’t give specific advice.

Hi Michael!
Thank you for the advice! But the problem persist even when I remove all the response-related code (I was of course just testing but I actually need to record data). So, I don’t know what the problem can be.

I’m still a bit puzzled by this myself, and just realised that I don’t really understand how Builder decides when a component is finished even in normal circumstances. Some points that are unlikely related to your issues, but anyway:

  • I love looking at other people’s experiments and finding a routine called Put_bird_in_box.
  • You define circle stimuli with 999999 vertices. Nothing comes for free: these stimuli with nearly a million points are massive overkill in terms of memory required, to achieve no real advantage (i.e. the pixels on your screen have a finite size. If a circle with 100 vertices still has visible corners, then bump it up to 200, say, rather than orders of magnitude more vertices than can physically be drawn on the pixel grid.
  • I’m not sure why you call thisExp.nextEntry(). Calls to nextEntry() shouldn’t really be necessary in Builder code, as it is taking care of all of your loops and trials for you.

Those points above probably won’t fix anything related to this particular issue. So how about you post a version of your .psyexp file that works in every respect except for this mystery delay, but has had the (potentially) infinite loops removed from your code? That might help to narrow things down.

Hi!
I did a simpler version checking the number of vertices and deleting most of the saving data code. I even deleted the pictures. So far, the only thing that deletes the delay in the choice loop is when I delete the mouses.

sub_opt_TEST2.psyexp (80.2 KB)

-I call thisExp.Entry() because that is what is suggested in the basic manual (psychopy.data - functions for storing/saving/analysing data — PsychoPy v2021.2)-

EDIT: Here is a version with only choice trials. Still the same problem
sub_opt_TESTONLYCHOICE.psyexp (70.9 KB)

Hi Valeria, sorry for the delay, I’ve been on holiday.

Is this still a live issue? If so, I’ll look at your files above.

That is oriented for people coding their own experiments from scratch (and even then, nextEntry() isn’t usually necessary). You shouldn’t need to make this call at all in a Builder-generated experiment (and it might even cause undesired side effects).

Yes, still is! In the meantime I realized the delay is equivalent to the duration of all four routines. It does not make any sense to me what they seem to be ‘active’ even after the ‘skip routine’ instruction was on effect.

Thanks for the note on Exp.Entry()!

That observation makes all the difference. I’ve only just realised that you are using a very old PsychoPy release. The ability to use continueRoutine = False in the “begin routine” tab was only added about the time of that version, so you might not have that capacity.

Can you push the “compile script” button in the toolbar and search for the line:

# ------Prepare to start Routine "S_plus"-------

and paste in a message here everything between that line and this one:

# -------Start Routine "S_plus"-------

This wouldn’t explain why the code did work before, but eliminating this possibility would be useful. If it isn’t the problem, then we need to debug elsewhere.

Lastly, that “each frame” code still includes lines like this in multiple places:

while (mouseA.isPressedIn(sub_area)):
        continue

I think as discussed above, this sort of code really needs to be deleted, as it will interfere with Builder’s timing. If it serves a particular function, please describe it, and we can discuss how to implement it without holding up Builder’s drawing cycle.

I’m so sorry for the delay. For some reason this time I did not get an email with your answer.

Here it is the code


# ------Prepare to start Routine "S_plus"-------
    t = 0
    S_plusClock.reset()  # clock
    frameN = -1
    continueRoutine = True
    routineTimer.add(3.000000)
    # update component parameters for each repeat
    Splus.setPos(sublocation)
    if skip_S_plus:
        continueRoutine = False
    # setup some python lists for storing info about the mouseA_5
    # keep track of which components have finished
    S_plusComponents = [Splus, background_3, mouseA_5]
    for thisComponent in S_plusComponents:
        if hasattr(thisComponent, 'status'):
            thisComponent.status = NOT_STARTED
    
    # -------Start Routine "S_plus"-------

Also, I am using a touch screen (the pigeon peck the pictures). So, If I don’t use:

while (mouseA.isPressedIn(sub_area)):
continue

then It registers as different pecks a long press to the touchscreen. That’s what I found online to avoid that problem; but if you have a better solution I would love to implement it.

Again, I apologize for my delay.
Thank you for your help!

Hi,

Your code shows that you are using a version which should respond to continueRoutine properly (but I think you’ve mentioned that it sometimes works OK anyway, so that was maybe a blind alley).

However, it would still be worth updating to the latest version of PsychoPy: the mouse component has changed to allow the detection of mouse presses in certain stimuli (i.e. it now has a field called “clickable stimuli”, where you just list the names of the stimuli that are valid click targets). This means that you can allow PsychoPy to do some of the hard work for you. It also seems to handle responding just once to a mouse click. i.e. using the latest version of PsychoPy, the code that gets generated from your .psyexp file probably looks different to me than it does for you.

I’m still concerned about the lines like:

while (mouseA.isPressedIn(sub_area)):
        continue

They could conceivably allow the routine to last beyond the specified 3 seconds if the pigeon keeps pressing the target. But also, I’m not sure what it achieves. Your code should just trigger on the initial click, and then, by setting continueRoutine to False, it should immediately end. There should be no need to guard against any other detections, as this “every frame” code shouldn’t get the chance to run again on this trial. Or is it important to you to end the trial after the press is completed, rather than when it is initially detected?

So, some debugging: In the “End routine” tab of the code on the “Choice” routine, put something like:

print('### Trial: ' + str(Choice1.thisN))
# these print statements might need adjusting if you are using Python 2:
print('skip_S_plus: ', skip_S_plus)
print('skip_S_minus: ', skip_S_minus)
print('skip_S3: ', skip_S3)
print('skip_S4: ', skip_S4)

Do the results fit with what you expect?

If that doesn’t give any obvious hints, then you should do the same in you “each frame” code. i.e. insert some statements to allow you to check that the logic is being followed as you intend. Making print statements up to, say, 60 times a second can be burdensome though and lead to backlogs, so for code in that tab, you might find that sending messages to the experiment log might be more practical. See:

https://www.psychopy.org/coder/codeLogging.html

and make sure that your experiment settings are set to record the level of log messages you are generating.

Hi!

It took me a while to update the task to the new version 3.0.3 and initially I had the same problem. But at the end, deleting the code and using just the alternative that the mouse component has now was enough to fix the problem.

I am not completely sure where the program was stuck, but It seems that those while loops to register clicks were slowing down the program.

Thank you so much for your help and patience!

Val

1 Like