def writeLoopStartCode(self, buff): """Write the code to create and run a sequence of trials """ # first create the handler init values inits = getInitVals(self.params) # import conditions from file? if self.params['conditionsFile'].val in ['None', None, 'none', '']: condsStr = "[None]" elif self.params['Selected rows'].val in ['None', None, 'none', '']: # just a conditions file with no sub-selection _con = "data.importConditions(%s)" condsStr = _con % self.params['conditionsFile'] else: # a subset of a conditions file condsStr = ("data.importConditions(%(conditionsFile)s, selection=" "%(Selected rows)s)") % self.params # also a 'thisName' for use in "for thisTrial in trials:" makeLoopIndex = self.exp.namespace.makeLoopIndex self.thisName = makeLoopIndex(self.params['name'].val) # write the code code = ( "\n# set up handler to look after randomisation of conditions etc\n" "%(name)s = data.TrialHandler(nReps=%(nReps)s, method=%(loopType)s, \n" " extraInfo=expInfo, originPath=-1,\n") buff.writeIndentedLines(code % inits) # the next line needs to be kept separate to preserve potential string formatting # by the user in condStr (i.e. it shouldn't be a formatted string itself code = " trialList=" + condsStr + ",\n" # conditions go here buff.writeIndented(code) code = " seed=%(random seed)s, name='%(name)s')\n" buff.writeIndentedLines(code % inits) code = ( "thisExp.addLoop(%(name)s) # add the loop to the experiment\n" + self.thisName + " = %(name)s.trialList[0] " + "# so we can initialise stimuli with some values\n") buff.writeIndentedLines(code % self.params) # unclutter the namespace if not self.exp.prefsBuilder['unclutteredNamespace']: code = ( "# abbreviate parameter names if possible (e.g. rgb = %(name)s.rgb)\n" "if %(name)s != None:\n" " for paramName in %(name)s:\n" " exec('{} = %(name)s[paramName]'.format(paramName))\n") buff.writeIndentedLines(code % {'name': self.thisName}) # then run the trials loop code = "\nfor %s in %s:\n" buff.writeIndentedLines(code % (self.thisName, self.params['name'])) # fetch parameter info from conditions buff.setIndentLevel(1, relative=True) buff.writeIndented("currentLoop = %s\n" % self.params['name']) # unclutter the namespace if not self.exp.prefsBuilder['unclutteredNamespace']: code = ( "# abbreviate parameter names if possible (e.g. rgb = %(name)s.rgb)\n" "if %(name)s != None:\n" " for paramName in %(name)s:\n" " exec('{} = %(name)s[paramName]'.format(paramName))\n") buff.writeIndentedLines(code % {'name': self.thisName})
def test_params_used(self): # Make minimal experiment just for this test rt, exp = _make_minimal_experiment(self) # Try with PsychoPy and PsychoJS for target in ("PsychoPy", "PsychoJS"): ## Skip PsychoJS until can write script without saving if target == "PsychoJS": continue # Skip unimplemented targets if target not in rt.targets: continue # Compile script script = exp.writeScript(target=target) # Check that the string value of each param is present in the script experiment.utils.scriptTarget = target # Iterate through every param for routine in exp.flow: for name, param in experiment.getInitVals( routine.params, target).items(): # Conditions to skip... if not param.direct: # Marked as not direct continue if any(name in depend['param'] for depend in routine.depends): # Dependent on another param continue # Check that param is used assert str(param) in script, ( f"Value {param} of <psychopy.experiment.params.Param: val={param.val}, valType={param.valType}> " f"in {type(rt).__name__} not found in {target} script." )
def writeLoopStartCode(self, buff): """Write the code to create and run a sequence of trials """ # first create the handler init values inits = getInitVals(self.params) # import conditions from file? if self.params['conditionsFile'].val in ['None', None, 'none', '']: condsStr = "[None]" elif self.params['Selected rows'].val in ['None', None, 'none', '']: # just a conditions file with no sub-selection _con = "data.importConditions(%s)" condsStr = _con % self.params['conditionsFile'] else: # a subset of a conditions file condsStr = ("data.importConditions(%(conditionsFile)s, selection=" "%(Selected rows)s)") % self.params # also a 'thisName' for use in "for thisTrial in trials:" makeLoopIndex = self.exp.namespace.makeLoopIndex self.thisName = makeLoopIndex(self.params['name'].val) # write the code code = ("\n# set up handler to look after randomisation of conditions etc\n" "%(name)s = data.TrialHandler(nReps=%(nReps)s, method=%(loopType)s, \n" " extraInfo=expInfo, originPath=-1,\n") buff.writeIndentedLines(code % inits) # the next line needs to be kept separate to preserve potential string formatting # by the user in condStr (i.e. it shouldn't be a formatted string itself code = " trialList=" + condsStr + ",\n" # conditions go here buff.writeIndented(code) code = " seed=%(random seed)s, name='%(name)s')\n" buff.writeIndentedLines(code % inits) code = ("thisExp.addLoop(%(name)s) # add the loop to the experiment\n" + self.thisName + " = %(name)s.trialList[0] " + "# so we can initialise stimuli with some values\n") buff.writeIndentedLines(code % self.params) # unclutter the namespace if not self.exp.prefsBuilder['unclutteredNamespace']: code = ("# abbreviate parameter names if possible (e.g. rgb = %(name)s.rgb)\n" "if %(name)s != None:\n" " for paramName in %(name)s:\n" " exec('{} = %(name)s[paramName]'.format(paramName))\n") buff.writeIndentedLines(code % {'name': self.thisName}) # then run the trials loop code = "\nfor %s in %s:\n" buff.writeIndentedLines(code % (self.thisName, self.params['name'])) # fetch parameter info from conditions buff.setIndentLevel(1, relative=True) buff.writeIndented("currentLoop = %s\n" % self.params['name']) # unclutter the namespace if not self.exp.prefsBuilder['unclutteredNamespace']: code = ("# abbreviate parameter names if possible (e.g. rgb = %(name)s.rgb)\n" "if %(name)s != None:\n" " for paramName in %(name)s:\n" " exec('{} = %(name)s[paramName]'.format(paramName))\n") buff.writeIndentedLines(code % {'name': self.thisName})
def test_params_used(self): # Change eyetracking settings self.expPy.settings.params['eyetracker'].val = "MouseGaze" # Test both python and JS for target, exp in { "PsychoPy": self.expPy, "PsychoJS": self.expJS }.items(): # todo: add JS exceptions if target == "PsychoJS": continue # Iterate through each component for compName, component in self.allComp.items(): # Skip if not valid for this (or any) target if target not in component.targets: continue if compName == "SettingsComponent": continue if compName in ['RatingScaleComponent', 'PatchComponent']: continue # Make a routine for this component rt = exp.addRoutine(compName + "Routine") comp = component(parentName=compName + "Routine", exp=exp) rt.append(comp) exp.flow.addRoutine(rt, 0) # Compile script script = exp.writeScript(target=target) # Check that the string value of each param is present in the script experiment.utils.scriptTarget = target # Iterate through every param for paramName, param in experiment.getInitVals( comp.params, target).items(): # Conditions to skip... if not param.direct: # Marked as not direct continue if any(paramName in depend['param'] for depend in comp.depends): # Dependent on another param continue if param.val in [ "from exp settings", # units and color space, aliased 'default', # most of the time will be aliased ]: continue # Check that param is used assert str( param ) in script, f"Could not find {target}.{type(comp).__name__}.{paramName}: <psychopy.experiment.params.Param: val={param.val}, valType={param.valType}> in script:\n\n{script}" # Remove routine exp.flow.removeComponent(rt)
def test_params_used(self): # Make minimal experiment just for this test comp, rt, exp = _make_minimal_experiment(self) # Skip if component shouldn't use all of its params if type(comp).__name__ in ["SettingsComponent", "CodeComponent"]: pytest.skip() # Skip if component is deprecated if type(comp).__name__ in ['RatingScaleComponent', 'PatchComponent']: pytest.skip() # Try with PsychoPy and PsychoJS for target in ("PsychoPy", "PsychoJS"): ## Skip PsychoJS until can write script without saving if target == "PsychoJS": continue # Skip if not valid for this target if target not in comp.targets: continue # Compile script script = exp.writeScript(target=target) # Check that the string value of each param is present in the script experiment.utils.scriptTarget = target # Iterate through every param for paramName, param in experiment.getInitVals( comp.params, target).items(): # Conditions to skip... if not param.direct: # Marked as not direct continue if any(paramName in depend['param'] for depend in comp.depends): # Dependent on another param continue if param.val in [ "from exp settings", # units and color space, aliased 'default', # most of the time will be aliased ]: continue # Check that param is used assert str(param) in script, ( f"Value {param} of <psychopy.experiment.params.Param: val={param.val}, valType={param.valType}> " f"in {type(comp).__name__} not found in {target} script.")
def test_params_used(self): # Change eyetracking settings self.expPy.settings.params['eyetracker'].val = "MouseGaze" # Test both python and JS for target, exp in { "PsychoPy": self.expPy, "PsychoJS": self.expJS }.items(): for rtName, routine in self.routines.items(): # Skip if not valid for this (or any) target if target not in routine.targets: continue # Make routine rt = routine(exp) rt = exp.addStandaloneRoutine(rtName, rt) exp.flow.addRoutine(rt, 0) # Compile script script = exp.writeScript(target=target) # Check that the string value of each param is present in the script experiment.utils.scriptTarget = target # Iterate through every param for routine in exp.flow: for name, param in experiment.getInitVals( routine.params, target).items(): # Conditions to skip... if not param.direct: # Marked as not direct continue if any(name in depend['param'] for depend in routine.depends): # Dependent on another param continue # Check that param is used assert str( param ) in script, f"{target}.{type(routine).__name__}.{name}: <psychopy.experiment.params.Param: val={param.val}, valType={param.valType}>"