def generate_argument_list(level: DerivedLevel, tup: Tuple) -> List:
     level_values = list(map(lambda t: t[1], tup))
     # For windows with a width of 1, we just pass the arguments directly, rather than putting them in lists.
     if level.window.width == 1:
         return level_values
     else:
         return list(chunk_list(level_values, level.window.width))
 def generate_argument_list(level: DerivedLevel, tup: Tuple[Level, ...]) -> List:
     # User-supplied string level names are the arguments for the user-supplied derivation functions
     level_strings = [level.name for level in tup]
     # For windows with a width of 1, we just pass the arguments directly, rather than putting them in lists.
     if level.window.width == 1:
         return level_strings
     else:
         return list(chunk_list(level_strings, level.window.width))
Example #3
0
 def generate_argument_list(level: DerivedLevel, tup: Tuple) -> List:
     # User-supplied string level names are the arguments for the user-supplied derivation functions
     level_strings = list(map(lambda t: get_external_level_name(t[1]), tup))
     # For windows with a width of 1, we just pass the arguments directly, rather than putting them in lists.
     if level.window.width == 1:
         return level_strings
     else:
         return list(chunk_list(level_strings, level.window.width))
Example #4
0
    def apply(block: Block, backend_request: BackendRequest) -> None:
        next_var = 1
        for _ in range(block.trials_per_sample()):
            for f in filter(lambda f: not f.has_complex_window, block.design):
                number_of_levels = len(f.levels)
                new_request = LowLevelRequest("EQ", 1, list(range(next_var, next_var + number_of_levels)))
                backend_request.ll_requests.append(new_request)
                next_var += number_of_levels

        for f in filter(lambda f: f.has_complex_window, block.design):
            variables_for_factor = block.variables_for_factor(f)
            var_list = list(map(lambda n: n + next_var, range(variables_for_factor)))
            chunks = list(chunk_list(var_list, len(f.levels)))
            backend_request.ll_requests += list(map(lambda v: LowLevelRequest("EQ", 1, v), chunks))
            next_var += variables_for_factor
Example #5
0
    def shift_window(idxs: List[List[int]], window: Union[WithinTrial,
                                                          Transition, Window],
                     trial_size: int) -> List[List[int]]:
        if window.width == 1:
            return idxs

        shifted_idxs = cast(List[List[int]], [])
        shifted_sublists = cast(List[List[int]], [])
        argc = 1 if window.argc == None else window.argc
        for idx_list in idxs:
            sublist_size = len(idx_list) // argc
            sublists = chunk_list(idx_list, sublist_size)
            shifted_sublists = [
                reduce(lambda l, idx: l + [idx + len(l) * trial_size],
                       idx_list, []) for idx_list in sublists
            ]
            shifted_idxs.append(list(reduce(op.add, shifted_sublists, [])))

        return shifted_idxs
    def shift_window(indices: List[List[int]],
                     window: DerivationWindow,
                     trial_size: int
                     ) -> List[List[int]]:
        """This is a helper function that shifts the indices of
        :func:`.DerivationProcessor.generate_derivations`.

        E.g., if it's a ``Transition(op.eq, [color, color])`` (i.e., "repeat"
        color transition) then the indices for the levels of color would be
        like ``(0, 0)``, ``(1, 1)``, but actually, the window size for a
        transition is ``2``, so what we really want is the indices ``(0, 5)``,
        ``(1, 6)`` (assuming there are 4 levels in the design).

        So this helper function shifts over indices that were meant to be
        interpreted as being in a subsequent trial.
        """
        if window.width == 1:
            return indices

        # shifted_indices: List[List[int]] = []
        # shifted_sublists: List[List[int]] = []

        # factor_count = len(window.factors)

        # for index_list in indices:
        #     sublist_size = len(index_list) // factor_count
        #     sublists = chunk_list(index_list, sublist_size)
        #     shifted_sublists =

        shifted_idxs = cast(List[List[int]], [])
        shifted_sublists = cast(List[List[int]], [])
        argc = window.initial_factor_count
        for idx_list in indices:
            sublist_size = len(idx_list) // argc
            sublists = chunk_list(idx_list, sublist_size)
            shifted_sublists = [reduce(lambda l, idx: l + [idx + len(l) * trial_size], idx_list, [])
                                for idx_list in sublists]
            shifted_idxs.append(list(reduce(op.add, shifted_sublists, [])))

        return shifted_idxs
    def generate_derivations(block: Block) -> List[Derivation]:
        """Usage::

            >>> import operator as op
            >>> color = Factor("color", ["red", "blue"])
            >>> text  = Factor("text",  ["red", "blue"])
            >>> conLevel  = DerivedLevel("con", WithinTrial(op.eq, [color, text]))
            >>> incLevel  = DerivedLevel("inc", WithinTrial(op.ne, [color, text]))
            >>> conFactor = Factor("congruent?", [conLevel, incLevel])
            >>> design = [color, text, conFactor]
            >>> crossing = [color, text]
            >>> block = fully_cross_block(design, crossing, [])
            >>> DerivationProcessor.generate_derivations(block)
            [Derivation(derivedIdx=4, dependentIdxs=[[0, 2], [1, 3]]), Derivation(derivedIdx=5, dependentIdxs=[[0, 3], [1, 2]])]

        In the example above, the indicies of the design are:

        ===  =============
        idx  level
        ===  =============
        0    color:red
        1    color:blue
        2    text:red
        3    text:blue
        4    conFactor:con
        5    conFactor:inc
        ===  =============

        So the tuple ``(4, [[0,2], [1,3]])`` represents the information that
        the derivedLevel con is true iff ``(color:red && text:red) ||
        (color:blue && text:blue)`` by pairing the relevant indices together.

        :rtype:
            returns a list of tuples. Each tuple is structured as:
            ``(index of the derived level, list of dependent levels)``
        """
        derived_factors: List[DerivedFactor] = [factor for factor in block.design if isinstance(factor, DerivedFactor)]
        accum = []

        for factor in derived_factors:
            according_level: Dict[Tuple[Any, ...], DerivedLevel] = {}
            for level in factor.levels:
                cross_product: List[Tuple[Level, ...]] = level.get_dependent_cross_product()
                valid_tuples: List[Tuple[Level, ...]] = []
                for level_tuple in cross_product:
                    names = [level.name for level in level_tuple]
                    if level.window.width != 1:
                        # NOTE: mypy doesn't like this, but I'm not rewriting
                        #       it right now. Need to replace `chunk_list` with
                        #       a better version.
                        names = list(chunk_list(names, level.window.width))  # type: ignore
                    result = level.window.predicate(*names)
                    if not isinstance(result, bool):
                        raise ValueError(f"Expected derivation predicate to return bool; got {type(result)}.")
                    if level.window.predicate(*names):
                        valid_tuples.append(level_tuple)
                        if level_tuple in according_level:
                            raise ValueError(f"Factor {factor.name} matches {according_level[level_tuple].name} and "
                                             f"{level.name} with assignment {names}.")
                        according_level[level_tuple] = level

                if not valid_tuples:
                    print(f"WARNING: There is no assignment that matches factor {factor.name} with level {level.name}.")

                valid_indices = [[block.first_variable_for_level(level.factor, level) for level in valid_tuple]
                                 for valid_tuple in valid_tuples]
                shifted_indices = DerivationProcessor.shift_window(valid_indices,
                                                                   level.window,
                                                                   block.variables_per_trial())
                level_index = block.first_variable_for_level(factor, level)
                accum.append(Derivation(level_index, shifted_indices, factor))
        return accum