def linear_intersection(line_1, line_2): # first establish if lines are given as absolute lengths or origins and angles l1_xy = None l2_xy = None try: if not all(iterable(p) for p in line_1 + line_2): # allow for rotation and clockwise arguments to be passed l1_xy = (line_1[0], point_pos(line_1[0], 9999999, *line_1[1:])) l2_xy = (line_2[0], point_pos(line_2[0], 9999999, *line_2[1:])) except AttributeError: raise ValueError( "Expected each line to be either 2 x,y pairs or and x,y pair and an radial description." ) d_x = (l1_xy[0][0] - l1_xy[1][0], l2_xy[0][0] - l2_xy[1][0]) d_y = (l1_xy[0][1] - l1_xy[1][1], l2_xy[0][1] - l2_xy[1][1]) def determinant(a, b): return a[0] * b[1] - a[1] * b[0] div = determinant(d_x, d_y) if not div: raise Exception('Supplied lines do not intersect.') d = (determinant(*l1_xy[0:2]), determinant(*l2_xy[0:2])) return (determinant(d, d_x) / div, determinant(d, d_y) / div)
def collect_export_data(self, multi_file=True, join_tables=[]): uid = P.unique_identifier participant_ids = self.__master.query( "SELECT `id`, `{0}` FROM `participants`".format(uid)) colnames = [] sub = {P.unique_identifier: 'participant'} # if P.default_participant_fields(_sf) is defined use that, but otherwise use # P.exclude_data_cols since that's the better way of doing things fields = P.default_participant_fields if multi_file else P.default_participant_fields_sf if len(fields) > 0: for field in fields: if iterable(field): sub[field[0]] = field[1] colnames.append(field[0]) else: colnames.append(field) else: for colname in self.__master.table_schemas['participants'].keys(): if colname not in ['id'] + P.exclude_data_cols: colnames.append(colname) for colname in P.append_info_cols: if colname not in self.__master.table_schemas['session_info'].keys( ): err = "Column '{0}' does not exist in the session_info table." raise RuntimeError(err.format(colname)) colnames.append(colname) for t in [P.primary_table] + join_tables: for colname in self.__master.table_schemas[t].keys(): if colname not in ['id', P.id_field_name ] + P.exclude_data_cols: colnames.append(colname) column_names = TAB.join(colnames) for colname in sub.keys(): column_names = column_names.replace(colname, sub[colname]) data = [] for p in participant_ids: primary_t = P.primary_table selected_cols = ",".join(["`" + col + "`" for col in colnames]) q = "SELECT " + selected_cols + " FROM participants " if len(P.append_info_cols ) and 'session_info' in self.__master.table_schemas: info_cols = ",".join(['participant_id'] + P.append_info_cols) q += "JOIN (SELECT " + info_cols + " FROM session_info) AS info " q += "ON participants.id = info.participant_id " for t in [primary_t] + join_tables: q += "JOIN {0} ON participants.id = {0}.participant_id ".format( t) q += " WHERE participants.id = ?" p_data = [] for trial in self.__master.query(q, q_vars=tuple([p[0]])): row_str = TAB.join(utf8(col) for col in trial) p_data.append(row_str) data.append([p[0], p_data]) return [column_names, data]
def remove_boundaries(self, labels): """Removes one or more boundaries from the boundary set. Args: labels (:obj:`List`): A list containing the labels of the boundaries to remove. Raises: KeyError: If any label does not correspond to a boundary within the set. """ if not iterable(labels): labels = [labels] for label in labels: self.__verify_label(label) self.boundaries.pop(label, None)
def which_boundary(self, p, labels=None, ignore=[]): """Determines which boundary (if any) a given point is within. Unlike :meth:`within_boundary`, which checks whether a point is within a `specific` boundary, this method returns the name of the boundary (if any) a given point is within (e.g. 'left_button'). If the point falls within multiple boundaries, the label of the boundary that was added most recently will be returned. By default, the point will be tested against all boundaries in the set. To check only a subset of the boundaries, you can specify the names of the boundaries to check using the ``labels`` argument. Conversely, you can exclude specific boundaries from the search using the ``ignore`` argument. Args: p (:obj:`Tuple` or :obj:`List`): The (x, y) coordinates of the point to test against the set's boundaries. labels (:obj:`List`, optional): A list containing the labels of the boundaries to inspect. Defaults to inspecting all boundaries. ignore (:obj:`List`, optional): A list containing the labels of any boundaries to ignore. Defaults to an empty list (no ignored boundaries). Returns: :obj:`str` or None: The label of the boundary that the point is within, or ``None`` if the point does not fall within any boundary. Raises: KeyError: If any given labels do not correspond to a boundary within the set. ValueError: If the given point is not a valid set of (x, y) coordinates. """ if not labels: labels = list(self.boundaries.keys()) if not iterable(ignore): ignore = [ignore] boundary = None for l in self.boundaries.keys(): if l in ignore or not l in labels: continue self.__verify_label(l) if self.boundaries[l].within(p): boundary = l return boundary
def clear_boundaries(self, preserve=[]): """Removes all boundaries from the boundary set. Args: preserve (:obj:`List`, optional): A list containing the labels of any boundaries that should remain in the set after the clear. Raises: KeyError: If any label does not correspond to a boundary within the set. """ if not iterable(preserve): preserve = [preserve] preserved = OrderedDict() for label in preserve: self.__verify_label(label) for label in self.labels: if label in preserve: preserved[label] = self.boundaries[label] self.boundaries = preserved