#ifndef pz_pose_H #define pz_pose_H /* A "pz_pose_t" is a placement of a fragment in a specified position. */ /* Last edited on 2015-01-20 16:49:37 by stolfilocal */ #include #include #include #include #include typedef struct pz_pose_t { msm_seq_desc_t cvx[2]; /* Two curve indices. */ r4x4_t m; /* Matrix that maps "cvx[0]" so as to fit "cvx[1]". */ } pz_pose_t; /* The curve "cvx[1]" may be (unsigned.ne - 1), to denote an absolute pose, i.e. a transformation to apply to "cvx[0]". */ vec_typedef(pz_pose_vec_t,pz_pose_vec,pz_pose_t); /* An array of {pz_pose_t}. */ pz_pose_t pz_pose_native(unsigned f); /* An absolute pose for "f" with the identity matrix. */ pz_pose_t pz_pose_indeterminate(unsigned f); /* A pose that relates "f" to itself through the identity matrix. */ pz_pose_t pz_pose_inverse(pz_pose_t *P); /* Returns the inverse of "p"'s pose, that is, swaps the two curves and the two matrices. */ pz_pose_t pz_pose_compose(pz_pose_t *P, pz_pose_t *Q); /* Given the pose "P" that makes curve "a" fit curve "b", and the pose "Q" that makes "b" fit "c", returns a pose that makes "a" fit "c". */ void pz_pose_make_absolute(pz_pose_vec_t *pos); /* Tries to change all relative poses in "pos" to absolute ones. More precisely, after this call, every pose "P == pos[k]" is either absolute ("P.cvx[1] == (unsigned.ne - 1)"), indeterminate ("P.cvx[1] == P.cvx[0]"), or relative to some curve for which there is no pose in "pos". Fails if "pos" contains two or more poses for the same curve, or a non-trivial loop of relative poses. */ typedef enum { pz_edge_kind_IGNORED, /* Not considered (out of range). */ pz_edge_kind_TREE, /* Edge belongs to the spanning tree. */ pz_edge_kind_OK, /* Edge is not in the spanning tree but is consistent with it. */ pz_edge_kind_BAD /* Edge is not in the spanning tree and is inconsistent with it. */ } pz_edge_kind_t; /* Classification of an edge in a frament assembly graph. */ vec_typedef(pz_edge_kind_vec_t,pz_edge_kind_vec,pz_edge_kind_t); /* A table of edge kinds. */ typedef struct pz_cluster_t { uint_vec_t ix; /* Indices of fragments in cluster. */ } /* A {pz_cluster_t} is one connected component of an assembly graph. */ vec_typedef(pz_cluster_vec_t,pz_cluster_vec,pz_cluster_t); /* An assembly graph is a list of fragment clusters. */ void pz_pose_find_clusters( pz_pose_vec_t *candPose, unsigned firstPose, unsigned lastPose, double angTol, /* Angular discrepancy tolerance, in radians. */ double linTol, /* Linear discrepancy tolerance. */ pz_cluster_vec_t *clu; /* The clusters. */ pz_edge_kind_vec_t *kind, /* Classification of each edge. */ pz_pose_vec_t *joinPose, uint_vec_t *clusterId ); /* Identifies clusters of connected fragments among a set of fragments that are connected by a given list of pairwise relative poses "candPose[firstPose..lastPose]". The procedure also computes a pose "joinPose[f]" for each fragment "f" within its cluster, that is consistent with the given relative poses. These can be seen as edges of a graph, whose vertices are the fragments. The procedure chooses arbitrarily a `root' fragment in each conected component of the forest; then, for every fragment "f" in that component, it sets "joinPose[f]" to the correct placement of fragment "f" with respect to that root. (In particular, if "f" is a root fragment, then "joinPose[f]" is an absolute pose for "f", with the identity matrix.) To compute the cluster-relative poses, the procedure computes a maximum-confidence spanning forest of the graph, assuming that the relative poses are sorted in order of decreasing confidence. Then the matrix "joinPose[f].m" is simply the product of the matrices "candPose[i].m" (or their inverses, as appropriate), along the path in this forest that connects "f" to the root node. The procedure sets "kind[i]" depending on whether "candPose[i]" was part of the spanning forest used to define the absolute poses, and, if not, on whether it is consistent with it. here consistent means that its matrix is not too different from the previously computed absolute poses --- i.e., if the product of all matrices along the cycle created by "candPose[i]" has rotation component greater tham "angTol", or linear displacement component greater than "linTol". The procedure returns a ragged two-dimensional array "cluster" of fragment indices, where each row is a connected component of the graph. I..e., "cluster[k][j]" is the "j"th fragment in the "k"th component, and (cluster[k]^.ne) is the size of that component. particular, "cluster[k][0]" is the root fragment. The rows are sorted by their root node, and within each row the fragments are in increasing order. The procedue also sets "clusterId[f] = k" if fragment "f" is part of "cluster[k]". */ r4x4_t pz_pose_place_segment ( pz_segment_t *seg, pz_r3_chain_t *chain, double tilt /* (default 0) */ r2_t shift, /* (default r2_t{0, 0}) */ bool_t flip, /* (default FALSE) */ ); /* Computes a matrix that, when applied to the given "chain", causes its segment "seg" to become tilted at angle {tilt} counterclockwise from horizontal, with midpoint at {shift}. If {flip} is TRUE, rotates by an additional 180 degrees. */ bool_vec_t *pz_pose_chains_placed(pz_pose_vec_t *pos); /* Returns a vector "used" such that "used[k]" is TRUE iff chain "k" is placed by some pose "pos[i]". */ typedef struct pz_pose_read_data_t { char *cmt; /* File comments. */ pz_pose_vec_t *pos; /* Poses for each fragment. */ } pz_pose_read_data_t; pz_pose_read_data_t pz_pose_vec_read(FILE *rd); /* Reads a vector of poses from {rd}. */ void pz_pose_vec_write(FILE *wr, pz_pose_vec_t *pos, char *cmt); /* Writes a vector of poses to {rd}, in a format that can be read back by {pz_pose_vec_read}. */ #endif