def applyConstraints(dm_exp, dm_fillers): """ Arguments: dm_exp --- dm containing exp scene-object combinations dm_fillers --- dm containing filler scene-object combinations Returns: final_dm_test_feedback --- final datamatrix for the test feedback blockloop final_dm_criterion_test --- final datamatrix for the test feedback blockloop """ # Add distractors: dm_exp = addDistractors.addDistractors(dm_exp) dm_fillers = addDistractors.addDistractors(dm_fillers) # Make sure we will collect two dms list_dms = [] for block in ["test_feedback", "criterion_test"]: # Shuffle the fillers: dm_fillers = ops.shuffle(dm_fillers) # Merge first 8 fillers to the main dm # NOTE: we leave out four fillers because we will use them for the # very first and the very last trials dm_fillers_slice = dm_fillers[0:8] main_dm = dm_exp << dm_fillers_slice # Shuffle the main dm: main_dm = ops.shuffle(main_dm) # Create an Enforce object, and add two constraints ef = Enforce(main_dm) ef.add_constraint(MaxRep, cols=[main_dm.Emotion], maxrep=3) ef.add_constraint(MinDist, cols=[main_dm.Trial_ID], mindist=2) # Enforce the constraints main_dm = ef.enforce() # See the resulting DataFrame and a report of how long the enforcement took. # Add two fillers to the beginning of the final dm: dm_fillers_slice_first = dm_fillers[8:10] final_dm = dm_fillers_slice_first << main_dm # And to the end fo the final dm: dm_fillers_slice_last = dm_fillers[10:] final_dm = final_dm << dm_fillers_slice_last # Append to the dm list: list_dms.append(final_dm) # Unpack the list so we can return two separate dms dm1, dm2 = list_dms return dm1, dm2
def check_shuffle(col_type): dm = DataMatrix(length=3, default_col_type=col_type) dm.col1 = 11, 12, 13 dm.col2 = 1, 2, 3 dm = operations.shuffle(dm) for row in dm: ok_(row.col1 == row.col2 + 10) dm.col1 = operations.shuffle(dm.col1) dm.col2 = operations.shuffle(dm.col2) check_integrity(dm)
def check_shuffle(col_type): dm = DataMatrix(length=3, default_col_type=col_type) dm.col1 = 11,12,13 dm.col2 = 1,2,3 dm = operations.shuffle(dm) for row in dm: ok_(row.col1 == row.col2+10) dm.col1 = operations.shuffle(dm.col1) dm.col2 = operations.shuffle(dm.col2) check_integrity(dm)
def check_mixedcolumn_sorting(): dm = DataMatrix(length=24) dm.c = [ 1, '1', 2, '2', 1.1, '1.1', 2.1, '2.1', INF, -INF, 'inf', '-inf', NAN, NAN, 'nan', 'nan', None, None, None, None, 'alpha', 'beta', 'None', '' ] dm.c = ops.shuffle(dm.c) dm = ops.sort(dm, by=dm.c) check_col(dm.c, [ -INF, -INF, 1, 1, 1.1, 1.1, 2, 2, 2.1, 2.1, INF, INF, '', 'None', 'alpha', 'beta', None, None, None, None, NAN, NAN, NAN, NAN, ])
def applyConstraints(dm_exp, dm_fillers): """ Arguments: dm_exp --- dm containing exp scene-object combinations dm_fillers --- dm containing filler scene-object combinations Returns: final_dm --- final datamatrix for the IMDF MC memory task """ # Add distractors: dm_exp = addDistractorsImdf.addDistractors(dm_exp) dm_fillers = addDistractorsImdf.addDistractors(dm_fillers) # Shuffle the fillers: dm_fillers = ops.shuffle(dm_fillers) # Merge first 4 fillers to the main dm # NOTE: we leave out four fillers because we will use them for the # very first and the very last trials # TODO: select 2 neg en 2 neutral dm_fillers_slice = dm_fillers[0:4] main_dm = dm_exp << dm_fillers_slice # Shuffle the main dm: main_dm = ops.shuffle(main_dm) # Create an Enforce object, and add two constraints ef = Enforce(main_dm) ef.add_constraint(MaxRep, cols=[main_dm.Emotion], maxrep=3) ef.add_constraint(MinDist, cols=[main_dm.Trial_ID], mindist=2) # Enforce the constraints main_dm = ef.enforce() # See the resulting DataFrame and a report of how long the enforcement took. # Add two fillers to the beginning of the final dm: dm_fillers_slice_first = dm_fillers[4:6] final_dm = dm_fillers_slice_first << main_dm # And to the end fo the final dm: dm_fillers_slice_last = dm_fillers[6:] final_dm = final_dm << dm_fillers_slice_last return final_dm
def check_intcolumn_sorting(): dm = DataMatrix(length=8, default_col_type=IntColumn) dm.c = [ 1, '1', 2, '2', 1.1, '1.1', 2.1, '2.8', ] dm.c = ops.shuffle(dm.c) dm = ops.sort(dm, by=dm.c) check_col(dm.c, [ 1, 1, 1, 1, 2, 2, 2, 2 ])
def test_shuffle(): dm = DataMatrix(length=2) dm.a = 'a', 'b' dm.b = 0, 1 while True: dm.a = ops.shuffle(dm.a) check_col(dm.b, [0, 1]) try: check_col(dm.a, ['b', 'a']) break except: pass dm = DataMatrix(length=2) dm.a = 'a', 'b' dm.b = 0, 1 while True: dm = ops.shuffle(dm) try: check_col(dm.a, ['b', 'a']) check_col(dm.b, [1, 0]) break except: pass
def test_shuffle(): dm = DataMatrix(length=2) dm.a = 'a', 'b' dm.b = 0, 1 while True: dm.a = ops.shuffle(dm.a) check_col(dm.b, [0, 1]) try: check_col(dm.a, ['b', 'a']) break except: pass dm = DataMatrix(length=2) dm.a = 'a', 'b' dm.b = 0, 1 while True: dm = ops.shuffle(dm) try: check_col(dm.a, ['b', 'a']) check_col(dm.b, [1, 0]) break except: pass
def test_bin_split(): dm = DataMatrix(length=4) dm.a = range(4) dm = ops.shuffle(dm) dm1, dm2 = ops.bin_split(dm.a, 2) check_col(dm1.a, [0,1]) check_col(dm2.a, [2,3]) dm1, dm2, dm3 = ops.bin_split(dm.a, 3) check_col(dm1.a, [0]) check_col(dm2.a, [1]) check_col(dm3.a, [2,3]) dm1, = ops.bin_split(dm.a, 1) check_col(dm1.a, [0,1,2,3]) @raises(ValueError) def _(): x, = ops.bin_split(dm.a, 5) _()
def addDistractors(dm): """ Adds distractors to a given datamatrix, making sure that both distractors are different from the target and from each other Arguments: dm --- a DataMatrix() instance without distractors Returns: new_dm --- a DataMatrix instance with distractors """ # Shuffle the dm: dm = ops.shuffle(dm) # Split the original dm by emotion: neg_dm = dm.Emotion == "neg" neu_dm = dm.Emotion == "neu" # Make a list of potential scenes for negative distractor 1 L_NEG_DIST1 = list(neg_dm.Scene) # and negative distractor 2 L_NEG_DIST2 = list(neg_dm.Scene) # Make a list of potential scenes for neutral distractor 1 L_NEU_DIST1 = list(neu_dm.Scene) # and 2 L_NEU_DIST2 = list(neu_dm.Scene) new_dm = combine(dm, L_NEG_DIST1[:], L_NEG_DIST2[:], L_NEU_DIST1[:], L_NEU_DIST2[:]) # Make sure target, distractor 1 and distractor 2 are different scenes: while any(row.distractor_scene_1 == row.distractor_scene_2 or row.distractor_scene_1 == row.Scene or row.distractor_scene_2 == row.Scene for row in new_dm): # If not, try again: print("try again") new_dm = combine(dm, L_NEG_DIST1[:], L_NEG_DIST2[:], L_NEU_DIST1[:], L_NEU_DIST2[:]) return new_dm
def test_bin_split(): dm = DataMatrix(length=4) dm.a = range(4) dm = ops.shuffle(dm) dm1, dm2 = ops.bin_split(dm.a, 2) check_col(dm1.a, [0, 1]) check_col(dm2.a, [2, 3]) dm1, dm2, dm3 = ops.bin_split(dm.a, 3) check_col(dm1.a, [0]) check_col(dm2.a, [1]) check_col(dm3.a, [2, 3]) dm1, = ops.bin_split(dm.a, 1) check_col(dm1.a, [0, 1, 2, 3]) def _(): with pytest.raises(ValueError): x, = ops.bin_split(dm.a, 5) _()
def enforce(self, maxreshuffle=100, maxpass=100): """ desc: Enforces constraints. keywords: maxpass: desc: The maximum number of times that the enforce algorithm may be restarted. type: int returns: desc: A `DataMatrix` that respects the constraints. type: DataMatrix """ t0 = time.time() reverse = False for i in range(maxreshuffle): self.dm = operations.shuffle(self.dm) for j in range(maxpass): if not self._enforce(reverse=reverse): break reverse = not reverse else: # If the maximum passes were exhausted, restart the loop continue # If the maximum passes were not exhausted, we are done break else: raise EnforceFailed( u'Failed to enforce constraints (maxreshuffle = %d)' \ % maxreshuffle) t1 = time.time() self.report = { u'time': t1 - t0, u'reshuffle': i + 1, } return self.dm
def run(self): """See item.""" self.set_item_onset() if self.live_dm is None or self.var.continuous == u'no': self.live_dm = self._create_live_datamatrix() self.live_row = 0 first = True while self.live_row < len(self.live_dm): self.experiment.var.repeat_cycle = 0 self.experiment.var.live_row = self.live_row self.experiment.var.set('live_row_%s' % self.name, self.live_row) for name, val in self.live_dm[self.live_row]: if isinstance(val, basestring) and val.startswith(u'='): val = self.python_workspace._eval(val[1:]) self.experiment.var.set(name, val) # Evaluate the run if statement if self._break_if is not None and \ (not first or self.var.break_if_on_first == u'yes'): self.python_workspace[u'self'] = self if self.python_workspace._eval(self._break_if): break # Run the item! self.experiment.items.execute(self._item) # If the repeat_cycle flag was set, run the item again later if self.experiment.var.repeat_cycle: self.live_dm <<= self.live_dm[self.live_row:self.live_row+1] if self.var.order == u'random': self.live_dm = self.live_dm[:self.live_row+1] \ << operations.shuffle(self.live_dm[self.live_row+1:]) self.live_row += 1 first = False else: # If the loop finished without breaking, it needs to be reset on # the next run of the loop item self.live_row = None self.live_dm = None
def check_floatcolumn_sorting(): dm = DataMatrix(length=24, default_col_type=FloatColumn) with pytest.warns(UserWarning): dm.c = [ 1, '1', 2, '2', 1.1, '1.1', 2.1, '2.1', INF, -INF, 'inf', '-inf', NAN, NAN, 'nan', 'nan', None, None, None, None, 'alpha', 'beta', 'None', '' ] dm.c = ops.shuffle(dm.c) dm = ops.sort(dm, by=dm.c) check_col(dm.c, [ -INF, -INF, 1, 1, 1.1, 1.1, 2, 2, 2.1, 2.1, INF, INF, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, ])
def run(self): """See item.""" self.set_item_onset() if self.live_dm is None or self.var.continuous == u'no': self.live_dm = self._create_live_datamatrix() self.live_row = 0 first = True while self.live_row < len(self.live_dm): self.experiment.var.repeat_cycle = 0 self.experiment.var.live_row = self.live_row self.experiment.var.set('live_row_%s' % self.name, self.live_row) for name, val in self.live_dm[self.live_row]: if isinstance(val, basestring) and val.startswith(u'='): val = self.python_workspace._eval(val[1:]) self.experiment.var.set(name, val) # Evaluate the run if statement if self._break_if is not None and \ (not first or self.var.break_if_on_first == u'yes'): self.python_workspace[u'self'] = self if self.python_workspace._eval(self._break_if): break # Run the item! self.experiment.items.execute(self._item) # If the repeat_cycle flag was set, run the item again later if self.experiment.var.repeat_cycle: self.live_dm <<= self.live_dm[self.live_row:self.live_row + 1] if self.var.order == u'random': self.live_dm = self.live_dm[:self.live_row+1] \ << operations.shuffle(self.live_dm[self.live_row+1:]) self.live_row += 1 first = False else: # If the loop finished without breaking, it needs to be reset on # the next run of the loop item self.live_row = None self.live_dm = None
def splitFillers(dm): """ Splits filler trials into: - 2 first fillers, one negative, one neutral - 2 last fillers, one negative, one neutral - remaining fillers, that should be mixed with the experimental trials Arguments: dm --- DataMatrix containing filler objects Returns: dm_first --- dm containing only 2 rows, corresponding to the first 2 fillers dm_last --- dm containing only 2 rows, corresponding to the last 2 fillers dm_remaining --- dm containing the remainder (if any) of the fillers NOTE the order """ # Below is an awful piece of script to make sure the first and last two fillers # consist of one neg and one neu trial. # I just don't see a way to do this more elegantly # Shuffle the fillers: dm = ops.shuffle(dm) # Split the fillers on the basis of valence: (cat1, filler_dm_negative), (cat2, filler_dm_neutral) = ops.split(dm["Emotion"]) # Select 2 fillers, one from each valence category, as first 2 fillers: identifier_filler1_neg = filler_dm_negative["Object"][0] identifier_filler1_neu = filler_dm_neutral["Object"][0] dm_filler1_neg = filler_dm_negative["Object"] == identifier_filler1_neg dm_filler1_neu = filler_dm_neutral["Object"] == identifier_filler1_neu # Merge the two first trial_dms dm_first = dm_filler1_neg << dm_filler1_neu # Shuffle dm_first = ops.shuffle(dm_first) # Add a column indicating the type of filler (for later debugging/cross # checking) dm_first["filler_type"] = "first" # Remove the already selected pairs from the dms # (i.e., select WITHOUT replacement): filler_dm_negative = filler_dm_negative[1:] filler_dm_neutral = filler_dm_neutral[1:] # Do the same thing for the last 2 fillers: # Select 2 fillers, one from each valence category, as first 2 fillers: identifier_filler2_neg = filler_dm_negative["Object"][0] identifier_filler2_neu = filler_dm_neutral["Object"][0] dm_filler2_neg = filler_dm_negative["Object"] == identifier_filler2_neg dm_filler2_neu = filler_dm_neutral["Object"] == identifier_filler2_neu # Merge: dm_last = dm_filler2_neg << dm_filler2_neu # And shuffle: dm_last = ops.shuffle(dm_last) # Add column with filler type dm_last["filler_type"] = "last" # Remove from the dms: filler_dm_negative = filler_dm_negative[1:] filler_dm_neutral = filler_dm_neutral[1:] # Merge the remaining filler dms: dm_remaining = filler_dm_negative << filler_dm_neutral # Shuffle: dm_remaining = ops.shuffle(dm_remaining) # Add column with filler type dm_remaining["filler_type"] = "middle" return dm_first, dm_last, dm_remaining
def _create_live_datamatrix(self): """ desc: Builds a live DataMatrix. That is, it takes the orignal DataMatrix and applies all the operations as specified. returns: desc: A live DataMatrix. type: DataMatrix """ if self.var.source == u'table': src_dm = self.dm else: from datamatrix import io src = self.experiment.pool[self.var.source_file] if src.endswith(u'.xlsx'): try: src_dm = io.readxlsx(src) except Exception as e: raise osexception(u'Failed to read .xlsx file: %s' % src, exception=e) else: try: src_dm = io.readtxt(src) except Exception as e: raise osexception(u'Failed to read text file (perhaps it has the wrong format or it is not utf-8 encoded): %s' % src, exception=e) for column_name in src_dm.column_names: if not self.syntax.valid_var_name(column_name): raise osexception( u'The loop table contains an invalid column name: 'u'\'%s\'' \ % column_name) # The number of repeats should be numeric. If not, then give an error. # This can also occur when generating a preview of a loop table if # repeat is variable. if not isinstance(self.var.repeat, (int, float)): raise osexception( u'Don\'t know how to generate a DataMatrix for "%s" repeats' \ % self.var.repeat) length = int(len(src_dm) * self.var.repeat) dm = DataMatrix(length=0) while len(dm) < length: i = min(length-len(dm), len(src_dm)) if self.var.order == u'random': dm <<= operations.shuffle(src_dm)[:i] else: dm <<= src_dm[:i] if self.var.order == u'random': dm = operations.shuffle(dm) if self.ef is not None: self.ef.dm = dm dm = self.ef.enforce() for cmd, arglist in self.operations: # The column name is always specified last, or not at all if arglist: try: colname = arglist[-1] col = dm[colname] except: raise osexception( u'Column %s does not exist' % arglist[-1]) if cmd == u'fullfactorial': dm = operations.fullfactorial(dm) elif cmd == u'shuffle': if not arglist: dm = operations.shuffle(dm) else: dm[colname] = operations.shuffle(col) elif cmd == u'shuffle_horiz': if not arglist: dm = operations.shuffle_horiz(dm) else: dm = operations.shuffle_horiz( *[dm[_colname] for _colname in arglist]) elif cmd == u'slice': self._require_arglist(cmd, arglist, minlen=2) dm = dm[arglist[0]: arglist[1]] elif cmd == u'sort': self._require_arglist(cmd, arglist) dm[colname] = operations.sort(col) elif cmd == u'sortby': self._require_arglist(cmd, arglist) dm = operations.sort(dm, by=col) elif cmd == u'reverse': if not arglist: dm = dm[::-1] else: dm[colname] = col[::-1] elif cmd == u'roll': self._require_arglist(cmd, arglist) steps = arglist[0] if not isinstance(steps, int): raise osexception(u'roll steps should be numeric') if len(arglist) == 1: dm = dm[-steps:] << dm[:-steps] else: dm[colname] = list(col[-steps:]) + list(col[:-steps]) elif cmd == u'weight': self._require_arglist(cmd, arglist) dm = operations.weight(col) return dm
def _create_live_datamatrix(self): """ desc: Builds a live DataMatrix. That is, it takes the orignal DataMatrix and applies all the operations as specified. returns: desc: A live DataMatrix. type: DataMatrix """ if self.var.source == u'table': src_dm = self.dm else: from datamatrix import io src = self.experiment.pool[self.var.source_file] if src.endswith(u'.xlsx'): try: src_dm = io.readxlsx(src) except Exception as e: raise osexception(u'Failed to read .xlsx file: %s' % src, exception=e) else: try: src_dm = io.readtxt(src) except Exception as e: raise osexception(u'Failed to read text file: %s' % src, exception=e) length = int(len(src_dm) * self.var.repeat) dm = DataMatrix(length=0) while len(dm) < length: i = min(length - len(dm), len(src_dm)) if self.var.order == u'random': dm <<= operations.shuffle(src_dm)[:i] else: dm <<= src_dm[:i] if self.var.order == u'random': dm = operations.shuffle(dm) if self.ef is not None: self.ef.dm = dm dm = self.ef.enforce() for cmd, arglist in self.operations: # The column name is always specified last, or not at all if arglist: try: colname = arglist[-1] col = dm[colname] except: raise osexception(u'Column %s does not exist' % arglist[-1]) if cmd == u'fullfactorial': dm = operations.fullfactorial(dm) elif cmd == u'shuffle': if not arglist: dm = operations.shuffle(dm) else: dm[colname] = operations.shuffle(col) elif cmd == u'shuffle_horiz': if not arglist: dm = operations.shuffle_horiz(dm) else: dm = operations.shuffle_horiz( *[dm[_colname] for _colname in arglist]) elif cmd == u'slice': self._require_arglist(cmd, arglist, minlen=2) dm = dm[arglist[0]:arglist[1]] elif cmd == u'sort': self._require_arglist(cmd, arglist) dm[colname] = operations.sort(col) elif cmd == u'sortby': self._require_arglist(cmd, arglist) dm = operations.sort(dm, by=col) elif cmd == u'reverse': if not arglist: dm = dm[::-1] else: dm[colname] = col[::-1] elif cmd == u'roll': self._require_arglist(cmd, arglist) steps = arglist[0] if not isinstance(steps, int): raise osexception(u'roll steps should be numeric') if len(arglist) == 1: dm = dm[-steps:] << dm[:-steps] else: dm[colname] = list(col[-steps:]) + list(col[:-steps]) elif cmd == u'weight': self._require_arglist(cmd, arglist) dm = operations.weight(col) return dm
def _create_live_datamatrix(self): """ desc: Builds a live DataMatrix. That is, it takes the orignal DataMatrix and applies all the operations as specified. returns: desc: A live DataMatrix. type: DataMatrix """ if self.var.source == u'table': src_dm = self.dm else: from datamatrix import io src = self.experiment.pool[self.var.source_file] if src.endswith(u'.xlsx'): try: src_dm = io.readxlsx(src) except Exception as e: raise osexception(u'Failed to read .xlsx file: %s' % src, exception=e) else: try: src_dm = io.readtxt(src) except Exception as e: raise osexception(u'Failed to read text file: %s' % src, exception=e) length = int(len(src_dm) * self.var.repeat) dm = DataMatrix(length=0) while len(dm) < length: i = min(length-len(dm), len(src_dm)) if self.var.order == u'random': dm <<= operations.shuffle(src_dm)[:i] else: dm <<= src_dm[:i] if self.var.order == u'random': dm = operations.shuffle(dm) if self.ef is not None: self.ef.dm = dm dm = self.ef.enforce() for cmd, arglist in self.operations: # The column name is always specified last, or not at all if arglist: try: colname = arglist[-1] col = dm[colname] except: raise osexception( u'Column %s does not exist' % arglist[-1]) if cmd == u'fullfactorial': dm = operations.fullfactorial(dm) elif cmd == u'shuffle': if not arglist: dm = operations.shuffle(dm) else: dm[colname] = operations.shuffle(col) elif cmd == u'shuffle_horiz': if not arglist: dm = operations.shuffle_horiz(dm) else: dm = operations.shuffle_horiz( *[dm[_colname] for _colname in arglist]) elif cmd == u'slice': self._require_arglist(cmd, arglist, minlen=2) dm = dm[arglist[0]: arglist[1]] elif cmd == u'sort': self._require_arglist(cmd, arglist) dm[colname] = operations.sort(col) elif cmd == u'sortby': self._require_arglist(cmd, arglist) dm = operations.sort(dm, by=col) elif cmd == u'reverse': if not arglist: dm = dm[::-1] else: dm[colname] = col[::-1] elif cmd == u'roll': self._require_arglist(cmd, arglist) steps = arglist[0] if not isinstance(steps, int): raise osexception(u'roll steps should be numeric') if len(arglist) == 1: dm = dm[-steps:] << dm[:-steps] else: dm[colname] = list(col[-steps:]) + list(col[:-steps]) elif cmd == u'weight': self._require_arglist(cmd, arglist) dm = operations.weight(col) return dm
def _create_live_datamatrix(self): """ desc: Builds a live DataMatrix. That is, it takes the orignal DataMatrix and applies all the operations as specified. returns: desc: A live DataMatrix. type: DataMatrix """ if self.var.source == u'table': src_dm = self.dm else: from datamatrix import io src = self.experiment.pool[self.var.source_file] if src.endswith(u'.xlsx'): try: src_dm = io.readxlsx(src) except Exception as e: raise osexception(u'Failed to read .xlsx file: %s' % src, exception=e) else: try: src_dm = io.readtxt(src) except Exception as e: raise osexception( u'Failed to read text file (perhaps it has the wrong format or it is not utf-8 encoded): %s' % src, exception=e) for column_name in src_dm.column_names: if not self.syntax.valid_var_name(column_name): raise osexception( u'The loop table contains an invalid column name: 'u'\'%s\'' \ % column_name) # The number of repeats should be numeric. If not, then give an error. # This can also occur when generating a preview of a loop table if # repeat is variable. if not isinstance(self.var.repeat, (int, float)): raise osexception( u'Don\'t know how to generate a DataMatrix for "%s" repeats' \ % self.var.repeat) length = int(len(src_dm) * self.var.repeat) dm = DataMatrix(length=0) while len(dm) < length: i = min(length - len(dm), len(src_dm)) if self.var.order == u'random': dm <<= operations.shuffle(src_dm)[:i] else: dm <<= src_dm[:i] if self.var.order == u'random': dm = operations.shuffle(dm) if self.ef is not None: self.ef.dm = dm dm = self.ef.enforce() for cmd, arglist in self.operations: # The column name is always specified last, or not at all if arglist: try: colname = arglist[-1] col = dm[colname] except: raise osexception(u'Column %s does not exist' % arglist[-1]) if cmd == u'fullfactorial': dm = operations.fullfactorial(dm) elif cmd == u'shuffle': if not arglist: dm = operations.shuffle(dm) else: dm[colname] = operations.shuffle(col) elif cmd == u'shuffle_horiz': if not arglist: dm = operations.shuffle_horiz(dm) else: dm = operations.shuffle_horiz( *[dm[_colname] for _colname in arglist]) elif cmd == u'slice': self._require_arglist(cmd, arglist, minlen=2) dm = dm[arglist[0]:arglist[1]] elif cmd == u'sort': self._require_arglist(cmd, arglist) dm[colname] = operations.sort(col) elif cmd == u'sortby': self._require_arglist(cmd, arglist) dm = operations.sort(dm, by=col) elif cmd == u'reverse': if not arglist: dm = dm[::-1] else: dm[colname] = col[::-1] elif cmd == u'roll': self._require_arglist(cmd, arglist) steps = arglist[0] if not isinstance(steps, int): raise osexception(u'roll steps should be numeric') if len(arglist) == 1: dm = dm[-steps:] << dm[:-steps] else: dm[colname] = list(col[-steps:]) + list(col[:-steps]) elif cmd == u'weight': self._require_arglist(cmd, arglist) dm = operations.weight(col) return dm
exp_phase = block.split("_")[-1] dst = "trial list %s/block loops TNT %s" % (exp_phase, exp_phase) for pp_ID in range(1, 71): main_dm = io.readtxt(src_exp) # Read in fillers: dm = io.readtxt(src_fillers) dm_first, dm_last, dm_remaining = helpers.splitFillers(dm) # Merge the remaining fillers with the main dm: merged_dm = main_dm << dm_remaining # Shuffle the merged dm: merged_dm = ops.shuffle(merged_dm) # Create an Enforce object, and add constraint ef = Enforce(merged_dm) ef.add_constraint(MaxRep, cols=[merged_dm.Emotion], maxrep=3) ef.add_constraint(MinDist, cols=[merged_dm.Trial_ID], mindist=2) # Enforce the constraints merged_dm = ef.enforce() # Add the first fillers: merged_dm = dm_first << merged_dm # Add the last fillers: merged_dm = merged_dm << dm_last # Add exp ID to the dm:
def _create_live_datamatrix(self): """ desc: Builds a live DataMatrix. That is, it takes the orignal DataMatrix and applies all the operations as specified. returns: desc: A live DataMatrix. type: DataMatrix """ src_dm = self.dm if self.var.source == u'table' else self._read_file() for column_name in src_dm.column_names: if not self.syntax.valid_var_name(column_name): raise osexception( u'The loop table contains an invalid column name: ' u'\'%s\'' % column_name) # The number of repeats should be numeric. If not, then give an error. # This can also occur when generating a preview of a loop table if # repeat is variable. if not isinstance(self.var.repeat, (int, float)): raise osexception( u'Don\'t know how to generate a DataMatrix for "%s" repeats' % self.var.repeat) length = int(len(src_dm) * self.var.repeat) dm = DataMatrix(length=0) while len(dm) < length: i = min(length - len(dm), len(src_dm)) if self.var.order == u'random': dm <<= operations.shuffle(src_dm)[:i] else: dm <<= src_dm[:i] if self.var.order == u'random': dm = operations.shuffle(dm) # Constraints come before loop operations if self._constraints: self.ef = Enforce(dm) for constraint_cls, colname, kwargs in self._constraints: self.ef.add_constraint(constraint_cls, cols=dm[colname], **kwargs) dm = self.ef.enforce() # Operations come last for cmd, arglist in self._operations: # The column name is always specified last, or not at all if arglist: try: colname = arglist[-1] col = dm[colname] except: raise osexception(u'Column %s does not exist' % arglist[-1]) if cmd == u'fullfactorial': dm = operations.fullfactorial(dm) elif cmd == u'shuffle': if not arglist: dm = operations.shuffle(dm) else: dm[colname] = operations.shuffle(col) elif cmd == u'shuffle_horiz': if not arglist: dm = operations.shuffle_horiz(dm) else: # There can be multiple column names, so we need to check # if all of them exist, rather than only the last one as # we did above. for _colname in arglist: try: dm[_colname] except: raise osexception(u'Column %s does not exist' % _colname) dm = operations.shuffle_horiz( *[dm[_colname] for _colname in arglist]) elif cmd == u'slice': self._require_arglist(cmd, arglist, minlen=2) dm = dm[arglist[0]:arglist[1]] elif cmd == u'sort': self._require_arglist(cmd, arglist) dm[colname] = operations.sort(col) elif cmd == u'sortby': self._require_arglist(cmd, arglist) dm = operations.sort(dm, by=col) elif cmd == u'reverse': if not arglist: dm = dm[::-1] else: dm[colname] = col[::-1] elif cmd == u'roll': self._require_arglist(cmd, arglist) steps = arglist[0] if not isinstance(steps, int): raise osexception(u'roll steps should be numeric') if len(arglist) == 1: dm = dm[-steps:] << dm[:-steps] else: dm[colname] = list(col[-steps:]) + list(col[:-steps]) elif cmd == u'weight': self._require_arglist(cmd, arglist) try: dm = operations.weight(col) except TypeError: raise osexception( u'weight values should be non-negative numeric values') return dm