/* # This file is part of the Astrometry.net suite. # Licensed under a 3-clause BSD style license - see LICENSE */ #include #include #include #include #include #include "os-features.h" #include "starutil.h" #include "mathutil.h" #include "bl.h" #include "matchobj.h" #include "matchfile.h" #include "solvedclient.h" #include "solvedfile.h" #include "boilerplate.h" char* OPTIONS = "hA:B:I:J:L:M:r:f:s:S:Fa"; void printHelp(char* progname) { BOILERPLATE_HELP_HEADER(stderr); fprintf(stderr, "Usage: %s [options]\n" " [-A first-field]\n" " [-B last-field]\n" " [-I first-field-filenum]\n" " [-J last-field-filenum]\n" " [-L write-leftover-matches-file]\n" " [-M write-successful-matches-file]\n" " [-r ratio-needed-to-solve]\n" " [-f minimum-field-objects-needed-to-solve] (default: no minimum)\n" " ( [-F]: write out the first sufficient match to surpass the solve threshold.\n" " or [-a]: write out all matches passing the solve threshold.\n" " (default is to write out the single best match (largest ratio))\n" " )\n" " [-S ]\n" " ...\n" "\n", progname); } static void write_field(pl* agreeing, pl* leftover, int fieldfile, int fieldnum); char* leftoverfname = NULL; matchfile* leftovermf = NULL; char* agreefname = NULL; matchfile* agreemf = NULL; il* solved; il* unsolved; char* solvedfile = NULL; double ratio_tosolve = 0.0; int ninfield_tosolve = 0; enum modes { MODE_BEST, MODE_FIRST, MODE_ALL }; int main(int argc, char *argv[]) { int argchar; char* progname = argv[0]; char** inputfiles = NULL; int ninputfiles = 0; int i; int firstfield=0, lastfield=INT_MAX-1; int firstfieldfile=1, lastfieldfile=INT_MAX-1; matchfile** mfs; MatchObj** mos; anbool* eofs; anbool* eofieldfile; int nread = 0; int f; int fieldfile; int totalsolved, totalunsolved; int mode = MODE_BEST; double logodds_tosolve = -HUGE_VAL; anbool agree = FALSE; MatchObj* bestmo; bl* keepers; bl* leftovers = NULL; while ((argchar = getopt (argc, argv, OPTIONS)) != -1) { switch (argchar) { case 'S': solvedfile = optarg; break; case 'F': mode = MODE_FIRST; break; case 'a': mode = MODE_ALL; break; case 'r': ratio_tosolve = atof(optarg); logodds_tosolve = log(ratio_tosolve); break; case 'f': ninfield_tosolve = atoi(optarg); break; case 'M': agreefname = optarg; break; case 'L': leftoverfname = optarg; break; case 'I': firstfieldfile = atoi(optarg); break; case 'J': lastfieldfile = atoi(optarg); break; case 'A': firstfield = atoi(optarg); break; case 'B': lastfield = atoi(optarg); break; case 'h': default: printHelp(progname); exit(-1); } } if (optind < argc) { ninputfiles = argc - optind; inputfiles = argv + optind; } else { printHelp(progname); exit(-1); } if (lastfield < firstfield) { fprintf(stderr, "Last field (-B) must be at least as big as first field (-A)\n"); exit(-1); } if (leftoverfname) { leftovermf = matchfile_open_for_writing(leftoverfname); if (!leftovermf) { fprintf(stderr, "Failed to open file %s to write leftover matches.\n", leftoverfname); exit(-1); } BOILERPLATE_ADD_FITS_HEADERS(leftovermf->header); qfits_header_add(leftovermf->header, "HISTORY", "This file was created by the program \"agreeable\".", NULL, NULL); if (matchfile_write_headers(leftovermf)) { fprintf(stderr, "Failed to write leftovers matchfile header.\n"); exit(-1); } leftovers = bl_new(256, sizeof(MatchObj)); } if (agreefname) { agreemf = matchfile_open_for_writing(agreefname); if (!agreemf) { fprintf(stderr, "Failed to open file %s to write agreeing matches.\n", agreefname); exit(-1); } BOILERPLATE_ADD_FITS_HEADERS(agreemf->header); qfits_header_add(agreemf->header, "HISTORY", "This file was created by the program \"agreeable\".", NULL, NULL); if (matchfile_write_headers(agreemf)) { fprintf(stderr, "Failed to write agreeing matchfile header.\n"); exit(-1); } agree = TRUE; } solved = il_new(256); unsolved = il_new(256); keepers = bl_new(256, sizeof(MatchObj)); totalsolved = totalunsolved = 0; mos = calloc(ninputfiles, sizeof(MatchObj*)); eofs = calloc(ninputfiles, sizeof(anbool)); eofieldfile = malloc(ninputfiles * sizeof(anbool)); mfs = malloc(ninputfiles * sizeof(matchfile*)); for (i=0; ifieldfile < firstfieldfile) || (mos[i]->fieldfile > lastfieldfile) || (mos[i]->fieldnum < firstfield) || (mos[i]->fieldnum > lastfield)) { mos[i] = NULL; ns++; continue; } if (mos[i]->fieldfile > fieldfile) eofieldfile[i] = TRUE; if (mos[i]->fieldfile != fieldfile) break; assert(mos[i]->fieldnum >= fieldnum); if (mos[i]->fieldnum != fieldnum) break; nread++; if (nread % 10000 == 9999) { fprintf(stderr, "."); fflush(stderr); } // if we've already found a solution, skip past the // remaining matches in this file... if (solved_it && (mode == MODE_FIRST)) { ns++; mos[i] = NULL; continue; } nr++; if ((mos[i]->logodds >= logodds_tosolve) && (mos[i]->nindex >= ninfield_tosolve)) { solved_it = TRUE; // (note, we get a pointer to its position in the list) mos[i] = bl_append(keepers, mos[i]); if (!bestmo || mos[i]->logodds > bestmo->logodds) bestmo = mos[i]; } else if (leftovers) { bl_append(leftovers, mos[i]); } mos[i] = NULL; } if (nr || ns) fprintf(stderr, "File %s: read %i matches, skipped %i matches.\n", inputfiles[i], nr, ns); } // which matches do we want to write out? if (agree) { writematches = bl_new(256, sizeof(MatchObj)); switch (mode) { case MODE_BEST: case MODE_FIRST: if (bestmo) bl_append(writematches, bestmo); break; case MODE_ALL: bl_append_list(writematches, keepers); break; } } write_field(writematches, leftovers, fieldfile, fieldnum); if (agree) bl_free(writematches); if (leftovers) bl_remove_all(leftovers); if (keepers) bl_remove_all(keepers); fprintf(stderr, "This file: %i fields solved, %i unsolved.\n", il_size(solved), il_size(unsolved)); fprintf(stderr, "Grand total: %i solved, %i unsolved.\n", totalsolved + il_size(solved), totalunsolved + il_size(unsolved)); } totalsolved += il_size(solved); totalunsolved += il_size(unsolved); il_remove_all(solved); il_remove_all(unsolved); if (alldone) break; } for (i=0; ilogodds, exp(mo->logodds)); } if (leftover && bl_size(leftover)) { fprintf(stderr, "Field %i: writing %i leftovers...\n", fieldnum, bl_size(leftover)); for (i=0; i