int ObservationCache::create(RunGeometry &geom, Catalog *cat, ObservationCalculator *calc) { const int blockSize = 10000; int recordCount = cat->recordCount(); cout << setprecision(6); MJD d0 = geom.tstart - 4./24.; // cout << d0 << "\n"; cout << "\n"; const int maxiter = 10; int hist[maxiter+1] = {0}; // start progress bar cout << "Progress [ "; cout.flush(); // calculate cache vector<Asteroid> obj; vector<Observation> obsv; int i = 0, prog = 0; double tref; while(i < recordCount) { int read = cat->read(obj, i, i+blockSize); // calculate positions for the time of TDI scan start (0th approximation) calc->calculateObservations(obsv, geom.tstart, obj, ObsFlags::pos | ObsFlags::vel, CalcFlags::twoBody); // start iterative approximation for TDI display for(int k = 0; k != obsv.size(); k++) { Observation &o = obsv[k]; coordinates::equgcs(geom.node, geom.inc, o.ra, o.dec, o.ra, o.dec); o.t0 = geom.tstart; int j; SkyPoint old; for(j = 0; j != maxiter; j++) { // if(i == 1023) { cout << setprecision(10) << j << " " << o.ra/ctn::d2r << " " << o.dec/ctn::d2r << " " << o.t0 << "\n"; cout.flush();} old = SkyPoint(o.ra, o.dec); // deal with compact (ra, dec) coordinate system #if 0 // this piece contained a _very_ subtle bug if the slew rate was != 1/360deg... o.t0 = geom.tstart + (o.ra - geom.muStart)/(ctn::pi2*361./360.); // o.t0 = geom.tstart + (o.ra - geom.muStart)/(ctn::pi2); #else Radians len = o.ra > geom.muStart ? o.ra - geom.muStart : o.ra + ctn::pi2 - geom.muStart; o.t0 = geom.tstart + len/(ctn::pi2*1.00273791); // o.t0 = geom.tstart + len/(ctn::pi2); #endif while(o.t0 > d0 + 1) o.t0 -= 1; while(o.t0 < d0 ) o.t0 += 1; // new approximation calc->calculateObservation(o, o.t0, obj[k], ObsFlags::pos | ObsFlags::vel, CalcFlags::twoBody); coordinates::equgcs(geom.node, geom.inc, o.ra, o.dec, o.ra, o.dec); // check convergence double dist = old.distance(SkyPoint(o.ra, o.dec)); /* if(!strcmp(o.name, "2005 SV285")) { fprintf(stderr, "t0,t1=%f,%f, iter=%d, dist=%f, t=%f, name=%s, muOld=%f, mu=%f, nu=%f]\n", geom.tstart, geom.tend, j, dist/ctn::s2r, o.t0, o.name, old.ra/ctn::d2r, o.ra/ctn::d2r, o.dec/ctn::d2r); } */ if(dist < 0.01*ctn::s2r) break; } if(j == maxiter && (fabs(o.t0 - d0) > 0.04 && fabs(o.t0 - d0) < 0.96)) { // didn't converge - sound a warning fprintf(stderr, "A TDI position calculation didn't converge [id=%d, name=%s, raOld=%f, ra=%f, dec=%f]\n", o.id, o.name, old.ra/ctn::d2r, o.ra/ctn::d2r, o.dec/ctn::d2r); fprintf(stderr, "t0,t1=%f,%f,%f iter=%d, t=%f, name=%s, muOld=%f, mu=%f, nu=%f]\n", geom.tstart, geom.tend, o.t0-d0, j, o.t0, o.name, old.ra/ctn::d2r, o.ra/ctn::d2r, o.dec/ctn::d2r); } hist[j]++; } fwrite(reinterpret_cast<void *>(&*obsv.begin()), sizeof(Observation), obsv.size(), f); i += read; // progress bar while(int(50*double(i)/double(recordCount)) > prog) { cout << "#"; cout.flush(); prog++; } } // finish progress bar cout << " ]\n"; cout.flush(); // construct and write the true header Header h; memset(&h, 0, sizeof(h)); h.geom = geom; h.len = i; strcpy(h.catalog, "NATIVE"); // cat->identify(h.catalog); setHeader(h); closeCache(); for(int i = 0; i != maxiter; i++) { cout << i+1 << ":" << hist[i] << (i+1 != maxiter ? " | " : "\n"); } return 0; }
int main(int argc, char* argv[]) { PRINT_VERSION_IF_ASKED(argc, argv); if(argc != 6) { cout << "Usage: " << argv[0] << " <output_file> <radius> <input_file> <catalog> <cache>\n"; cout << "Catalog must be in NATIVE format\n"; return -1; } out.open(argv[1]); const double matchRadius = atof(argv[2]); ifstream f(argv[3]); Catalog *cat = Catalog::open(argv[4], "NATIVE"); ObservationCache cache(argv[5], "r"); cout << "Radius : " << matchRadius << "\"\n"; cout << "Catalog : " << argv[4] << "\n"; cout << "Cache : " << argv[5] << "\n"; ObservationCalculator oc; vector<Asteroid> o; vector<Observation> obsv; int i; // unidentified observation dummy object Observation unmached; unmached.name[0] = 0; unmached.ra = unmached.dec = unmached.ddec = unmached.dra = unmached.mag = 0; Asteroid unmachedAst; // header out << "#run\tsloanId\tastorbId\ttime\tname\terrRa\terrDec\tra\tdec\tmag\tdra\tddec\ttra\ttswc\ttmag\ttdra\ttddec\tl\tb\tphi\n"; cout << setiosflags( ios::fixed ); MJD t2; SkyPoint target; double v, rowv, colw; int sloanID, run; double r_mag; int plus = 0, minus = 0; while(!f.eof()) { f >> r_mag >> run >> sloanID >> t2 >> v >> rowv >> colw >> target.ra >> target.dec; target.ra *= ctn::d2r; target.dec *= ctn::d2r; double err = 1E5; if(cache.getCandidates(obsv, t2, target, .2*ctn::d2r) > 0) { // load Asteroids for all candidates int *ids = new int[obsv.size()]; for(i = 0; i != obsv.size(); i++) ids[i] = obsv[i].id; cat->read(o, ids, obsv.size()); delete [] ids; // calculate exact position oc.calculateObservations(obsv, t2, o, ObsFlags::pos | ObsFlags::vel, CalcFlags::twoBody); // find best int bestMatch; for(i = 0; i != obsv.size(); i++) { double d = target.distance(SkyPoint(obsv[i].ra, obsv[i].dec)); if(d < err) { bestMatch = i; err = d; } } // show our best candidate err /= ctn::s2r; if(err < matchRadius) { double errRa, errDec; errRa = (obsv[bestMatch].ra - target.ra) / ctn::s2r; errDec = (obsv[bestMatch].dec - target.dec) / ctn::s2r; printMatch(t2, errRa, errDec, &o[bestMatch], obsv[bestMatch], target, run, sloanID, rowv, colw, r_mag); plus++; } } // absolutely nothing was found if(err >= matchRadius) { printMatch(t2, 0, 0, &unmachedAst, unmached, target, run, sloanID, rowv, colw, r_mag); minus++; } // progress info if((plus + minus) % 50 == 0) { cout << " [" << plus << "/" << minus << "/" << plus+minus << " : " << setprecision(1) << r_mag << "m]\n"; } cout << "#"; cout.flush(); } cout << "\nTotals (+/-/total) : " << plus << "/" << minus << "/" << plus+minus << "\n"; delete cat; return 0; }