void startree_search_for(const startree_t* s, const double* xyzcenter, double radius2, double** xyzresults, double** radecresults, int** starinds, int* nresults) { kdtree_qres_t* res = NULL; int opts; double* xyz; int i, N; opts = KD_OPTIONS_SMALL_RADIUS; if (xyzresults || radecresults) opts |= KD_OPTIONS_RETURN_POINTS; res = kdtree_rangesearch_options(s->tree, xyzcenter, radius2, opts); if (!res || !res->nres) { if (xyzresults) *xyzresults = NULL; if (radecresults) *radecresults = NULL; if (starinds) *starinds = NULL; *nresults = 0; if (res) kdtree_free_query(res); return; } xyz = res->results.d; N = res->nres; *nresults = N; if (radecresults) { *radecresults = malloc(N * 2 * sizeof(double)); for (i=0; i<N; i++) xyzarr2radecdegarr(xyz + i*3, (*radecresults) + i*2); } if (xyzresults) { // Steal the results array. *xyzresults = xyz; res->results.d = NULL; } if (starinds) { *starinds = malloc(res->nres * sizeof(int)); for (i=0; i<N; i++) (*starinds)[i] = res->inds[i]; } kdtree_free_query(res); }
bl* henry_draper_get(hd_catalog_t* hdcat, double racenter, double deccenter, double r_arcsec) { double r2; double xyz[3]; kdtree_qres_t* q; bl* res; int i; hd_entry_t hd; radecdeg2xyzarr(racenter, deccenter, xyz); r2 = arcsec2distsq(r_arcsec); q = kdtree_rangesearch(hdcat->kd, xyz, r2); if (!q) { return NULL; } res = bl_new(256, sizeof(hd_entry_t)); for (i=0; i<q->nres; i++) { double* pt = q->results.d + i*3; xyzarr2radecdeg(pt, &(hd.ra), &(hd.dec)); hd.hd = q->inds[i] + 1; bl_append(res, &hd); } kdtree_free_query(q); return res; }
int hpquads(startree_t* starkd, codefile_t* codes, quadfile_t* quads, int Nside, double scale_min_arcmin, double scale_max_arcmin, int dimquads, int passes, int Nreuses, int Nloosen, int id, anbool scanoccupied, void* sort_data, int (*sort_func)(const void*, const void*), int sort_size, char** args, int argc) { hpquads_t myhpquads; hpquads_t* me = &myhpquads; int i; int pass; anbool circle = TRUE; double radius2; il* hptotry; int Nhptotry = 0; int nquads; double hprad; double quadscale; int skhp, sknside; qfits_header* qhdr; qfits_header* chdr; int N; int dimcodes; int quadsize; int NHP; memset(me, 0, sizeof(hpquads_t)); if (Nside > HP_MAX_INT_NSIDE) { ERROR("Error: maximum healpix Nside = %i", HP_MAX_INT_NSIDE); return -1; } if (Nreuses > 255) { ERROR("Error, reuse (-r) must be less than 256"); return -1; } me->Nside = Nside; me->dimquads = dimquads; NHP = 12 * Nside * Nside; dimcodes = dimquad2dimcode(dimquads); quadsize = sizeof(unsigned int) * dimquads; logmsg("Nside=%i. Nside^2=%i. Number of healpixes=%i. Healpix side length ~ %g arcmin.\n", me->Nside, me->Nside*me->Nside, NHP, healpix_side_length_arcmin(me->Nside)); me->sort_data = sort_data; me->sort_func = sort_func; me->sort_size = sort_size; tic(); me->starkd = starkd; N = startree_N(me->starkd); logmsg("Star tree contains %i objects.\n", N); // get the "HEALPIX" header from the skdt... skhp = qfits_header_getint(startree_header(me->starkd), "HEALPIX", -1); if (skhp == -1) { if (!qfits_header_getboolean(startree_header(me->starkd), "ALLSKY", FALSE)) { logmsg("Warning: skdt does not contain \"HEALPIX\" header. Code and quad files will not contain this header either.\n"); } } // likewise "HPNSIDE" sknside = qfits_header_getint(startree_header(me->starkd), "HPNSIDE", 1); if (sknside && Nside % sknside) { logerr("Error: Nside (-n) must be a multiple of the star kdtree healpixelisation: %i\n", sknside); return -1; } if (!scanoccupied && (N*(skhp == -1 ? 1 : sknside*sknside*12) < NHP)) { logmsg("\n\n"); logmsg("NOTE, your star kdtree is sparse (has only a fraction of the stars expected)\n"); logmsg(" so you probably will get much faster results by setting the \"-E\" command-line\n"); logmsg(" flag.\n"); logmsg("\n\n"); } quads->dimquads = me->dimquads; codes->dimcodes = dimcodes; quads->healpix = skhp; codes->healpix = skhp; quads->hpnside = sknside; codes->hpnside = sknside; if (id) { quads->indexid = id; codes->indexid = id; } qhdr = quadfile_get_header(quads); chdr = codefile_get_header(codes); add_headers(qhdr, args, argc, startree_header(me->starkd), circle, passes); add_headers(chdr, args, argc, startree_header(me->starkd), circle, passes); if (quadfile_write_header(quads)) { ERROR("Couldn't write headers to quad file"); return -1; } if (codefile_write_header(codes)) { ERROR("Couldn't write headers to code file"); return -1; } quads->numstars = codes->numstars = N; me->quad_dist2_upper = arcmin2distsq(scale_max_arcmin); me->quad_dist2_lower = arcmin2distsq(scale_min_arcmin); codes->index_scale_upper = quads->index_scale_upper = distsq2rad(me->quad_dist2_upper); codes->index_scale_lower = quads->index_scale_lower = distsq2rad(me->quad_dist2_lower); me->nuses = calloc(N, sizeof(unsigned char)); // hprad = sqrt(2) * (healpix side length / 2.) hprad = arcmin2dist(healpix_side_length_arcmin(Nside)) * M_SQRT1_2; quadscale = 0.5 * sqrt(me->quad_dist2_upper); // 1.01 for a bit of safety. we'll look at a few extra stars. radius2 = square(1.01 * (hprad + quadscale)); me->radius2 = radius2; logmsg("Healpix radius %g arcsec, quad scale %g arcsec, total %g arcsec\n", distsq2arcsec(hprad*hprad), distsq2arcsec(quadscale*quadscale), distsq2arcsec(radius2)); hptotry = il_new(1024); if (scanoccupied) { logmsg("Scanning %i input stars...\n", N); for (i=0; i<N; i++) { double xyz[3]; int j; if (startree_get(me->starkd, i, xyz)) { ERROR("Failed to get star %i", i); return -1; } j = xyzarrtohealpix(xyz, Nside); il_insert_unique_ascending(hptotry, j); if (log_get_level() > LOG_VERB) { double ra,dec; if (startree_get_radec(me->starkd, i, &ra, &dec)) { ERROR("Failed to get RA,Dec for star %i\n", i); return -1; } logdebug("star %i: RA,Dec %g,%g; xyz %g,%g,%g; hp %i\n", i, ra, dec, xyz[0], xyz[1], xyz[2], j); } } logmsg("Will check %zu healpixes.\n", il_size(hptotry)); if (log_get_level() > LOG_VERB) { logdebug("Checking healpixes: [ "); for (i=0; i<il_size(hptotry); i++) logdebug("%i ", il_get(hptotry, i)); logdebug("]\n"); } } else { if (skhp == -1) { // Try all healpixes. il_free(hptotry); hptotry = NULL; Nhptotry = NHP; } else { // The star kdtree may itself be healpixed int starhp, starx, stary; // In that case, the healpixes we are interested in form a rectangle // within a big healpix. These are the coords (in [0, Nside)) of // that rectangle. int x0, x1, y0, y1; int x, y; healpix_decompose_xy(skhp, &starhp, &starx, &stary, sknside); x0 = starx * (Nside / sknside); x1 = (starx+1) * (Nside / sknside); y0 = stary * (Nside / sknside); y1 = (stary+1) * (Nside / sknside); for (y=y0; y<y1; y++) { for (x=x0; x<x1; x++) { int j = healpix_compose_xy(starhp, x, y, Nside); il_append(hptotry, j); } } assert(il_size(hptotry) == (Nside/sknside) * (Nside/sknside)); } } if (hptotry) Nhptotry = il_size(hptotry); me->quadlist = bl_new(65536, quadsize); if (Nloosen) me->retryhps = il_new(1024); for (pass=0; pass<passes; pass++) { char key[64]; int nthispass; logmsg("Pass %i of %i.\n", pass+1, passes); logmsg("Trying %i healpixes.\n", Nhptotry); nthispass = build_quads(me, Nhptotry, hptotry, Nreuses); logmsg("Made %i quads (out of %i healpixes) this pass.\n", nthispass, Nhptotry); logmsg("Made %i quads so far.\n", (me->bigquadlist ? bt_size(me->bigquadlist) : 0) + (int)bl_size(me->quadlist)); sprintf(key, "PASS%i", pass+1); fits_header_mod_int(chdr, key, nthispass, "quads created in this pass"); fits_header_mod_int(qhdr, key, nthispass, "quads created in this pass"); logmsg("Merging quads...\n"); if (!me->bigquadlist) me->bigquadlist = bt_new(quadsize, 256); for (i=0; i<bl_size(me->quadlist); i++) { void* q = bl_access(me->quadlist, i); bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads); } bl_remove_all(me->quadlist); } il_free(hptotry); hptotry = NULL; if (Nloosen) { int R; for (R=Nreuses+1; R<=Nloosen; R++) { il* trylist; int nthispass; logmsg("Loosening reuse maximum to %i...\n", R); logmsg("Trying %zu healpixes.\n", il_size(me->retryhps)); if (!il_size(me->retryhps)) break; trylist = me->retryhps; me->retryhps = il_new(1024); nthispass = build_quads(me, il_size(trylist), trylist, R); logmsg("Made %i quads (out of %zu healpixes) this pass.\n", nthispass, il_size(trylist)); il_free(trylist); for (i=0; i<bl_size(me->quadlist); i++) { void* q = bl_access(me->quadlist, i); bt_insert2(me->bigquadlist, q, FALSE, compare_quads, &me->dimquads); } bl_remove_all(me->quadlist); } } if (me->retryhps) il_free(me->retryhps); kdtree_free_query(me->res); me->res = NULL; me->inds = NULL; me->stars = NULL; free(me->nuses); me->nuses = NULL; logmsg("Writing quads...\n"); // add the quads from the big-quadlist nquads = bt_size(me->bigquadlist); for (i=0; i<nquads; i++) { unsigned int* q = bt_access(me->bigquadlist, i); quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes); } // add the quads that were made during the final round. for (i=0; i<bl_size(me->quadlist); i++) { unsigned int* q = bl_access(me->quadlist, i); quad_write(codes, quads, q, me->starkd, me->dimquads, dimcodes); } // fix output file headers. if (quadfile_fix_header(quads)) { ERROR("Failed to fix quadfile headers"); return -1; } if (codefile_fix_header(codes)) { ERROR("Failed to fix codefile headers"); return -1; } bl_free(me->quadlist); bt_free(me->bigquadlist); toc(); logmsg("Done.\n"); return 0; }
void verify_get_all_matches(const double* refxys, int NR, const double* testxys, const double* testsigma2s, int NT, double effective_area, double distractors, double nsigma, double limit, il*** p_reflist, dl*** p_problist) { double* refcopy; kdtree_t* rtree; int Nleaf = 10; int i,j; double logd; double logbg; double loglimit; il** reflist; dl** problist; reflist = calloc(NT, sizeof(il*)); problist = calloc(NT, sizeof(dl*)); // Build a tree out of the index stars in pixel space... // kdtree scrambles the data array so make a copy first. refcopy = malloc(2 * NR * sizeof(double)); memcpy(refcopy, refxys, 2 * NR * sizeof(double)); rtree = kdtree_build(NULL, refcopy, NR, 2, Nleaf, KDTT_DOUBLE, KD_BUILD_SPLIT); logbg = log(1.0 / effective_area); logd = log(distractors / effective_area); loglimit = log(distractors / effective_area * limit); for (i=0; i<NT; i++) { const double* testxy; double sig2; kdtree_qres_t* res; testxy = testxys + 2*i; sig2 = testsigma2s[i]; logverb("\n"); logverb("test star %i: (%.1f,%.1f), sigma: %.1f\n", i, testxy[0], testxy[1], sqrt(sig2)); // find all ref stars within nsigma. res = kdtree_rangesearch_options(rtree, testxy, sig2*nsigma*nsigma, KD_OPTIONS_SORT_DISTS | KD_OPTIONS_SMALL_RADIUS); if (res->nres == 0) { kdtree_free_query(res); continue; } reflist[i] = il_new(4); problist[i] = dl_new(4); for (j=0; j<res->nres; j++) { double d2; int refi; double loggmax, logfg; d2 = res->sdists[j]; refi = res->inds[j]; // peak value of the Gaussian loggmax = log((1.0 - distractors) / (2.0 * M_PI * sig2 * NR)); // value of the Gaussian logfg = loggmax - d2 / (2.0 * sig2); if (logfg < loglimit) continue; logverb(" ref star %i, dist %.2f, sigmas: %.3f, logfg: %.1f (%.1f above distractor, %.1f above bg, %.1f above keep-limit)\n", refi, sqrt(d2), sqrt(d2 / sig2), logfg, logfg - logd, logfg - logbg, logfg - loglimit); il_append(reflist[i], refi); dl_append(problist[i], logfg); } kdtree_free_query(res); } kdtree_free(rtree); free(refcopy); *p_reflist = reflist; *p_problist = problist; }
static PyObject* spherematch_kdtree_rangesearch(PyObject* self, PyObject* args) { double* X; PyObject* rtn; npy_intp dims[1]; long i; kdtree_t* kd; int D, N; PyObject* pyO; PyObject* pyI; PyObject* pyInds; PyObject* pyDists = NULL; PyArray_Descr* dtype = PyArray_DescrFromType(NPY_DOUBLE); int req = NPY_C_CONTIGUOUS | NPY_ALIGNED | NPY_NOTSWAPPED | NPY_ELEMENTSTRIDES; double radius; kdtree_qres_t* res; int getdists, sortdists; int opts; if (!PyArg_ParseTuple(args, "lOdii", &i, &pyO, &radius, &getdists, &sortdists)) { PyErr_SetString(PyExc_ValueError, "need five args: kdtree identifier (int), query point (numpy array of floats), radius (double), get distances (int 0/1), sort distances (int 0/1)"); return NULL; } // Nasty! kd = (kdtree_t*)i; D = kd->ndim; if (sortdists) { getdists = 1; } Py_INCREF(dtype); pyI = PyArray_FromAny(pyO, dtype, 1, 1, req, NULL); if (!pyI) { PyErr_SetString(PyExc_ValueError, "Failed to convert query point array to np array of float"); Py_XDECREF(dtype); return NULL; } N = (int)PyArray_DIM(pyI, 0); if (N != D) { PyErr_SetString(PyExc_ValueError, "Query point must have size == dimension of tree"); Py_DECREF(pyI); Py_DECREF(dtype); return NULL; } X = PyArray_DATA(pyI); opts = 0; if (getdists) { opts |= KD_OPTIONS_COMPUTE_DISTS; } if (sortdists) { opts |= KD_OPTIONS_SORT_DISTS; } res = kdtree_rangesearch_options(kd, X, radius*radius, opts); N = res->nres; dims[0] = N; res->inds = realloc(res->inds, N * sizeof(uint32_t)); pyInds = PyArray_SimpleNewFromData(1, dims, NPY_UINT32, res->inds); res->inds = NULL; if (getdists) { res->sdists = realloc(res->sdists, N * sizeof(double)); pyDists = PyArray_SimpleNewFromData(1, dims, NPY_DOUBLE, res->sdists); res->sdists = NULL; } kdtree_free_query(res); Py_DECREF(pyI); Py_DECREF(dtype); if (getdists) { rtn = Py_BuildValue("(OO)", pyInds, pyDists); Py_DECREF(pyDists); } else { rtn = Py_BuildValue("O", pyInds); } Py_DECREF(pyInds); return rtn; }