def __get_response_transition() -> Factor: color = Factor("color", ["red", "blue", "green"]) motion = Factor("motion", ["up", "down"]) task = Factor("task", ["color", "motion"]) # Response Definition def response_left(task, color, motion): return (task == "color" and color == "red") or \ (task == "motion" and motion == "up") def response_right(task, color, motion): return not response_left(task, color, motion) response = Factor("response", [ DerivedLevel("left", WithinTrial(response_left, [task, color, motion])), DerivedLevel("right", WithinTrial(response_right, [task, color, motion])) ]) return Factor("response transition", [ DerivedLevel( "repeat", Transition(lambda responses: responses[0] == responses[1], [response])), DerivedLevel( "switch", Transition(lambda responses: responses[0] != responses[1], [response])) ])
def test_generate_argument_list_with_transition(): color_repeats_level = DerivedLevel( "yes", Transition(lambda colors: colors[0] == colors[1], [color])) x_product = color_repeats_level.get_dependent_cross_product() assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[0]) == [['red', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[1]) == [['red', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[2]) == [['blue', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[3]) == [['blue', 'blue']] double_repeat_level = DerivedLevel( "name", Transition(lambda colors, texts: True, [color, text])) x_product = double_repeat_level.get_dependent_cross_product() assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[0]) == [['red', 'red'], ['red', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[1]) == [['red', 'red'], ['red', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[2]) == [['red', 'red'], ['blue', 'red']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[3]) == [['red', 'red'], ['blue', 'blue']] assert DerivationProcessor.generate_argument_list( color_repeats_level, x_product[15]) == [['blue', 'blue'], ['blue', 'blue']]
def test_factor_validation(): Factor("factor name", ["level 1", "level 2"]) # Non-string name with pytest.raises(ValueError): Factor(56, ["level "]) # Non-list levels with pytest.raises(ValueError): Factor("name", 42) # Empty list with pytest.raises(ValueError): Factor("name", []) # Invalid level type with pytest.raises(ValueError): Factor("name", [1, 2]) # Valid level types, but not uniform. with pytest.raises(ValueError): Factor("name", ["level1", con_level]) # Derived levels with non-uniform window types with pytest.raises(ValueError): Factor("name", [ con_level, DerivedLevel( "other", Transition(lambda colors: colors[0] == colors[1], [color])) ])
def test_shift_window(): assert DerivationProcessor.shift_window([[0, 0], [1, 1]], WithinTrial(lambda x: x, None), 0) == [[0, 0], [1, 1]] assert DerivationProcessor.shift_window([[0, 0], [1, 1]], Transition(lambda x: x, None), 4) == [[0, 4], [1, 5]] assert DerivationProcessor.shift_window([[0, 2, 4], [1, 3, 5]], Window(lambda x: x, [1, 2], 2, 3), 6) == [[0, 8, 16], [1, 9, 17]] assert DerivationProcessor.shift_window([[1, 1, 1, 1], [2, 2, 2, 2]], Window(lambda x: x, [1, 2], 2, 4), 10) == \ [[1, 11, 21, 31], [2, 12, 22, 32]]
def test_factor_validation(): Factor("factor name", ["level 1", "level 2"]) Factor("name", [1, 2]) # Duplicated name with pytest.raises(ValueError): Factor("name", ["a", "b", "a"]) with pytest.raises(ValueError): Factor("name", [ DerivedLevel("a", WithinTrial(op.eq, [color, text])), ElseLevel("a") ]) # Non-string name with pytest.raises(ValueError): Factor(56, ["level "]) # Non-list levels with pytest.raises(TypeError): Factor("name", 42) # Empty list with pytest.raises(ValueError): Factor("name", []) # Valid level types, but not uniform. with pytest.raises(ValueError): Factor("name", ["level1", con_level]) # Derived levels with non-uniform window types with pytest.raises(ValueError): Factor("name", [ con_level, DerivedLevel("other", WithinTrial(lambda color: color, [color])) ]) # Derived levels with different window arguments with pytest.raises(ValueError): Factor("name", [ con_level, DerivedLevel( "other", Transition(lambda colors: colors[0] == colors[1], [color])) ])
def test_derivation_with_three_level_transition(): f = Factor("f", ["a", "b", "c"]) f_transition = Factor("transition", [ DerivedLevel("aa", Transition(lambda c: c[0] == "a" and c[1] == "a", [f])), DerivedLevel("ab", Transition(lambda c: c[0] == "a" and c[1] == "b", [f])), DerivedLevel("ac", Transition(lambda c: c[0] == "a" and c[1] == "c", [f])), DerivedLevel("ba", Transition(lambda c: c[0] == "b" and c[1] == "a", [f])), DerivedLevel("bb", Transition(lambda c: c[0] == "b" and c[1] == "b", [f])), DerivedLevel("bc", Transition(lambda c: c[0] == "b" and c[1] == "c", [f])), DerivedLevel("ca", Transition(lambda c: c[0] == "c" and c[1] == "a", [f])), DerivedLevel("cb", Transition(lambda c: c[0] == "c" and c[1] == "b", [f])), DerivedLevel("cc", Transition(lambda c: c[0] == "c" and c[1] == "c", [f])), ]) block = fully_cross_block([f, f_transition], [f], []) # a-a derivation d = Derivation(9, [[0, 3]], f_transition) backend_request = BackendRequest(28) d.apply(block, backend_request) (expected_cnf, expected_fresh) = to_cnf_tseitin( And([Iff(10, Or([And([1, 4])])), Iff(19, Or([And([4, 7])]))]), 28) assert backend_request.fresh == expected_fresh assert backend_request.cnfs == [expected_cnf]
red_text = get_level_from_name(text, "red") blue_text = get_level_from_name(text, "blue") con_factor_within_trial = Factor("congruent?", [ DerivedLevel("con", WithinTrial(op.eq, [color, text])), DerivedLevel("inc", WithinTrial(op.ne, [color, text])) ]) con_factor_window = Factor("congruent?", [ DerivedLevel("con", Window(op.eq, [color, text], 1, 1)), DerivedLevel("inc", Window(op.ne, [color, text], 1, 1)) ]) color_repeats_factor = Factor("repeated color?", [ DerivedLevel("yes", Transition(lambda colors: colors[0] == colors[1], [color])), DerivedLevel("no", Transition(lambda colors: colors[0] != colors[1], [color])) ]) def test_validate_accepts_basic_factors(): block = fully_cross_block([color, text], [color, text], []) UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__validate( block) def test_validate_accepts_derived_factors_with_simple_windows(): block = fully_cross_block([color, text, con_factor_within_trial], [color, text], []) UniformCombinatoricSamplingStrategy._UniformCombinatoricSamplingStrategy__validate(
from sweetpea import fully_cross_block, __decode from sweetpea.primitives import Factor, DerivedLevel, WithinTrial, Transition, Window from sweetpea.constraints import NoMoreThanKInARow from sweetpea.logic import to_cnf_tseitin # Common variables for stroop. color = Factor("color", ["red", "blue"]) text = Factor("text", ["red", "blue"]) con_level = DerivedLevel("con", WithinTrial(op.eq, [color, text])) inc_level = DerivedLevel("inc", WithinTrial(op.ne, [color, text])) con_factor = Factor("congruent?", [con_level, inc_level]) color_repeats_factor = Factor("color repeats?", [ DerivedLevel("yes", Transition(lambda colors: colors[0] == colors[1], [color])), DerivedLevel("no", Transition(lambda colors: colors[0] != colors[1], [color])) ]) text_repeats_factor = Factor("text repeats?", [ DerivedLevel("yes", Transition(lambda colors: colors[0] == colors[1], [text])), DerivedLevel("no", Transition(lambda colors: colors[0] != colors[1], [text])) ]) congruent_bookend = Factor("congruent bookend?", [ DerivedLevel("yes", Window(lambda color, text: color == text, [color, text], 1, 3)), DerivedLevel("no", Window(lambda color, text: color != text, [color, text], 1, 3)) ]) design = [color, text, con_factor] crossing = [color, text]
color = Factor("color", ["red", "blue", "green", "brown"]) word = Factor("motion", ["red", "blue", "green", "brown"]) task = Factor("task", ["color naming", "word reading"]) cue = Factor("cue", ["cue 1", "cue 2"]) # DEFINE TASK TRANSITION def task_repeat(tasks): return tasks[0] == tasks[1] def task_switch(tasks): return not task_repeat(tasks) task_transition = Factor("task_transition", [ DerivedLevel("repeat", Transition(task_repeat, [task])), DerivedLevel("switch", Transition(task_switch, [task])) ]) # DEFINE CUE TRANSITION def cue_repeat(cue): return cue[0] == cue[1] def cue_switch(cue): return not cue_repeat(cue) cue_transition = Factor("cue transition", [ DerivedLevel("repeat", Transition(cue_repeat, [cue])), DerivedLevel("switch", Transition(cue_switch, [cue])) ])
import operator as op import pytest from sweetpea.primitives import Factor, DerivedLevel, WithinTrial, Transition, Window color = Factor("color", ["red", "blue"]) text = Factor("text", ["red", "blue"]) con_level = DerivedLevel("con", WithinTrial(op.eq, [color, text])) inc_level = DerivedLevel("inc", WithinTrial(op.ne, [color, text])) con_factor = Factor("congruent?", [con_level, inc_level]) color_repeats_level = DerivedLevel("yes", Transition(op.eq, [color])) color_no_repeat_level = DerivedLevel("no", Transition(op.ne, [color])) color_repeats_factor = Factor("color repeats?", [color_repeats_level, color_no_repeat_level]) color3 = Factor("color3", ["red", "blue", "green"]) yes_fn = lambda colors: colors[0] == colors[1] == colors[2] no_fn = lambda colors: not yes_fn(colors) color3_repeats_factor = Factor("color3 repeats?", [ DerivedLevel("yes", Window(yes_fn, [color3], 3, 1)), DerivedLevel("no", Window(no_fn, [color3], 3, 1)) ]) def test_factor_validation(): Factor("factor name", ["level 1", "level 2"]) # Non-string name
def make_k_diff_level(k): def k_diff(colors, texts): return count_diff(colors, texts) == k return DerivedLevel(str(k), Transition(k_diff, [color, text]))
congruent = DerivedLevel("con", WithinTrial(operator.eq, [color, word])) incongruent = DerivedLevel("inc", WithinTrial(operator.ne, [color, word])) congruence = Factor("congruence", [congruent, incongruent]) one_con_at_a_time = at_most_k_in_a_row(1, (congruence, congruent)) def one_diff(colors, words): if (colors[0] == colors[1]): return words[0] != words[1] else: return words[0] == words[1] def both_diff(colors, words): return not one_diff(colors, words) one = DerivedLevel("one", Transition(one_diff, [color, word])) both = DerivedLevel("both", Transition(both_diff, [color, word])) changed = Factor("changed", [one, both]) block = fully_cross_block([color, word, congruence, changed], [color, word, changed], []) experiments = synthesize_trials_non_uniform(block, 1) print_experiments(block, experiments)
- response (left, right) - congruency transition (congruent-congruent, congruent-incongruent, congruent-neutral, incongruent-congruent, incongruent-incongruent, incongruent-neutral, neutral-congruent, neutral-incongruent, neutral-neutral) constraints: - counterbalancing congruency x reward x response x congruency transition (3*2*2*9 = 108) - counterbalancing all transitions <-- ???? Total number of trials: around 120 """ congruency = Factor("congruency", ["congruent", "incongruent", "neutral"]) reward = Factor("reward", ["rewarded", "non-rewarded"]) response = Factor("response", ["building", "house"]) congruency_transition = Factor("congruency_transition", [ DerivedLevel( "c-c", Transition(lambda c: c[0] == "congruent" and c[1] == "congruent", [congruency])), DerivedLevel( "c-i", Transition(lambda c: c[0] == "congruent" and c[1] == "incongruent", [congruency])), DerivedLevel( "c-n", Transition(lambda c: c[0] == "congruent" and c[1] == "neutral", [congruency])), DerivedLevel( "i-c", Transition(lambda c: c[0] == "incongruent" and c[1] == "congruent", [congruency])), DerivedLevel( "i-i", Transition(lambda c: c[0] == "incongruent" and c[1] == "incongruent",
((color == "blue") and (motion == "down")) def color_motion_incongruent(color, motion): return not color_motion_congruent(color, motion) congruency = Factor("congruency", [ DerivedLevel("con", WithinTrial(color_motion_congruent, [color, motion])), DerivedLevel("inc", WithinTrial(color_motion_incongruent, [color, motion])) ]) # Task Transition task_transition = Factor("task Transition", [ DerivedLevel("repeat", Transition(lambda tasks: tasks[0] == tasks[1], [task])), DerivedLevel("switch", Transition(lambda tasks: tasks[0] != tasks[1], [task])) ]) # Response Transition response_transition = Factor("response Transition", [ DerivedLevel( "repeat", Transition(lambda responses: responses[0] == responses[1], [response])), DerivedLevel( "switch", Transition(lambda responses: responses[0] != responses[1], [response])) ])
import operator as op from sweetpea.internal import get_all_level_names, intersperse from sweetpea.primitives import Factor, DerivedLevel, Transition color = Factor("color", ["red", "blue"]) text = Factor("text", ["red", "blue", "green"]) color_repeats_level = DerivedLevel("yes", Transition(lambda colors: colors[0] == colors[1], [color])) color_no_repeat_level = DerivedLevel("no", Transition(lambda colors: colors[0] != colors[1], [color])) color_repeats_factor = Factor("color repeats?", [color_repeats_level, color_no_repeat_level]) def test_get_all_level_names(): assert get_all_level_names([color, text]) == [('color', 'red'), ('color', 'blue'), ('text', 'red'), ('text', 'blue'), ('text', 'green')] assert get_all_level_names([color_repeats_factor]) == [('color repeats?', 'yes'), ('color repeats?', 'no')] def test_intersperse(): assert list(intersperse('', ['yes', 'no', 'yes'])) == \ ['yes', '', 'no', '', 'yes'] assert list(intersperse('', ['yes', 'no', 'yes'], 2)) == \ ['yes', '', '', 'no', '', '', 'yes']
DerivedLevel("right", WithinTrial(response_right, [color])), ]) # DEFINE RESPONSE TRANSITION FACTOR def response_repeat(response): return response[0] == response[1] def response_switch(response): return not response_repeat(response) resp_transition = Factor("response_transition", [ DerivedLevel("repeat", Transition(response_repeat, [response])), DerivedLevel("switch", Transition(response_switch, [response])) ]) # DEFINE SEQUENCE CONSTRAINTS k = 7 constraints = [NoMoreThanKInARow(k, resp_transition)] # DEFINE EXPERIMENT design = [color, word, congruency, resp_transition, response] crossing = [color, word, resp_transition] block = fully_cross_block(design, crossing, constraints) # SOLVE
. if color-motion then task Transition = switch if motion-color then task Transition = switch """ def task_repeat(tasks): return tasks[0] == tasks[1] def task_switch(tasks): return not task_repeat(tasks) task_transition = Factor("task_transition", [ derived_level("repeat", Transition(task_repeat, [task])), derived_level("switch", Transition(task_switch, [task])) ]) """ response Transition (repetition, switch). dependent Factor of correct response: if left-left then task Transition = repetition if right-right then task Transition = repetition . if left-right then task Transition = switch if right-left then task Transition = switch """ def response_repeat(responses): return responses[0] == responses[1]
DerivedLevel("up", WithinTrial(response_up, [color])), DerivedLevel("down", WithinTrial(response_down, [color])), DerivedLevel("left", WithinTrial(response_left, [color])), DerivedLevel("right", WithinTrial(response_right, [color])), ]) # DEFINE WORD TRANSITION FACTOR def word_repeat(word): return word[0] == word[1] def word_switch(word): return not word_repeat(word) word_transition = Factor("word_transition", [ DerivedLevel("repeat", Transition(word_repeat, [word])), DerivedLevel("switch", Transition(word_switch, [word])) ]) # DEFINE COLOR TRANSITION FACTOR def color_repeat(color): return color[0] == color[1] def color_switch(color): return not color_repeat(color) color_transition = Factor("color_transition", [ DerivedLevel("repeat", Transition(color_repeat, [color])), DerivedLevel("switch", Transition(color_switch, [color])) ])
def ntr_con(congruency): return congruency[0] == "neutral" and congruency[1] == "congruent" def ntr_inc(congruency): return congruency[0] == "neutral" and congruency[1] == "incongruent" def ntr_ntr(congruency): return congruency[0] == "neutral" and congruency[1] == "neutral" congruency_transition = Factor("congruency_transition", [ DerivedLevel("congruent-congruent", Transition(con_con, [congruency])), DerivedLevel("congruent-incongruent", Transition(con_inc, [congruency])), DerivedLevel("congruent-neutral", Transition(con_ntr, [congruency])), DerivedLevel("incongruent-congruent", Transition(inc_con, [congruency])), DerivedLevel("incongruent-incongruent", Transition(inc_inc, [congruency])), DerivedLevel("incongruent-neutral", Transition(inc_ntr, [congruency])), DerivedLevel("neutral-congruent", Transition(ntr_con, [congruency])), DerivedLevel("neutral-incongruent", Transition(ntr_inc, [congruency])), DerivedLevel("neutral-neutral", Transition(ntr_ntr, [congruency])) ]) # DEFINE RESPONSE TRANSITION FACTOR def response_repeat(responses): return responses[0] == responses[1]
import operator as op from sweetpea.internal import get_all_external_level_names, intersperse from sweetpea.primitives import Factor, DerivedLevel, Transition color = Factor("color", ["red", "blue"]) text = Factor("text", ["red", "blue", "green"]) color_repeats_level = DerivedLevel( "yes", Transition(lambda colors: colors[0] == colors[1], [color])) color_no_repeat_level = DerivedLevel( "no", Transition(lambda colors: colors[0] != colors[1], [color])) color_repeats_factor = Factor("color repeats?", [color_repeats_level, color_no_repeat_level]) def test_get_all_external_level_names(): assert get_all_external_level_names([color, text]) == [('color', 'red'), ('color', 'blue'), ('text', 'red'), ('text', 'blue'), ('text', 'green')] assert get_all_external_level_names([color_repeats_factor ]) == [('color repeats?', 'yes'), ('color repeats?', 'no')] def test_intersperse(): assert list(intersperse('', ['yes', 'no', 'yes'])) == \ ['yes', '', 'no', '', 'yes']
# Congruency Definition def color_motion_congruent(color, motion): return ((color == "red") and (motion == "up")) or \ ((color == "blue") and (motion == "down")) def color_motion_incongruent(color, motion): return not color_motion_congruent(color, motion) congruency = Factor("congruency", [ DerivedLevel("con", WithinTrial(color_motion_congruent, [color, motion])), DerivedLevel("inc", WithinTrial(color_motion_incongruent, [color, motion])) ]) # Task Transition task_transition = Factor("task transition", [ DerivedLevel("repeat", Transition(lambda tasks: tasks[0] == tasks[1], [task])), DerivedLevel("switch", Transition(lambda tasks: tasks[0] != tasks[1], [task])) ]) # Response Transition response_transition = Factor("response transition", [ DerivedLevel("repeat", Transition(lambda responses: responses[0] == responses[1], [response])), DerivedLevel("switch", Transition(lambda responses: responses[0] != responses[1], [response])) ]) def __shuffled_design_sample(): perms = list(permutations([color, motion, task, response, congruency, task_transition, response_transition])) shuffle(perms) return perms[:6]
color = Factor("color", color_list) text = Factor("text", color_list) def one_different(colors, texts): if (colors[0] == colors[1]): return texts[0] != texts[1] else: return texts[0] == texts[1] def other_different(colors, texts): return not one_different(colors, texts) one_level = DerivedLevel("one", Transition(one_different, [color, text])) other_level = DerivedLevel("other", Transition(other_different, [color, text])) change = Factor("change", [one_level, other_level]) design = [color, text, change] crossing = [color, text] block = fully_cross_block(design, crossing, []) # Encoding diagram minus 1 # ----------------------------------------------- # | Trial | color | text | change | # | # | red green | red green | one other | # ----------------------------------------------- # | 1 | 0 1 | 2 3 | | # | 2 | 4 5 | 6 7 | 16 17 |
(task == "motion" and motion == "up") def response_right(task, color, motion): return not response_left(task, color, motion) response = Factor("response", [ DerivedLevel("left", WithinTrial(response_left, [task, color, motion])), DerivedLevel("right", WithinTrial(response_right, [task, color, motion])) ]) response_transition = Factor("response transition", [ DerivedLevel( "repeat", Transition(lambda responses: responses[0] == responses[1], [response])), DerivedLevel( "switch", Transition(lambda responses: responses[0] != responses[1], [response])) ]) def test_generate_derivations_with_transition_that_depends_on_derived_levels(): block = fully_cross_block( [color, motion, task, response, response_transition], [color, motion, task], []) derivations = DerivationProcessor.generate_derivations(block) assert Derivation(64, [[6, 14], [7, 15]], response_transition) in derivations assert Derivation(65, [[6, 15], [7, 14]],
def con_inc(congruency): return congruency[0] == "congruent" and congruency[1] == "incongruent" def inc_con(congruency): return congruency[0] == "incongruent" and congruency[1] == "congruent" def inc_inc(congruency): return congruency[0] == "incongruent" and congruency[1] == "incongruent" congruency_transition = Factor("congruency Transition", [ DerivedLevel("congruent-congruent", Transition(con_con, [congruency])), DerivedLevel("congruent-incongruent", Transition(con_inc, [congruency])), DerivedLevel("incongruent-congruent", Transition(inc_con, [congruency])), DerivedLevel("incongruent-incongruent", Transition(inc_inc, [congruency])), ]) # DEFINE FLANKER RESPONSE FACTOR def flanker_left(target_direction, congruency): return ((target_direction == "1" and congruency == "congruent") or (target_direction == "-1" and congruency == "incongruent")) def flanker_right(target_direction, congruency): return not flanker_left(target_direction, congruency)