Response Box vs Target Box HELP! :)

Hi all,

I am creating an experiment that includes an ‘image’ witha target inside of it, and it is up to the participant to look at the image, identify the target, inidicate using the keyboard whether the target is present (Y = yes, N = no), then draw a box around the target to show where they think it is.

I seem to be having some isses with the coding. This is my current error code.

####### Running: /Users/amylou/Desktop/PsychoPy IIT/untitled_lastrun.py ########
5240.0064 INFO Loaded monitor calibration from [‘2025_03_10 15:05’]
5240.0248 INFO Loaded monitor calibration from [‘2025_03_10 15:05’]
2026-03-23 16:23:01.472 python[28448:4160181] ApplePersistenceIgnoreState: Existing state will not be touched. New state will be written to /var/folders/m9/h3_x_j9d1c55ly8f360sb9wh0000gn/T/org.opensciencetools.psychopy.savedState
2026-03-23 16:23:04.587 python[28448:4160181] Warning: Expected min height of view: (<NSPopoverTouchBarItemButton: 0x7f8b065f4970>) to be less than or equal to 30 but got a height of 32.000000. This error will be logged once per view in violation.
2026-03-23 16:23:04.587 python[28448:4160181] Warning: Expected min height of view: (<NSButton: 0x7f8b063e6bd0>) to be less than or equal to 30 but got a height of 32.000000. This error will be logged once per view in violation.
2026-03-23 16:23:04.588 python[28448:4160181] Warning: Expected min height of view: (<NSPopoverTouchBarItemButton: 0x7f8b0618f340>) to be less than or equal to 30 but got a height of 32.000000. This error will be logged once per view in violation.
2026-03-23 16:23:04.589 python[28448:4160181] Warning: Expected min height of view: (<NSPopoverTouchBarItemButton: 0x7f8b12307080>) to be less than or equal to 30 but got a height of 32.000000. This error will be logged once per view in violation.
8.3921 WARNING Couldn’t measure a consistent frame rate!
Traceback (most recent call last):

  • Is your graphics card set to sync to vertical blank?
  • Are you running other processes on your computer?

0.0380 WARNING t of last frame was 20.93ms (=1/47)
1.5097 WARNING t of last frame was 200.33ms (=1/4)
2.7496 WARNING Stopping key buffers but this could be dangerous ifother keyboards rely on the same.
2.7497 WARNING Stopping key buffers but this could be dangerous ifother keyboards rely on the same.
2.7498 WARNING Stopping key buffers but this could be dangerous ifother keyboards rely on the same.
File “/Users/amylou/Desktop/PsychoPy IIT/untitled_lastrun.py”, line 1484, in
run(
File “/Users/amylou/Desktop/PsychoPy IIT/untitled_lastrun.py”, line 966, in run
respBox.opacity = 0
NameError: name ‘respBox’ is not defined
################ Experiment ended with exit code 1 [pid:28448] #################

I will also include the code for the target and response boxes too

Begin Experiment

=== TRUE TARGET BOX ===

target_x = 0.120
target_y = 0.345
target_w = 0.402
target_h = 0.454

Only require box drawing if participant said “yes”

needBox = (correctAns.keys == ‘y’)

Track drag state

dragging = False
boxFinished = False
startX, startY = None, None
endX, endY = None, None

Default drawn box values

drawn_x = None
drawn_y = None
drawn_w = None
drawn_h = None

Default scoring values

localisationCorrect = None
overlapArea = 0
overlapPropTarget = 0

Hide the response box at first

respBox.opacity = 0
respBox.size = (0.001, 0.001)
respBox.pos = (0, 0)

If the participant said “no”, skip this routine immediately

if not needBox:
continueRoutine = False

EACH FRAME

Keep debug target box aligned (only matters if you made it visible)

targetBox.pos = (target_x, target_y)
targetBox.size = (target_w, target_h)

Current mouse position and buttons

mousePos = boxMouse.getPos()
buttons = boxMouse.getPressed()

Start drawing when left mouse button is first pressed

if needBox and buttons[0] and not dragging and not boxFinished:
dragging = True
startX, startY = mousePos

While dragging, update the visible response rectangle

if dragging and buttons[0]:
currentX, currentY = mousePos

drawn_x = (startX + currentX) / 2.0
drawn_y = (startY + currentY) / 2.0
drawn_w = abs(currentX - startX)
drawn_h = abs(currentY - startY)

respBox.pos = (drawn_x, drawn_y)
respBox.size = (max(drawn_w, 0.001), max(drawn_h, 0.001))
respBox.opacity = 1

When mouse is released, finalise box and score it

if dragging and not buttons[0] and not boxFinished:
dragging = False
boxFinished = True

endX, endY = mousePos

drawn_x = (startX + endX) / 2.0
drawn_y = (startY + endY) / 2.0
drawn_w = abs(endX - startX)
drawn_h = abs(endY - startY)

# Prevent zero-size boxes causing odd scoring
drawn_w = max(drawn_w, 0.001)
drawn_h = max(drawn_h, 0.001)

# Update visible response box one last time
respBox.pos = (drawn_x, drawn_y)
respBox.size = (drawn_w, drawn_h)
respBox.opacity = 1

# Edge coordinates of participant's drawn box
drawn_left = drawn_x - drawn_w / 2.0
drawn_right = drawn_x + drawn_w / 2.0
drawn_bottom = drawn_y - drawn_h / 2.0
drawn_top = drawn_y + drawn_h / 2.0

# Edge coordinates of true target box
target_left = target_x - target_w / 2.0
target_right = target_x + target_w / 2.0
target_bottom = target_y - target_h / 2.0
target_top = target_y + target_h / 2.0

# Compute overlap rectangle
overlap_w = max(0, min(drawn_right, target_right) - max(drawn_left, target_left))
overlap_h = max(0, min(drawn_top, target_top) - max(drawn_bottom, target_bottom))
overlapArea = overlap_w * overlap_h

# Areas
targetArea = target_w * target_h
drawnArea = drawn_w * drawn_h

# Proportion of the TRUE target covered by participant box
if targetArea > 0:
    overlapPropTarget = overlapArea / targetArea
else:
    overlapPropTarget = 0

# Proportion of participant's box that overlaps the target
if drawnArea > 0:
    overlapPropDrawn = overlapArea / drawnArea
else:
    overlapPropDrawn = 0

# Scoring rule:
# correct if participant box covers at least 10% of true target area
localisationCorrect = int(overlapPropTarget >= 0.10)

# End routine once the box is completed
continueRoutine = False

END ROUTINE

Save box data

thisExp.addData(‘needBox’, needBox)
thisExp.addData(‘drawn_x’, drawn_x)
thisExp.addData(‘drawn_y’, drawn_y)
thisExp.addData(‘drawn_w’, drawn_w)
thisExp.addData(‘drawn_h’, drawn_h)
thisExp.addData(‘overlapArea’, overlapArea)
thisExp.addData(‘overlapPropTarget’, overlapPropTarget)
thisExp.addData(‘localisationCorrect’, localisationCorrect)

Detection score

if decisionResp.keys is not None:
detectionCorrect = int(decisionResp.keys == correctAns)
else:
detectionCorrect = 0

thisExp.addData(‘detectionCorrect’, detectionCorrect)

Overall combined score:

- absent trials are correct if N was pressed correctly

- present trials are fully correct only if Y was correct and localisation is correct

if correctAns == ‘n’:
overallCorrect = detectionCorrect
elif correctAns == ‘y’:
overallCorrect = int((decisionResp.keys == ‘y’) and (localisationCorrect == 1))
else:
overallCorrect = None

thisExp.addData(‘overallCorrect’, overallCorrect)

Any help on how to solve this, or any advice would be greatly received.

Many thanks,

Lou!

I assume that this is in a code component in the same routine as respBox. You could just set the opacity to 0 in the component. However, the key error here is that the code component should be above respBox.

Also, you seem to have continueRoutine = False in Begin Experiment, which doesn’t make sense. You could set the Routine Settins to skip if “not needBox”.