def test_dollar_sign_syntax(self):
     # Define several "tykes" - values which are likely to cause confusion - along with whether or not they are valid syntax
     tykes = {
         "$hello $there": False,
         "$hello \\$there": False,
         "hello $there": False,
         "\\$hello there": True,
         "#$hello there": False,
         "$#hello there": True,
         "$hello #there": True,
         "$hello #$there": True,
         "$hello \"\\$there\"": True,
         "$hello \'\\$there\'": True,
     }
     # Make a component with a str parameter for each tyke
     tykeComponent = BaseComponent(None, None)
     for (i, val) in enumerate(tykes):
         tykeComponent.params.update({str(i): Param(val, "str")})
     for (i, val) in enumerate(tykes):
         # Check the validity of each tyke param against the expected value
         assert tykeComponent.params[str(i)].dollarSyntax()[0] == tykes[val]
Esempio n. 2
0
 def __init__(self,
              exp,
              name,
              nReps='50',
              stairType='simple',
              switchStairs='random',
              conditions=(),
              conditionsFile='',
              endPoints=(0, 1),
              isTrials=True):
     """
     @param name: name of the loop e.g. trials
     @type name: string
     @param nReps: number of reps (for all conditions)
     @type nReps:int
     """
     super(MultiStairHandler, self).__init__()
     self.type = 'MultiStairHandler'
     self.exp = exp
     self.order = ['name']  # make name come first
     self.params = {}
     self.params['name'] = Param(name,
                                 valType='code',
                                 label=_localized['Name'],
                                 hint=_translate("Name of this loop"))
     self.params['nReps'] = Param(
         nReps,
         valType='code',
         label=_localized['nReps'],
         hint=_translate("(Minimum) number of trials in *each* staircase"))
     self.params['stairType'] = Param(
         stairType,
         valType='str',
         allowedVals=['simple', 'QUEST', 'quest', 'questplus'],
         label=_localized['stairType'],
         hint=_translate("How to select the next staircase to run"))
     self.params['switchMethod'] = Param(
         switchStairs,
         valType='str',
         allowedVals=['random', 'sequential', 'fullRandom'],
         label=_localized['switchMethod'],
         hint=_translate("How to select the next staircase to run"))
     # these two are really just for making the dialog easier (they won't
     # be used to generate code)
     self.params['loopType'] = Param(
         'staircase',
         valType='str',
         allowedVals=[
             'random', 'sequential', 'fullRandom', 'staircase',
             'interleaved staircases'
         ],
         label=_localized['loopType'],
         hint=_translate("How should the next trial value(s) be chosen?"))
     self.params['endPoints'] = Param(
         list(endPoints),
         valType='num',
         label=_localized['endPoints'],
         hint=_translate('Where to loop from and to (see values currently'
                         ' shown in the flow view)'))
     self.params['conditions'] = Param(
         list(conditions),
         valType='str',
         updates=None,
         allowedUpdates=None,
         label=_localized['conditions'],
         hint=_translate("A list of dictionaries describing the "
                         "differences between each staircase"))
     self.params['conditionsFile'] = Param(
         conditionsFile,
         valType='str',
         updates=None,
         allowedUpdates=None,
         label=_localized['conditions'],
         hint=_translate("An xlsx or csv file specifying the parameters "
                         "for each condition"))
     self.params['isTrials'] = Param(
         isTrials,
         valType='bool',
         updates=None,
         allowedUpdates=None,
         label=_localized["Is trials"],
         hint=_translate("Indicates that this loop generates TRIALS, "
                         "rather than BLOCKS of trials or stimuli within "
                         "a trial. It alters how data files are output"))
     pass  # don't initialise at start of exp, create when needed
Esempio n. 3
0
 def __init__(self,
              exp,
              name,
              nReps='50',
              startVal='',
              nReversals='',
              nUp=1,
              nDown=3,
              minVal=0,
              maxVal=1,
              stepSizes='[4,4,2,2,1]',
              stepType='db',
              endPoints=(0, 1),
              isTrials=True):
     """
     @param name: name of the loop e.g. trials
     @type name: string
     @param nReps: number of reps (for all conditions)
     @type nReps:int
     """
     super(StairHandler, self).__init__()
     self.type = 'StairHandler'
     self.exp = exp
     self.order = ['name']  # make name come first (others don't matter)
     self.children = []
     self.params = {}
     self.params['name'] = Param(name,
                                 valType='code',
                                 hint=_translate("Name of this loop"),
                                 label=_localized['Name'])
     self.params['nReps'] = Param(
         nReps,
         valType='code',
         label=_localized['nReps'],
         hint=_translate("(Minimum) number of trials in the staircase"))
     self.params['start value'] = Param(
         startVal,
         valType='code',
         label=_localized['start value'],
         hint=_translate("The initial value of the parameter"))
     self.params['max value'] = Param(
         maxVal,
         valType='code',
         label=_localized['max value'],
         hint=_translate("The maximum value the parameter can take"))
     self.params['min value'] = Param(
         minVal,
         valType='code',
         label=_localized['min value'],
         hint=_translate("The minimum value the parameter can take"))
     self.params['step sizes'] = Param(
         stepSizes,
         valType='code',
         label=_localized['step sizes'],
         hint=_translate("The size of the jump at each step (can change"
                         " on each 'reversal')"))
     self.params['step type'] = Param(
         stepType,
         valType='str',
         allowedVals=['lin', 'log', 'db'],
         label=_localized['step type'],
         hint=_translate("The units of the step size (e.g. 'linear' will"
                         " add/subtract that value each step, whereas "
                         "'log' will ad that many log units)"))
     self.params['N up'] = Param(
         nUp,
         valType='code',
         label=_localized['N up'],
         hint=_translate("The number of 'incorrect' answers before the "
                         "value goes up"))
     self.params['N down'] = Param(
         nDown,
         valType='code',
         label=_localized['N down'],
         hint=_translate("The number of 'correct' answers before the "
                         "value goes down"))
     self.params['N reversals'] = Param(
         nReversals,
         valType='code',
         label=_localized['N reversals'],
         hint=_translate("Minimum number of times the staircase must "
                         "change direction before ending"))
     # these two are really just for making the dialog easier (they won't
     # be used to generate code)
     self.params['loopType'] = Param(
         'staircase',
         valType='str',
         allowedVals=[
             'random', 'sequential', 'fullRandom', 'staircase',
             'interleaved staircases'
         ],
         label=_localized['loopType'],
         hint=_translate("How should the next trial value(s) be chosen?"))
     # NB this is added for the sake of the loop properties dialog
     self.params['endPoints'] = Param(
         list(endPoints),
         valType='num',
         label=_localized['endPoints'],
         hint=_translate('Where to loop from and to (see values currently'
                         ' shown in the flow view)'))
     self.params['isTrials'] = Param(
         isTrials,
         valType='bool',
         updates=None,
         allowedUpdates=None,
         label=_localized["Is trials"],
         hint=_translate("Indicates that this loop generates TRIALS, "
                         "rather than BLOCKS of trials or stimuli within"
                         " a trial. It alters how data files are output"))
Esempio n. 4
0
 def __init__(self,
              exp,
              name,
              loopType='random',
              nReps=5,
              conditions=(),
              conditionsFile='',
              endPoints=(0, 1),
              randomSeed='',
              selectedRows='',
              isTrials=True):
     """
     @param name: name of the loop e.g. trials
     @type name: string
     @param loopType:
     @type loopType: string ('rand', 'seq')
     @param nReps: number of reps (for all conditions)
     @type nReps:int
     @param conditions: list of different trial conditions to be used
     @type conditions: list (of dicts?)
     @param conditionsFile: filename of the .csv file that
         contains conditions info
     @type conditions: string (filename)
     """
     super(TrialHandler, self).__init__()
     self.type = 'TrialHandler'
     self.exp = exp
     self.order = ['name']  # make name come first (others don't matter)
     self.params = {}
     self.params['name'] = Param(name,
                                 valType='code',
                                 updates=None,
                                 allowedUpdates=None,
                                 label=_localized['Name'],
                                 hint=_translate("Name of this loop"))
     self.params['nReps'] = Param(
         nReps,
         valType='code',
         updates=None,
         allowedUpdates=None,
         label=_localized['nReps'],
         hint=_translate("Number of repeats (for each condition)"))
     self.params['conditions'] = Param(
         list(conditions),
         valType='str',
         updates=None,
         allowedUpdates=None,
         label=_localized['conditions'],
         hint=_translate("A list of dictionaries describing the "
                         "parameters in each condition"))
     self.params['conditionsFile'] = Param(
         conditionsFile,
         valType='str',
         updates=None,
         allowedUpdates=None,
         label=_localized['conditions'],
         hint=_translate("Name of a file specifying the parameters for "
                         "each condition (.csv, .xlsx, or .pkl). Browse "
                         "to select a file. Right-click to preview file "
                         "contents, or create a new file."))
     self.params['endPoints'] = Param(
         list(endPoints),
         valType='num',
         updates=None,
         allowedUpdates=None,
         label=_localized['endPoints'],
         hint=_translate("The start and end of the loop (see flow "
                         "timeline)"))
     self.params['Selected rows'] = Param(
         selectedRows,
         valType='str',
         updates=None,
         allowedUpdates=None,
         label=_localized['Selected rows'],
         hint=_translate("Select just a subset of rows from your condition"
                         " file (the first is 0 not 1!). Examples: 0, "
                         "0:5, 5:-1"))
     # NB staircase is added for the sake of the loop properties dialog:
     self.params['loopType'] = Param(
         loopType,
         valType='str',
         allowedVals=[
             'random', 'sequential', 'fullRandom', 'staircase',
             'interleaved staircases'
         ],
         label=_localized['loopType'],
         hint=_translate("How should the next condition value(s) be "
                         "chosen?"))
     self.params['random seed'] = Param(
         randomSeed,
         valType='code',
         updates=None,
         allowedUpdates=None,
         label=_localized['random seed'],
         hint=_translate("To have a fixed random sequence provide an "
                         "integer of your choosing here. Leave blank to "
                         "have a new random sequence on each run of the "
                         "experiment."))
     self.params['isTrials'] = Param(
         isTrials,
         valType='bool',
         updates=None,
         allowedUpdates=None,
         label=_localized["Is trials"],
         hint=_translate("Indicates that this loop generates TRIALS, "
                         "rather than BLOCKS of trials or stimuli within "
                         "a trial. It alters how data files are output"))
Esempio n. 5
0
    def _getXMLparam(self, params, paramNode, componentNode=None):
        """params is the dict of params of the builder component
        (e.g. stimulus) into which the parameters will be inserted
        (so the object to store the params should be created first)
        paramNode is the parameter node fetched from the xml file
        """
        name = paramNode.get('name')
        valType = paramNode.get('valType')
        val = paramNode.get('val')
        # many components need web char newline replacement
        if not name == 'advancedParams':
            val = val.replace("
", "\n")

        # custom settings (to be used when
        if name == 'storeResponseTime':
            return  # deprecated in v1.70.00 because it was redundant
        elif name == 'nVertices':  # up to 1.85 there was no shape param
            # if no shape param then use "n vertices" only
            if _findParam('shape', componentNode) is None:
                if val == '2':
                    params['shape'].val = "line"
                elif val == '3':
                    params['shape'].val = "triangle"
                elif val == '4':
                    params['shape'].val = "rectangle"
                else:
                    params['shape'].val = "regular polygon..."
            params['nVertices'].val = val
        elif name == 'startTime':  # deprecated in v1.70.00
            params['startType'].val = "{}".format('time (s)')
            params['startVal'].val = "{}".format(val)
            return  # times doesn't need to update its type or 'updates' rule
        elif name == 'forceEndTrial':  # deprecated in v1.70.00
            params['forceEndRoutine'].val = bool(val)
            return  # forceEndTrial doesn't need to update type or 'updates'
        elif name == 'forceEndTrialOnPress':  # deprecated in v1.70.00
            params['forceEndRoutineOnPress'].val = bool(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'forceEndRoutineOnPress':
            if val is True:
                val = "any click"
            elif val is False:
                val = "never"
            params['forceEndRoutineOnPress'].val = val
            return
        elif name == 'trialList':  # deprecated in v1.70.00
            params['conditions'].val = eval(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'trialListFile':  # deprecated in v1.70.00
            params['conditionsFile'].val = "{}".format(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'duration':  # deprecated in v1.70.00
            params['stopType'].val = u'duration (s)'
            params['stopVal'].val = "{}".format(val)
            return  # times doesn't need to update its type or 'updates' rule
        elif name == 'allowedKeys' and valType == 'str':  # changed v1.70.00
            # ynq used to be allowed, now should be 'y','n','q' or
            # ['y','n','q']
            if len(val) == 0:
                newVal = val
            elif val[0] == '$':
                newVal = val[1:]  # they were using code (which we can reuse)
            elif val.startswith('[') and val.endswith(']'):
                # they were using code (slightly incorectly!)
                newVal = val[1:-1]
            elif val in ['return', 'space', 'left', 'right', 'escape']:
                newVal = val  # they were using code
            else:
                # convert string to list of keys then represent again as a
                # string!
                newVal = repr(list(val))
            params['allowedKeys'].val = newVal
            params['allowedKeys'].valType = 'code'
        elif name == 'correctIf':  # deprecated in v1.60.00
            corrIf = val
            corrAns = corrIf.replace('resp.keys==unicode(',
                                     '').replace(')', '')
            params['correctAns'].val = corrAns
            name = 'correctAns'  # then we can fetch other aspects below
        elif 'olour' in name:  # colour parameter was Americanised v1.61.00
            name = name.replace('olour', 'olor')
            params[name].val = val
        elif name == 'times':  # deprecated in v1.60.00
            times = eval('%s' % val)
            params['startType'].val = "{}".format('time (s)')
            params['startVal'].val = "{}".format(times[0])
            params['stopType'].val = "{}".format('time (s)')
            params['stopVal'].val = "{}".format(times[1])
            return  # times doesn't need to update its type or 'updates' rule
        elif name in ('Begin Experiment', 'Begin Routine', 'Each Frame',
                      'End Routine', 'End Experiment'):
            params[name].val = val
            params[name].valType = 'extendedCode'  # changed in 1.78.00
            return  # so that we don't update valTyp again below
        elif name == 'Saved data folder':
            # deprecated in 1.80 for more complete data filename control
            params[name] = Param(val,
                                 valType='code',
                                 allowedTypes=[],
                                 hint=_translate(
                                     "Name of the folder in which to save data"
                                     " and log files (blank defaults to the "
                                     "builder pref)"),
                                 categ='Data')
        elif 'val' in list(paramNode.keys()):
            if val == 'window units':  # changed this value in 1.70.00
                params[name].val = 'from exp settings'
            # in v1.80.00, some RatingScale API and Param fields were changed
            # Try to avoid a KeyError in these cases so can load the expt
            elif name in ('choiceLabelsAboveLine', 'lowAnchorText',
                          'highAnchorText'):
                # not handled, just ignored; want labels=[lowAnchor,
                # highAnchor]
                return
            elif name == 'customize_everything':
                # Try to auto-update the code:
                v = val  # python code, not XML
                v = v.replace('markerStyle',
                              'marker').replace('customMarker', 'marker')
                v = v.replace('stretchHoriz',
                              'stretch').replace('displaySizeFactor', 'size')
                v = v.replace('textSizeFactor', 'textSize')
                v = v.replace('ticksAboveLine=False', 'tickHeight=-1')
                v = v.replace('showScale=False',
                              'scale=None').replace('allowSkip=False',
                                                    'skipKeys=None')
                v = v.replace('showAnchors=False', 'labels=None')
                # lowAnchorText highAnchorText will trigger obsolete error
                # when run the script
                params[name].val = v
            else:
                if name in params:
                    params[name].val = val
                else:
                    # we found an unknown parameter (probably from the future)
                    params[name] = Param(
                        val,
                        valType=paramNode.get('valType'),
                        allowedTypes=[],
                        hint=_translate(
                            "This parameter is not known by this version "
                            "of PsychoPy. It might be worth upgrading"))
                    params[name].allowedTypes = paramNode.get('allowedTypes')
                    if params[name].allowedTypes is None:
                        params[name].allowedTypes = []
                    params[name].readOnly = True
                    msg = _translate(
                        "Parameter %r is not known to this version of "
                        "PsychoPy but has come from your experiment file "
                        "(saved by a future version of PsychoPy?). This "
                        "experiment may not run correctly in the current "
                        "version.")
                    logging.warn(msg % name)
                    logging.flush()

        # get the value type and update rate
        if 'valType' in list(paramNode.keys()):
            params[name].valType = paramNode.get('valType')
            # compatibility checks:
            if name in ['allowedKeys'] and paramNode.get('valType') == 'str':
                # these components were changed in v1.70.00
                params[name].valType = 'code'
            elif name == 'Selected rows':
                # changed in 1.81.00 from 'code' to 'str': allow string or var
                params[name].valType = 'str'
            # conversions based on valType
            if params[name].valType == 'bool':
                params[name].val = eval("%s" % params[name].val)
        if 'updates' in list(paramNode.keys()):
            params[name].updates = paramNode.get('updates')
Esempio n. 6
0
    def _getXMLparam(self, params, paramNode, componentNode=None):
        """params is the dict of params of the builder component
        (e.g. stimulus) into which the parameters will be inserted
        (so the object to store the params should be created first)
        paramNode is the parameter node fetched from the xml file
        """
        name = paramNode.get('name')
        valType = paramNode.get('valType')
        val = paramNode.get('val')
        # many components need web char newline replacement
        if not name == 'advancedParams':
            val = val.replace("
", "\n")

        # custom settings (to be used when
        if name == 'storeResponseTime':
            return  # deprecated in v1.70.00 because it was redundant
        elif name == 'nVertices':  # up to 1.85 there was no shape param
            # if no shape param then use "n vertices" only
            if _findParam('shape', componentNode) is None:
                if val == '2':
                    params['shape'].val = "line"
                elif val == '3':
                    params['shape'].val = "triangle"
                elif val == '4':
                    params['shape'].val = "rectangle"
                else:
                    params['shape'].val = "regular polygon..."
            params['nVertices'].val = val
        elif name == 'startTime':  # deprecated in v1.70.00
            params['startType'].val = "{}".format('time (s)')
            params['startVal'].val = "{}".format(val)
            return  # times doesn't need to update its type or 'updates' rule
        elif name == 'forceEndTrial':  # deprecated in v1.70.00
            params['forceEndRoutine'].val = bool(val)
            return  # forceEndTrial doesn't need to update type or 'updates'
        elif name == 'forceEndTrialOnPress':  # deprecated in v1.70.00
            params['forceEndRoutineOnPress'].val = bool(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'forceEndRoutineOnPress':
            if val == 'True':
                val = "any click"
            elif val == 'False':
                val = "never"
            params['forceEndRoutineOnPress'].val = val
            return
        elif name == 'trialList':  # deprecated in v1.70.00
            params['conditions'].val = eval(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'trialListFile':  # deprecated in v1.70.00
            params['conditionsFile'].val = "{}".format(val)
            return  # forceEndTrial doesn't need to update  type or 'updates'
        elif name == 'duration':  # deprecated in v1.70.00
            params['stopType'].val = u'duration (s)'
            params['stopVal'].val = "{}".format(val)
            return  # times doesn't need to update its type or 'updates' rule
        elif name == 'allowedKeys' and valType == 'str':  # changed v1.70.00
            # ynq used to be allowed, now should be 'y','n','q' or
            # ['y','n','q']
            if len(val) == 0:
                newVal = val
            elif val[0] == '$':
                newVal = val[1:]  # they were using code (which we can reuse)
            elif val.startswith('[') and val.endswith(']'):
                # they were using code (slightly incorectly!)
                newVal = val[1:-1]
            elif val in ['return', 'space', 'left', 'right', 'escape']:
                newVal = val  # they were using code
            else:
                # convert string to list of keys then represent again as a
                # string!
                newVal = repr(list(val))
            params['allowedKeys'].val = newVal
            params['allowedKeys'].valType = 'code'
        elif name == 'correctIf':  # deprecated in v1.60.00
            corrIf = val
            corrAns = corrIf.replace(
                'resp.keys==unicode(', '').replace(')', '')
            params['correctAns'].val = corrAns
            name = 'correctAns'  # then we can fetch other aspects below
        elif 'olour' in name:  # colour parameter was Americanised v1.61.00
            name = name.replace('olour', 'olor')
            params[name].val = val
        elif name == 'times':  # deprecated in v1.60.00
            times = eval('%s' % val)
            params['startType'].val = "{}".format('time (s)')
            params['startVal'].val = "{}".format(times[0])
            params['stopType'].val = "{}".format('time (s)')
            params['stopVal'].val = "{}".format(times[1])
            return  # times doesn't need to update its type or 'updates' rule
        elif name in ('Begin Experiment', 'Begin Routine', 'Each Frame',
                      'End Routine', 'End Experiment'):
            params[name].val = val
            params[name].valType = 'extendedCode'  # changed in 1.78.00
            return  # so that we don't update valTyp again below
        elif name == 'Saved data folder':
            # deprecated in 1.80 for more complete data filename control
            params[name] = Param(
                val, valType='code', allowedTypes=[],
                hint=_translate("Name of the folder in which to save data"
                                " and log files (blank defaults to the "
                                "builder pref)"),
                categ='Data')
        elif 'val' in list(paramNode.keys()):
            if val == 'window units':  # changed this value in 1.70.00
                params[name].val = 'from exp settings'
            # in v1.80.00, some RatingScale API and Param fields were changed
            # Try to avoid a KeyError in these cases so can load the expt
            elif name in ('choiceLabelsAboveLine', 'lowAnchorText',
                          'highAnchorText'):
                # not handled, just ignored; want labels=[lowAnchor,
                # highAnchor]
                return
            elif name == 'customize_everything':
                # Try to auto-update the code:
                v = val  # python code, not XML
                v = v.replace('markerStyle', 'marker').replace(
                    'customMarker', 'marker')
                v = v.replace('stretchHoriz', 'stretch').replace(
                    'displaySizeFactor', 'size')
                v = v.replace('textSizeFactor', 'textSize')
                v = v.replace('ticksAboveLine=False', 'tickHeight=-1')
                v = v.replace('showScale=False', 'scale=None').replace(
                    'allowSkip=False', 'skipKeys=None')
                v = v.replace('showAnchors=False', 'labels=None')
                # lowAnchorText highAnchorText will trigger obsolete error
                # when run the script
                params[name].val = v
            else:
                if name in params:
                    params[name].val = val
                else:
                    # we found an unknown parameter (probably from the future)
                    params[name] = Param(
                        val, valType=paramNode.get('valType'),
                        allowedTypes=[],
                        hint=_translate("This parameter is not known by this version "
                                        "of PsychoPy. It might be worth upgrading"))
                    params[name].allowedTypes = paramNode.get('allowedTypes')
                    if params[name].allowedTypes is None:
                        params[name].allowedTypes = []
                    params[name].readOnly = True
                    msg = _translate("Parameter %r is not known to this version of "
                                     "PsychoPy but has come from your experiment file "
                                     "(saved by a future version of PsychoPy?). This "
                                     "experiment may not run correctly in the current "
                                     "version.")
                    logging.warn(msg % name)
                    logging.flush()

        # get the value type and update rate
        if 'valType' in list(paramNode.keys()):
            params[name].valType = paramNode.get('valType')
            # compatibility checks:
            if name in ['allowedKeys'] and paramNode.get('valType') == 'str':
                # these components were changed in v1.70.00
                params[name].valType = 'code'
            elif name == 'Selected rows':
                # changed in 1.81.00 from 'code' to 'str': allow string or var
                params[name].valType = 'str'
            # conversions based on valType
            if params[name].valType == 'bool':
                params[name].val = eval("%s" % params[name].val)
        if 'updates' in list(paramNode.keys()):
            params[name].updates = paramNode.get('updates')