From 4e900fda39adfc718882788fdecd7b25ca3b40b2 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 10:54:07 -0400 Subject: [PATCH 1/7] copy the readme (fix #37) --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 11b3ab2..7d200d7 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ EXTVERSION := $(shell grep default_version $(EXTENSION).control | \ sed -e "s/default_version[[:space:]]*=[[:space:]]*'\([^']*\)'/\1/") -DOCS = README.md +DOCS = q3c.md OBJS = dump.o q3c.o q3c_poly.o q3cube.o MODULE_big = q3c DATA = $(wildcard scripts/*sql) @@ -42,6 +42,9 @@ else MYBINLIBS := $(PG_LIBS) -lm endif +readme: + cp README.md q3c.md + dump.c: prepare ./prepare From 1002b72a12444236ae0a9cfca6638111eb9cc834 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 11:05:35 -0400 Subject: [PATCH 2/7] add readme to prepare target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 7d200d7..4d8893d 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,7 @@ readme: dump.c: prepare ./prepare -prepare: prepare.o q3cube.o q3c_poly.o +prepare: prepare.o q3cube.o q3c_poly.o readme $(CC) $? $(CFLAGS) $(PG_LIBS) $(PG_LDFLAGS) $(LDFLAGS) $(MYBINLIBS) -o $@ gen_data: gen_data.c From b6484ef67b3b6bff878c06ce6ea57e209c33a263 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 11:08:17 -0400 Subject: [PATCH 3/7] tinker with makefiel --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 4d8893d..2bd72aa 100644 --- a/Makefile +++ b/Makefile @@ -45,10 +45,10 @@ endif readme: cp README.md q3c.md -dump.c: prepare +dump.c: prepare readme ./prepare -prepare: prepare.o q3cube.o q3c_poly.o readme +prepare: prepare.o q3cube.o q3c_poly.o $(CC) $? $(CFLAGS) $(PG_LIBS) $(PG_LDFLAGS) $(LDFLAGS) $(MYBINLIBS) -o $@ gen_data: gen_data.c From 5a6c047f11c3e7162c2834001ecf3e816ac65d12 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 11:22:27 -0400 Subject: [PATCH 4/7] test more pg versions silence github warning update copyright --- .github/workflows/test.yml | 4 ++-- README.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 22c2319..57dc638 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -17,7 +17,7 @@ jobs: matrix: container: ['ubuntu:22.04'] compiler: [gcc] - PGVERSION: [12, 13, 14, 15] + PGVERSION: [12, 13, 14, 15, 16, 17] COVERAGE: ['0'] APT: ['1'] include: @@ -29,7 +29,7 @@ jobs: compiler: 'clang' steps: - name: Checkout - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: PG cleanup run: | sudo apt-get -y --purge remove postgresql libpq-dev libpq5 postgresql-client-common postgresql-common diff --git a/README.md b/README.md index 30fa956..96e9aaa 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Author: Sergey Koposov, University of Edinburgh -Copyright (c) 2004-2023 Sergey Koposov +Copyright (c) 2004-2024 Sergey Koposov Email: skoposov AT ed DOT ac DOT uk From 47911f261c0ca7bbe435a494aa384d324970c6ea Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 11:46:44 -0400 Subject: [PATCH 5/7] add comment --- Makefile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Makefile b/Makefile index 2bd72aa..a0418b8 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,12 @@ EXTVERSION := $(shell grep default_version $(EXTENSION).control | \ sed -e "s/default_version[[:space:]]*=[[:space:]]*'\([^']*\)'/\1/") +# Note the filename is different from README.md +# because of the requirement to have unique filenames +# we create q3c.md out of README.md when compiling +# the extension DOCS = q3c.md + OBJS = dump.o q3c.o q3c_poly.o q3cube.o MODULE_big = q3c DATA = $(wildcard scripts/*sql) From 7a7037e3231f5e23a9ed1174535d330c2d93d499 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 11:57:41 -0400 Subject: [PATCH 6/7] add constants to the q3c_prm structure --- common.h | 18 +++++++++++++----- prepare.c | 6 +++--- q3cube.c | 49 ++++++++++++++++++++++++++++--------------------- 3 files changed, 44 insertions(+), 29 deletions(-) diff --git a/common.h b/common.h index 7aa518f..fc367d0 100644 --- a/common.h +++ b/common.h @@ -205,6 +205,14 @@ typedef long double q3c_coord_t; #endif struct q3c_prm +{ + const q3c_ipix_t nside; + const q3c_ipix_t *xbits; + const q3c_ipix_t *ybits; + const q3c_ipix_t *xbits1; + const q3c_ipix_t *ybits1; +}; +struct q3c_prm_write { q3c_ipix_t nside; q3c_ipix_t *xbits; @@ -257,11 +265,11 @@ typedef struct typedef enum {Q3C_CIRCLE, Q3C_POLYGON, Q3C_ELLIPSE} q3c_region; -void init_q3c(struct q3c_prm *, q3c_ipix_t); +void init_q3c(struct q3c_prm_write *, q3c_ipix_t); -void init_q3c1(struct q3c_prm *, q3c_ipix_t); +void init_q3c1(struct q3c_prm_write *, q3c_ipix_t); -void q3c_dump_prm(struct q3c_prm *,char *); +void q3c_dump_prm(struct q3c_prm_write *,char *); void q3c_ang2ipix(struct q3c_prm *, q3c_coord_t, q3c_coord_t, q3c_ipix_t *); @@ -341,8 +349,8 @@ int q3c_check_sphere_point_in_poly(struct q3c_prm *hprm, int n, char q3c_get_region_facenum(q3c_region region, void *data); -q3c_ipix_t q3c_xiyi2ipix(q3c_ipix_t nside, q3c_ipix_t *xbits, - q3c_ipix_t *ybits, char face_num, +q3c_ipix_t q3c_xiyi2ipix(const q3c_ipix_t nside, const q3c_ipix_t *xbits, + const q3c_ipix_t *ybits, char face_num, q3c_ipix_t xi, q3c_ipix_t yi); void q3c_multi_face_check(q3c_coord_t *xmin0, q3c_coord_t *ymin0, diff --git a/prepare.c b/prepare.c index 2644474..45cb13a 100644 --- a/prepare.c +++ b/prepare.c @@ -25,11 +25,11 @@ #include "common.h" int main() { - struct q3c_prm hprm1; + struct q3c_prm_write hprm1; - init_q3c1(&hprm1,1073741824); + init_q3c1(&hprm1, 1073741824); - q3c_dump_prm(&hprm1,"dump.c"); + q3c_dump_prm(&hprm1, "dump.c"); return 0; diff --git a/q3cube.c b/q3cube.c index b694825..1e0ddad 100644 --- a/q3cube.c +++ b/q3cube.c @@ -180,8 +180,9 @@ void q3c_ang2ipix_xy (struct q3c_prm *hprm, q3c_coord_t ra0, q3c_coord_t dec0, { q3c_coord_t x0 = 0, y0 = 0, ra1, dec1, tmp0, td1; q3c_coord_t ra,dec; - q3c_ipix_t nside = hprm->nside, *xbits = hprm->xbits, - *ybits = hprm->ybits, xi, yi; + const q3c_ipix_t nside = hprm->nside, *xbits = hprm->xbits, + *ybits = hprm->ybits; + q3c_ipix_t xi, yi; char face_num; /* We check against crazy right ascensions */ @@ -561,8 +562,9 @@ void q3c_get_nearby(struct q3c_prm *hprm, q3c_region region, void *region_data, q3c_ipix_t *ipix) { q3c_coord_t xmin, xmax, ymin, ymax, xesize, yesize, points[4]; - q3c_ipix_t nside = hprm->nside, *xbits = hprm->xbits, *ybits = hprm->ybits, - *ipix_cur = ipix, ipix0, xi, yi, n0, n1, ixmin, + const q3c_ipix_t nside = hprm->nside, *xbits = hprm->xbits, *ybits = hprm->ybits; + + q3c_ipix_t *ipix_cur = ipix, ipix0, xi, yi, n0, n1, ixmin, ixmax, iymin, iymax, xistack[4], yistack[4], facestack[4], nstack[4]; char face_num, face_num0, multi_flag; @@ -963,8 +965,8 @@ void q3c_get_nearby(struct q3c_prm *hprm, q3c_region region, void *region_data, /* Converts integer coordinates on cube face to * ipix number by performing bit interleaving */ -q3c_ipix_t q3c_xiyi2ipix(q3c_ipix_t nside, q3c_ipix_t *xbits, - q3c_ipix_t *ybits, char face_num, +q3c_ipix_t q3c_xiyi2ipix(const q3c_ipix_t nside, const q3c_ipix_t *xbits, + const q3c_ipix_t *ybits, char face_num, q3c_ipix_t xi, q3c_ipix_t yi) { @@ -980,8 +982,9 @@ q3c_ipix_t q3c_xiyi2ipix(q3c_ipix_t nside, q3c_ipix_t *xbits, void q3c_ipix2ang(struct q3c_prm *hprm, q3c_ipix_t ipix, q3c_coord_t *ra, q3c_coord_t *dec) { - q3c_ipix_t nside = hprm->nside, ipix1, *xbits1 = hprm->xbits1, - *ybits1 = hprm->ybits1, i2, i3, x0, y0; + const q3c_ipix_t nside = hprm->nside, *xbits1 = hprm->xbits1, + *ybits1 = hprm->ybits1; + q3c_ipix_t ipix1, i2, i3, x0, y0; q3c_coord_t x, y, ra0; char face_num = ipix / (nside * nside); @@ -1058,8 +1061,9 @@ q3c_coord_t q3c_pixarea(struct q3c_prm *hprm, q3c_ipix_t ipix, int depth) * In the future I should split the ipix2xy and xy2ang codepaths * and put them in the separate functions */ - q3c_ipix_t nside = hprm->nside, ipix1, *xbits1 = hprm->xbits1, - *ybits1 = hprm->ybits1, i2, i3, x0, y0, idx, + const q3c_ipix_t nside = hprm->nside, *xbits1 = hprm->xbits1, + *ybits1 = hprm->ybits1; + q3c_ipix_t ipix1, i2, i3, x0, y0, idx, ix1, iy1, ix2, iy2; q3c_coord_t x1, y1, x2, y2, result; /* char face_num = ipix / (nside * nside);*/ @@ -1176,7 +1180,7 @@ char q3c_xy2facenum(q3c_coord_t x, q3c_coord_t y, char face_num0) * hprm -- Pointer to main Q3C structure * nside -- Nside parameter (number of quadtree subdivisions) */ -void init_q3c1(struct q3c_prm *hprm, q3c_ipix_t nside) +void init_q3c1(struct q3c_prm_write *hprm, q3c_ipix_t nside) { int i, k, m, l; const q3c_ipix_t nbits = Q3C_INTERLEAVED_NBITS; @@ -1290,7 +1294,7 @@ void init_q3c1(struct q3c_prm *hprm, q3c_ipix_t nside) /* Dump the definitions of main Q3C arrays into a .c file */ -void q3c_dump_prm(struct q3c_prm *hprm,char *filename) +void q3c_dump_prm(struct q3c_prm_write *hprm,char *filename) { FILE *fp = fopen(filename, "w"); int i, x = 1 << Q3C_INTERLEAVED_NBITS; @@ -1298,7 +1302,7 @@ void q3c_dump_prm(struct q3c_prm *hprm,char *filename) *xbits1 = hprm->xbits1, *ybits1 = hprm->ybits1; fprintf(fp, "#include \"common.h\"\n"); - fprintf(fp, "\nq3c_ipix_t ____xbits[%d]={", x); + fprintf(fp, "\nconst q3c_ipix_t ____xbits[%d]={", x); fprintf(fp, " "); for(i = 0; i < x; i++) @@ -1311,7 +1315,7 @@ void q3c_dump_prm(struct q3c_prm *hprm,char *filename) } fprintf(fp, "};"); - fprintf(fp, "\nq3c_ipix_t ____ybits[%d]={",x); + fprintf(fp, "\nconst q3c_ipix_t ____ybits[%d]={",x); fprintf(fp, " "); for(i = 0; i < x; i++) @@ -1324,7 +1328,7 @@ void q3c_dump_prm(struct q3c_prm *hprm,char *filename) } fprintf(fp, "};"); - fprintf(fp, "\nq3c_ipix_t ____xbits1[%d]={", x); + fprintf(fp, "\nconst q3c_ipix_t ____xbits1[%d]={", x); fprintf(fp, " "); for(i = 0; i < x; i++) @@ -1337,7 +1341,7 @@ void q3c_dump_prm(struct q3c_prm *hprm,char *filename) } fprintf(fp, "};"); - fprintf(fp, "\nq3c_ipix_t ____ybits1[%d]={",x); + fprintf(fp, "\nconst q3c_ipix_t ____ybits1[%d]={",x); fprintf(fp, " "); for(i = 0; i < x; i++) @@ -1350,7 +1354,7 @@ void q3c_dump_prm(struct q3c_prm *hprm,char *filename) } fprintf(fp, "};\n"); - fprintf(fp, "struct q3c_prm hprm={" + fprintf(fp, "const struct q3c_prm hprm={" Q3C_IPIX_FMT ",____xbits,____ybits,____xbits1,____ybits1};\n", hprm->nside); fclose(fp); } @@ -2362,7 +2366,7 @@ void q3c_output_stack( struct q3c_prm *hprm, { int i, j; q3c_ipix_t xi, yi, ipix_tmp1, ipix_tmp2, ntmp1; - q3c_ipix_t *xbits = hprm->xbits, *ybits = hprm->ybits; + const q3c_ipix_t *xbits = hprm->xbits, *ybits = hprm->ybits; struct q3c_square *cur_square; /* Run through fully covered squares (we take them from out_stack) */ @@ -2461,7 +2465,8 @@ void q3c_radial_query(struct q3c_prm *hprm, q3c_coord_t ra0, xc_cur = 0, yc_cur = 0, cur_size, xesize, yesize, points[4]; - q3c_ipix_t n0, nside = hprm->nside; + q3c_ipix_t n0; + const q3c_ipix_t nside = hprm->nside; char face_num, multi_flag = 0, face_count, face_num0, full_flags[3] = {0,0,0}; int out_ipix_arr_fulls_pos = 0; @@ -2673,7 +2678,8 @@ void q3c_poly_query(struct q3c_prm *hprm, q3c_poly *qp, xc_cur = 0, yc_cur = 0, cur_size, xesize, yesize, points[4]; - q3c_ipix_t n0, nside = hprm->nside; + q3c_ipix_t n0; + const q3c_ipix_t nside = hprm->nside; char face_num, multi_flag = 0, face_count, face_num0, large_flag = 0; int out_ipix_arr_fulls_pos = 0; @@ -2854,7 +2860,8 @@ void q3c_ellipse_query(struct q3c_prm *hprm, q3c_coord_t ra0, yc_cur = 0, cur_size, xesize, yesize, points[4], axx, ayy, axy, ax, ay, a; - q3c_ipix_t n0, nside = hprm->nside; + q3c_ipix_t n0; + const q3c_ipix_t nside = hprm->nside; char face_num, multi_flag = 0, face_count, face_num0; int out_ipix_arr_fulls_pos = 0; From e4cbfef2e9d80cb9d1c7ee159650d60355332466 Mon Sep 17 00:00:00 2001 From: "Sergey E. Koposov" Date: Tue, 2 Jul 2024 13:44:37 -0400 Subject: [PATCH 7/7] edit readme --- README.md | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 96e9aaa..fc82f55 100644 --- a/README.md +++ b/README.md @@ -63,7 +63,7 @@ The next procedure is optional but strongly recommended: cluster the table using Alternatively, instead of CLUSTER, you can also just reorder your table yourself before indexing (can be faster) `my_db# create table mytable1 as select * from mytable order by q3c_ang2ipix(ra,dec);` -The last step is analyzing your table: +The last step after creating the index is analyzing your table: `my_db# ANALYZE mytable;` @@ -73,17 +73,19 @@ Now you should be able to use q3c queries. *IMPORTANT* Throughout q3c it is assumed that all the angles (ra, dec and distances) are in units of angular degrees, the proper motions are in mas/year, and that the units for the epochs are years, i.e. 2000.5, 2010.5. +Throughout the rest of the text I will use ipix as reference to the 64 bit integer identifier of the pixel on the sphere in Q3C. + The functions installed by Q3C are: -- q3c_ang2ipix(ra, dec) -- returns the ipix value at ra and dec +- q3c_ang2ipix(ra, dec) -- returns the ipix value for given ra and dec -- q3c_dist(ra1, dec1, ra2, dec2) -- returns the distance in degrees between two points (ra1,dec1) and (ra2,dec2) +- q3c_dist(ra1, dec1, ra2, dec2) -- returns the distance in degrees between two points (ra1,dec1) and (ra2,dec2) - q3c_dist_pm(ra1, dec1, pmra1, pmdec1, cosdec_flag, epoch1, ra2, dec2, epoch2) -- returns the distance in degrees between two points (ra1,dec1) and (ra2,dec2) at the epoch epoch2 while taking the proper motion into account. *IMPORTANT* The cosdec flag (0 or 1) indicates whether the provided proper motion - includes the cos(dec) term (1) or not (0) . The previous versions + includes the cos(dec) term (1) or not (0) . The previous version of q3c (q3c 1.8) did not have that parameter and assumed pmra without cos(dec)) - q3c_join(ra1, dec1, ra2, dec2, radius) -- returns true if (ra1, dec1) @@ -119,7 +121,7 @@ The functions installed by Q3C are: axis_ratio, PA ) -- returns true if ra, dec is within the ellipse from center_ra, center_dec. The ellipse is specified by semi-major axis, axis ratio and positional angle. - This function should be used if when the index on q3c_ang2ipix(ra,dec) is created. + This function should be used when the index on q3c_ang2ipix(ra,dec) is created. - q3c_poly_query(ra, dec, poly) -- returns true if ra, dec is within the spherical polygon specified as an array of right ascensions and declinations @@ -129,27 +131,29 @@ The functions installed by Q3C are: - q3c_ipix2ang(ipix) -- returns a two-element array of (ra,dec) corresponding to a given ipix. -- q3c_pixarea(ipix, bits) -- returns the area corresponding to a given ipix at the pixelisation level given by - bits (1 is smallest, 30 is the cube face) in steradians. +- q3c_pixarea(ipix, bits) -- returns the spherical area corresponding to a given ipix at the pixelisation level given by + bits (1 is smallest, 30 is the cube face). - q3c_ipixcenter(ra, dec, bits) -- returns the ipix value of the pixel center at certain pixel depth covering the specified (ra,dec) - q3c_in_poly(ra, dec, poly) -- returns true/false if point is inside a - polygon. This function will not use the index. + polygon. This function will *NOT* use the q3c index. - q3c_version() -- returns the version of Q3C that is installed ## Query examples -- The cone search (the query of all objects within the circular region of the sky): - For example to query all objects within radius of 0.1 deg from (ra,dec) = (11,12)deg in the table mytable you would do: +- The cone search (the query of all objects within the circle around around the point on the sky): + For example to query all objects within radius of 0.1 deg from (ra,dec) = (11,12) deg in the table mytable you would do: + ``` my_db# SELECT * FROM mytable WHERE q3c_radial_query(ra, dec, 11, 12, 0.1); ``` -The order of arguments is important, so that the column names of the table should come first, and the -location where you search after, otherwise the index won't be used. + +The order of arguments of q3c_radial_query() is important, so that the column names of +the table should come first, and the location where you search after, otherwise the index won't be used. There is also an alternative way of doing cone searches which could be a bit faster if the table that you are working with that table that is small. In @@ -159,6 +163,7 @@ table: ``` my_db# SELECT * FROM mytable WHERE q3c_join(11, 12, ra, dec, 0.1); ``` +Note here ra,dec column names are 3rd and 4th argument respectively. - The ellipse search: search for objects within the ellipse from a given point: ``` @@ -202,9 +207,9 @@ index is going to be used or not. The ra,dec columns from the table with the index should go after the ra,dec columns from the table without the index. It is important that the query will return *ALL* the pairs within the matching -distance, rather than just nearest neighbors. See the nearest neighbors queries below. +distance, rather than just nearest neighbors. See below for examples of nearest neighbor queries. -If every object in table1 have his own error circle ( we'll assume +If every object in table1 have their own error circle/matching radius ( we'll assume that the radius of that circle in degrees is stored in the column "err"), then you should run the query: