def _parse_subject(self, v_str, variables): err = f"Parameter {kw.SUBJECT} must be 'average', 'all', or a positive integer." if v_str.lower() in ('average', 'all'): self.val[kw.SUBJECT] = v_str.lower() else: v, interr = ParseUtil.parse_posint(v_str, variables) if interr: # Parsing error return err + " " + interr if v is None: # Parsing worked, but negative integer return err self.val[kw.SUBJECT] = v - 1 # Zero-based index internally return None
def str_set(self, prop, v_str, variables, phases, all_run_labels, to_be_continued, is_appending=False): """ Parses the specified value (as a string) of the specified parameter and sets the resulting value. The input variables is a Variables object. Returns error message if parsing failed. """ err = check_is_parameter_name(prop) if err: return err # all_phase_labels = phases.labels_set() if prop == kw.BEHAVIORS: return self._parse_behaviors(v_str, variables, is_appending) elif prop == kw.STIMULUS_ELEMENTS: return self._parse_stimulus_elements(v_str, variables, is_appending) elif prop == kw.MECHANISM_NAME: return self._parse_mechanism_name(v_str) elif prop in (kw.START_VSS, kw.ALPHA_VSS): return self._parse_alphastart_vss(prop, v_str, variables, to_be_continued, is_appending) elif prop in (kw.START_W, kw.ALPHA_W, kw.U, kw.LAMBDA): return self._parse_stimulus_values(prop, v_str, variables, to_be_continued, is_appending) elif prop in (kw.BETA, kw.MU, kw.START_V, kw.ALPHA_V): return self._parse_stimulus_response_values( prop, v_str, variables, to_be_continued, is_appending) # Float elif prop in (kw.DISCOUNT, kw.TRACE): v, err = ParseUtil.evaluate(v_str, variables) if err: return err if (v < 0) or (v > 1): return f"Parameter '{prop}' must be a number >=0 and <=1." self.val[prop] = v return None elif prop == kw.BEHAVIOR_COST: return self._parse_behavior_cost(v_str, variables, to_be_continued, is_appending) elif prop == kw.RESPONSE_REQUIREMENTS: return self._parse_response_requirements(v_str, to_be_continued, is_appending) # 'on' or 'off' elif prop in (kw.BIND_TRIALS, kw.CUMULATIVE): v_str_lower = v_str.lower() if v_str_lower not in ('on', 'off'): return "Parameter '{}' must be 'on' or 'off'.".format(prop) self.val[prop] = v_str_lower return None # Positive integer elif prop == kw.N_SUBJECTS: v, err = ParseUtil.parse_posint(v_str, variables) if err: return err if not v: return "Parameter {} must be a positive integer.".format( kw.N_SUBJECTS) self.val[kw.N_SUBJECTS] = v return None # Any nonempty (after strip) string elif prop in (kw.TITLE, kw.SUBPLOTTITLE): if to_be_continued: # Add the removed comma v_str = v_str + "," self.val[prop] = v_str return None # 'average', 'all' or 1-based index elif prop == kw.SUBJECT: return self._parse_subject(v_str, variables) # 'all' or s1->b1->s2->..., s=se1,se2,... elif prop == kw.XSCALE: return self._parse_xscale(v_str, phases) # 'subset' or 'exact' elif prop in (kw.MATCH, kw.XSCALE_MATCH): if v_str.lower() not in ('subset', 'exact'): return "Parameter {} must be 'subset' or 'exact'.".format(prop) self.val[prop] = v_str return None # 'all' or cs-list of phase labels elif prop == kw.PHASES: return self._parse_phases(v_str) # , all_phase_labels) # String (@run-labels) (for postprocessing) elif prop == kw.RUNLABEL: if v_str not in all_run_labels: return "Invalid @RUN-label {}".format(v_str) self.val[kw.RUNLABEL] = v_str return None # Valid path to writable file elif prop == kw.FILENAME: filename = v_str try: file = open(filename, 'w', newline='') except Exception as ex: return str(ex) finally: file.close() try: os.remove(filename) except FileNotFoundError: pass self.val[kw.FILENAME] = filename return None