/* Indentifies clusters of fragments, and computes cluster-relative poses. */ /* Last edited on 2015-01-20 16:46:09 by stolfilocal */ #include #include #include #include #include #include #include #include TYPE Options = struct ??? { /* Input data specs: */ char *input; /* Input candidate file name */ char *chainDir; /* Directory where chains can be found. */ char *chainPrefix; /* Chain file name prefix */ unsigned band; /* Nominal band width for file names */ char *extension; /* Extension for geometric chains (".flc" usually) */ /* Parameters for pose computation: */ unsigned firstCand; /* Index of first candidate to consider. */ unsigned lastCand; /* Index of last candidate to consider. */ double angTolerance; /* Max inconsistency in angle (radians). */ double linTolerance; /* Max position inconsistency (pixels). */ /* Output specs: */ char *output; /* Output plot file (without ".ps"/".eps") */ unsigned minClusterSize; /* Minimum number of fragments in output cluster. */ } ???; int main(int argc, char **argv ) { { /* with */ ??? o = pz_get_options(int argc, char **argv); /* do */ { /* with */ ??? inpData = ReadCands(o.input); ??? cand = inpData.c^; ??? lambda = inpData.lambda; ??? chainUsed = ChainsReallyUsed(cand, o)^; chAllData = pz_r3_chain_read_all( o.chainPrefix, o.band, o.extension, sel := chainUsed; dir := o.chainDir, header_only := FALSE, recenter := pz_ctr_SMPS ); ??? chData = chAllData.chData^; ??? candPose = ComputeCandPoses(cand, o.firstCand, o.lastCand, chData)^; ??? kind = NEW(ARRAY *OF pz_pose.EdgeKind, (cand.ne))^; ??? joinPose = NEW(REF pz_pose.List, (chData.ne))^; ??? clusterNum = NEW(REF int_vec_t, (chData.ne))^; cluster = pz_pose.FindClusters( candPose, o.firstCand, o.lastCand; o.angTolerance, o.linTolerance; kind, joinPose, clusterNum )^; /* do */ for (i = 0; i < (cluster.ne ) ; i++){ { /* with */ ??? clu = cluster[i]^; /* do */ if (( (clu.ne) >= o.minClusterSize )){ WriteClusterPoses(o.output, i, joinPose, clu, "");; }; }; }; WriteGraphs(o.output, cand, kind, lambda, ""); }; }; } /* Main */ pz_candidate_read_data ReadCands( char *name ) { { /* with */ ??? fileName = txtcat(name , ".can"); /* do */ fprintf(stderr, "reading %s\n", fileName ); return pz_candidate_read(open_read(fileName, TRUE)); } } /* ReadCands */ bool_vec_t *ChainsReallyUsed( pz_candidate.List *cand, Options *o ) { { /* with */ ??? nCands = MIN(o.lastCand, (cand.ne - 1)) - o.firstCand + 1; /* do */ return pz_candidate_chains_used(SUBARRAY(cand, o.firstCand, nCands)); } } /* ChainsReallyUsed */ pz_pose.List *ComputeCandPoses( pz_candidate.List *cand, unsigned firstCand, unsigned lastCand, ARRAY *OF pz_r3_chain_read_data chData ) /* For each candidate "c == cand[i]" in the specified range, computes the 4x4 Euclidean transformation matrix "candPose[i]" that, when applied to the segment "c.seg[0]", makes it coincide (approximately) with the segment "c.seg[1]". */ VAR m: ARRAY [0..1] OF r4x4_t; /* Mapping matrices */ { { /* with */ ??? rp = NEW(REF pz_pose.List, (cand.ne)), candPose = rp^; /* do */ for ( iCand = 0 TO (cand.ne - 1) ){ { /* with */ ??? ci = cand[iCand]; ??? P = candPose[iCand]; /* do */ if (( iCand >= firstCand ) ANDAND ( iCand <= lastCand )){ for (j = 0; j <= 1 ; j++){ { /* with */ ??? s = ci.seg[j]; ??? f = s.cvx; /* do */ P.cvx[j] = f; m[j] = pz_pose.PlaceSegment( s, chain = chData[f].c^, tilt = 0.0e0, shift = LR2.T{0.0e0,0.0e0}, flip = FALSE ); }; }; P.m = LR4x4.Mul(m[0], LR4x4.Inv(m[1])) }else{ P.m = LR4x4.Identity(); }; }; }; return rp; } } /* ComputeCandPoses */ void WriteClusterPoses( char *name, unsigned clusterId, pz_pose.List *joinPose, int_vec_t *frag, char *cmt ) /* Writes out a file contaning the poses "pos[frag[j]]" for a set of fragments whose numbers are given in "frag[j]". */ { { /* with */ ??? fileName = name & "-" & FIZ(clusterId,4) & ".pos"; /* do */ fprintf(stderr, "writing %s\n", fileName ); { /* with */ ??? wr = open_write(fileName, TRUE); ??? pos = NEW(REF pz_pose.List, (frag.ne))^; /* do */ for (j = 0; j < (frag.ne ) ; j++){ pos[j] = joinPose[frag[j]] ;}; pz_pose.Write(wr, pos, cmt); fclose(wr); }; } } /* WriteClusterPoses */ void WriteGraphs( char *name, pz_candidate.List *cand, ARRAY *OF pz_pose.EdgeKind kind, double lambda, char *cmt ) { WriteSelectedCands( name & "-tree", cand, kind, pz_pose.EdgeKind.Tree, lambda, cmt & "\n\n [candidates of the spanning forest]" ); WriteSelectedCands( name & "-ok", cand, kind, pz_pose.EdgeKind.Ok, lambda, cmt & "\n\n [redundant candidates]" ); WriteSelectedCands( name & "-bad", cand, kind, pz_pose.EdgeKind.Bad, lambda, cmt & "\n\n [inconsistent edges]" ) } /* WriteGraphs */ void WriteSelectedCands( char *name, pz_candidate.List *cand, ARRAY *OF pz_pose.EdgeKind kind, pz_pose.EdgeKind which, double lambda, char *cmt ) VAR nSel: unsigned := 0; { { /* with */ ??? fileName = txtcat(name , ".can"); /* do */ fprintf(stderr, "writing %s\n", fileName ); /* Count selected cands: */ for (i = 0; i < (cand.ne ) ; i++){ if (( kind[i] == which )){ nSel++ ;}; }; { /* with */ ??? wr = open_write(fileName, TRUE); ??? selCand = NEW(REF pz_candidate.List, nSel)^; /* do */ /* Collect selected cands: */ nSel = 0; for (i = 0; i < (cand.ne ) ; i++){ if (( kind[i] == which )){ selCand[nSel] = cand[i]; nSel++ ;}; }; pz_candidate_write(wr, cmt, selCand, lambda); fclose(wr); }; } } /* WriteSelectedCands */ Options pz_get_options(int argc, char **argv ) VAR o: Options; { argparser_t *pp = argparser_new(stderr, argc, argv); argparser_set_help(pp, PROG_NAME " version " PROG_VERS ", usage:\n" PROG_HELP); argparser_set_info(pp, PROG_INFO); argparser_process_help_info_options(pp); { /* with */ /* do */ TRY argparser_get_keyword(pp, "-input"); o.input = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-chainDir") )){ o.chainDir = argparser_get_next(pp) }else{ o.chainDir = "."; }; argparser_get_keyword(pp, "-chainPrefix"); o.chainPrefix = argparser_get_next(pp); argparser_get_keyword(pp, "-band"); o.band = argparser_get_next_int(pp); if (( argparser_keyword_present(pp, "-extension") )){ o.extension= argparser_get_next(pp); }else{ o.extension = ".flc";; }; /* Pose computation options: */ if (( argparser_keyword_present(pp, "-maxCands") )){ o.firstCand = 0; o.lastCand = argparser_get_next_int(pp, 1) - 1 }else if (( argparser_keyword_present(pp, "-candsRange") )){ o.firstCand = argparser_get_next_int(pp, 0); o.lastCand = argparser_get_next_int(pp, o.firstCand) }else{ o.firstCand = 0; o.lastCand = 239; }; if (( argparser_keyword_present(pp, "-angTolerance") )){ o.angTolerance = argparser_get_next_double(pp, 0.0e0) }else{ o.angTolerance = 0.05e0; }; if (( argparser_keyword_present(pp, "-linTolerance") )){ o.linTolerance = argparser_get_next_double(pp, 0.0e0) }else{ o.linTolerance = 0.05e0; }; /* Output options: */ argparser_get_keyword(pp, "-output"); o.output = argparser_get_next(pp); if (( argparser_keyword_present(pp, "-minClusterSize") )){ o.minClusterSize = argparser_get_next_int(pp, 0) }else{ o.minClusterSize = 1; }; argparser_finish(pp); EXCEPT | ParseParams.Error ==> fprintf(stderr, "Usage: pz_find_clusters \\\n"); fprintf(stderr, " -input NAME \\\n"); fprintf(stderr, " [ -chainDir DIR ] -chainPrefix NAME \\\n"); fprintf(stderr, " -band NUMBER [ -extension EXT ] \\\n"); fprintf(stderr, " [ -maxCands NUMBER | -candsRange FIRSTNUM LASTNUM ] \\\n"); fprintf(stderr, " [ -angTolerance NUMBER ] [ -linTolerance NUMBER ] \\\n"); fprintf(stderr, " -output NAME [ -minClusterSize NUM ] \n"); Process.Exit(1);; };; }; return o } /* GetOptions */ char *FIZ( int x, unsigned width ) { return Fmt.Pad(Fmt.Int(x), width, '0') } /* FIZ */ <*UNUSED); char *FLR( double x, unsigned width, unsigned prec ) { return Fmt.Pad(Fmt.LongReal(x, Fmt.Style.Fix, prec), width) } /* FLR */ { /* Copyright © 2001 Universidade Estadual de Campinas (UNICAMP). Authors: Helena C. G. Leitão and Jorge Stolfi. This file can be freely distributed, used, and modified, provided that this copyright and authorship notice is preserved, and that any modified versions are clearly marked as such. This software has NO WARRANTY of correctness or applicability for any purpose. Neither the authors nor their employers chall be held responsible for any losses or damages that may result from its use. */