33 #define omp_get_max_threads() 1 34 #define omp_get_thread_num() 0 39 #include "muse_pixgrid.h" 41 #include "muse_pfits.h" 42 #include "muse_quality.h" 43 #include "muse_utils.h" 70 muse_pixgrid_new(cpl_size aSizeX, cpl_size aSizeY, cpl_size aSizeZ,
71 unsigned short aNMaps)
77 pixels->pix = cpl_calloc(aSizeX * aSizeY * aSizeZ,
sizeof(cpl_size));
79 pixels->nmaps = aNMaps;
80 pixels->nxalloc = cpl_calloc(aNMaps,
sizeof(cpl_size));
82 pixels->nxmap = cpl_calloc(aNMaps,
sizeof(cpl_size));
104 muse_pixgrid_add(
muse_pixgrid *aGrid, cpl_size aIndex, cpl_size aRow,
105 unsigned short aXIdx)
111 if (aGrid->pix[aIndex] == 0 && aRow > 0) {
113 aGrid->pix[aIndex] = aRow;
114 }
else if (aGrid->pix[aIndex] == 0 && aRow == 0) {
116 cpl_size iext = aGrid->nxmap[aXIdx]++;
117 if (aGrid->nxmap[aXIdx] > aGrid->nxalloc[aXIdx]) {
119 aGrid->nxalloc[aXIdx] = 2 * aGrid->nxmap[aXIdx];
120 aGrid->xmaps[aXIdx] = cpl_realloc(aGrid->xmaps[aXIdx],
121 aGrid->nxalloc[aXIdx]
124 aGrid->xmaps[aXIdx][iext].npix = 1;
125 aGrid->xmaps[aXIdx][iext].pix = cpl_malloc(
sizeof(cpl_size));
126 aGrid->xmaps[aXIdx][iext].pix[0] = aRow;
127 aGrid->pix[aIndex] = -(iext + 1 + ((cpl_size)aXIdx << XMAP_LSHIFT));
128 }
else if (aGrid->pix[aIndex] > 0) {
130 cpl_size iext = aGrid->nxmap[aXIdx]++;
131 if (aGrid->nxmap[aXIdx] > aGrid->nxalloc[aXIdx]) {
133 aGrid->nxalloc[aXIdx] = 2 * aGrid->nxmap[aXIdx];
134 aGrid->xmaps[aXIdx] = cpl_realloc(aGrid->xmaps[aXIdx],
135 aGrid->nxalloc[aXIdx]
138 aGrid->xmaps[aXIdx][iext].npix = 2;
139 aGrid->xmaps[aXIdx][iext].pix = cpl_malloc(2 *
sizeof(cpl_size));
140 aGrid->xmaps[aXIdx][iext].pix[0] = aGrid->pix[aIndex];
141 aGrid->xmaps[aXIdx][iext].pix[1] = aRow;
142 aGrid->pix[aIndex] = -(iext + 1 + ((cpl_size)aXIdx << XMAP_LSHIFT));
145 cpl_size iext = (-aGrid->pix[aIndex] - 1) & PT_IDX_MASK;
147 unsigned int ipix = aGrid->xmaps[aXIdx][iext].npix;
148 aGrid->xmaps[aXIdx][iext].npix++;
149 aGrid->xmaps[aXIdx][iext].pix = cpl_realloc(aGrid->xmaps[aXIdx][iext].pix,
150 (ipix + 1) *
sizeof(cpl_size));
151 aGrid->xmaps[aXIdx][iext].pix[ipix] = aRow;
164 muse_pixgrid_dump_xmaps(
muse_pixgrid *aGrid, cpl_boolean aFull)
170 cpl_msg_debug(__func__,
"Dumping %u extension maps:", aGrid->nmaps);
172 for (ix = 0; ix < aGrid->nmaps; ix++) {
173 cpl_msg_debug(__func__,
"- Map %u (%"CPL_SIZE_FORMAT
" / %"CPL_SIZE_FORMAT
174 " entries):", ix + 1u, aGrid->nxmap[ix], aGrid->nxalloc[ix]);
176 nmax = aFull ? aGrid->nxalloc[ix] : 0;
177 for (iext = 0; iext < nmax; iext++) {
179 for (ipix = 0; ipix < aGrid->xmaps[ix][iext].npix; ipix++) {
180 cpl_size value = aGrid->xmaps[ix][iext].pix[ipix];
181 char *warning = NULL;
182 if (value < 0 || value > 13534057) {
183 warning = cpl_sprintf(
" WARNING!!!");
186 cpl_msg_debug(__func__,
" %08"CPL_SIZE_FORMAT
" %u: %"CPL_SIZE_FORMAT
"%s",
187 iext + 1, ipix + 1u, value, warning ? warning :
"");
191 cpl_msg_debug(__func__,
" %u: %"CPL_SIZE_FORMAT
"%s", ipix + 1u,
192 value, warning ? warning :
"");
195 if (1 + iext > aGrid->nxmap[ix]) {
196 cpl_msg_debug(__func__,
"Not initialized!");
238 cpl_size aXSize, cpl_size aYSize, cpl_size aZSize)
240 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, NULL);
243 cpl_msg_error(__func__,
"Invalid pixel table (no entries?)");
244 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
247 cpl_ensure(aXSize > 0 && aYSize > 0 && aZSize > 0, CPL_ERROR_ILLEGAL_INPUT,
260 cpl_boolean loglambda = ctype3 && (!strncmp(ctype3,
"AWAV-LOG", 9) ||
261 !strncmp(ctype3,
"WAVE-LOG", 9));
263 double ptxoff = 0., ptyoff = 0.;
271 if (!xpos || !ypos || !lbda) {
272 cpl_msg_error(__func__,
"Missing pixel table column (%p %p %p): %s",
273 (
void *)xpos, (
void *)ypos, (
void *)lbda,
274 cpl_error_get_message());
275 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
279 #ifdef ESO_ENABLE_DEBUG 281 if (getenv(
"MUSE_DEBUG_GRID_CONVERSION")) {
282 debug = atoi(getenv(
"MUSE_DEBUG_GRID_CONVERSION"));
285 printf(
"crpix=%f %f %f, crval=%f %f %f, cd=%e %e %f\n",
286 wcs->crpix1, wcs->
crpix2, crpix3, wcs->crval1, wcs->
crval2, crval3,
287 wcs->cd11, wcs->
cd22, cd33);
291 wcs->crval1 /= CPL_MATH_DEG_RAD;
292 wcs->
crval2 /= CPL_MATH_DEG_RAD;
294 double timeinit = cpl_test_get_walltime(),
295 timeprogress = timeinit,
296 cpuinit = cpl_test_get_cputime();
297 cpl_boolean showprogress = cpl_msg_get_level() == CPL_MSG_DEBUG
298 || cpl_msg_get_log_level() == CPL_MSG_DEBUG;
304 cpl_array *asel = NULL;
305 const cpl_size *sel = NULL;
306 cpl_size nsel = cpl_table_count_selected(aPixtable->
table);
308 asel = cpl_table_where_selected(aPixtable->
table);
309 sel = cpl_array_get_data_cplsize_const(asel);
314 int nth = omp_get_max_threads() > XMAP_BITMASK ? XMAP_BITMASK
315 : omp_get_max_threads();
317 cpl_array *az1 = cpl_array_new(nth, CPL_TYPE_INT),
318 *az2 = cpl_array_new(nth, CPL_TYPE_INT);
321 cpl_array_fill_window_int(az1, aZSize, nth, -1);
322 cpl_array_fill_window_int(az2, aZSize, nth, -2);
325 double base = nth > aZSize ? 1. : (double)aZSize / nth;
327 for (ith = 0; ith < nth && ith < aZSize; ith++) {
328 cpl_array_set_int(az1, ith, lround(base * ith));
329 cpl_array_set_int(az2, ith, lround(base * (ith + 1) - 1));
335 cpl_array_set_int(az1, 0, -INT_MAX / 2 + 1);
336 cpl_array_set_int(az2, ith - 1, INT_MAX / 2 - 1);
338 if (aZSize < 2*nth) {
339 printf(
"arrays (base = %f, aZSize = %d, nth = %d):\n",
340 base, (
int)aZSize, nth);
341 cpl_array_dump(az1, 0, nth, stdout);
342 cpl_array_dump(az2, 0, nth, stdout);
348 muse_pixgrid *grid = muse_pixgrid_new(aXSize, aYSize, aZSize, nth);
351 #ifdef ESO_ENABLE_DEBUG 352 #pragma omp parallel num_threads(nth) default(none) \ 353 shared(aXSize, aYSize, aZSize, az1, az2, cd33, crpix3, crval3, debug,\ 354 grid, lbda, loglambda, nsel, ptxoff, ptyoff, sel, \ 355 showprogress, timeinit, timeprogress, wcs, xpos, ypos) 357 #pragma omp parallel num_threads(nth) default(none) \ 358 shared(aXSize, aYSize, aZSize, az1, az2, cd33, crpix3, crval3, grid, \ 359 lbda, loglambda, nsel, ptxoff, ptyoff, sel, showprogress, \ 360 timeinit, timeprogress, wcs, xpos, ypos) 364 unsigned short ithread = omp_get_thread_num();
365 int z1 = cpl_array_get_int(az1, ithread, NULL),
366 z2 = cpl_array_get_int(az2, ithread, NULL),
367 zrange = z2 - z1 + 1;
373 cpl_msg_debug(__func__,
"%lld z pixels, thread index %hu, z range: %d..%d " 374 "(%d planes)", aZSize, ithread, z1, z2, zrange);
376 cpl_msg_debug(__func__,
"%lld z pixels, thread index %hu, z range: %d..%d " 377 "(%d planes) --> thread not used!", aZSize, ithread, z1, z2,
384 for (isel = 0 ; zrange > 0 && isel < nsel; isel++) {
386 if (showprogress && !((isel+1) % 1000000ll)) {
387 double timenow = cpl_test_get_walltime();
388 if (timenow - timeprogress > 30.) {
389 timeprogress = timenow;
390 double percent = 100. * (isel + 1.) / nsel,
391 elapsed = timeprogress - timeinit,
392 remaining = (100. - percent) * elapsed / percent;
395 cpl_msg_info_overwritable(__func__,
"pixel grid creation is %.1f%% " 396 "complete, %.1fs elapsed, ~%.1fs remaining",
397 percent, elapsed, remaining);
403 cpl_size n = sel ? sel[isel] : isel;
406 z = lround(crval3 / cd33 * log(lbda[n] / crval3)) + crpix3 - 1;
408 z = lround((lbda[n] - crval3) / cd33 + crpix3) - 1;
410 if (z < z1 || z > z2) {
418 (ypos[n] + ptyoff) / CPL_MATH_DEG_RAD,
424 int x = lround(xpx) - 1,
427 #ifdef ESO_ENABLE_DEBUG 429 printf(
"%"CPL_SIZE_FORMAT
": %f %f %f -> %d %d %d (%"CPL_SIZE_FORMAT
")\n",
430 n, xpos[n] + ptxoff, ypos[n] + ptyoff, lbda[n], x, y, z, idx);
435 muse_pixgrid_add(grid, idx, n, ithread);
440 grid->xmaps[ithread] = cpl_realloc(grid->xmaps[ithread],
443 grid->nxalloc[ithread] = grid->nxmap[ithread];
445 cpl_array_delete(asel);
447 cpl_array_delete(az1);
448 cpl_array_delete(az2);
449 #ifdef ESO_ENABLE_DEBUG 455 cpl_size idx, npix = 0;
456 for (idx = 0; idx < aXSize * aYSize * aZSize; idx++) {
460 for (idx = 0; idx < (cpl_size)grid->nmaps; idx++) {
461 nxmap += grid->nxmap[idx];
464 char *msg = cpl_sprintf(
"Pixels got lost while creating the cube (input " 465 "pixel table: %"CPL_SIZE_FORMAT
", output pixel grid" 466 ": %"CPL_SIZE_FORMAT
")", nsel, npix);
467 cpl_msg_error(__func__,
"%s:", msg);
468 muse_pixgrid_dump_xmaps(grid, CPL_FALSE);
469 cpl_error_set_message(__func__, CPL_ERROR_ILLEGAL_OUTPUT,
"%s!", msg);
472 double timefini = cpl_test_get_walltime(),
473 cpufini = cpl_test_get_cputime();
474 cpl_msg_debug(__func__,
"pixel grid: %dx%dx%d, %"CPL_SIZE_FORMAT
" pixels " 475 "total, %"CPL_SIZE_FORMAT
" (%.1f%%) in %hu extension maps; took" 476 " %gs (wall-clock) and %gs (CPU) to create", (
int)grid->nx,
477 (
int)grid->ny, (
int)grid->nz, npix, nxmap,
478 (
double)nxmap / npix * 100., grid->nmaps, timefini - timeinit,
508 double aZMin,
double aZMax,
double aDZ,
float *aXMin)
510 cpl_ensure(aTable, CPL_ERROR_NULL_INPUT, NULL);
511 cpl_size nrow = cpl_table_get_nrow(aTable);
513 cpl_msg_error(__func__,
"Invalid pixel table (no entries?)");
514 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
521 if (!xpos || !lbda) {
522 cpl_msg_error(__func__,
"Missing pixel table column (%p %p): %s",
523 (
void *)xpos, (
void *)lbda, cpl_error_get_message());
524 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
529 cpl_array *selection = cpl_table_where_selected(aTable);
530 cpl_size nsel = cpl_array_get_size(selection);
531 const cpl_size *sel = cpl_array_get_data_cplsize_const(selection);
534 float xlo = FLT_MAX, xhi = -FLT_MAX;
536 for (i = 0; i < nsel; i++) {
537 if (xpos[sel[i]] > xhi) xhi = xpos[sel[i]];
538 if (xpos[sel[i]] < xlo) xlo = xpos[sel[i]];
545 cpl_size xsize = ceil((xhi - xlo) / aDX) + 1,
546 zsize = ceil((aZMax - aZMin) / aDZ) + 1;
547 muse_pixgrid *grid = muse_pixgrid_new(xsize, 1, zsize, 1);
550 for (i = 0; i < nsel; i++) {
553 int x = lround((xpos[sel[i]] - xlo) / aDX),
554 z = lround((lbda[sel[i]] - aZMin) / aDZ);
557 muse_pixgrid_add(grid, idx, sel[i], 0);
559 cpl_array_delete(selection);
561 grid->xmaps[0] = cpl_realloc(grid->xmaps[0],
563 grid->nxalloc[0] = grid->nxmap[0];
580 cpl_free(aGrid->pix);
584 for (ix = 0; ix < aGrid->nmaps; ix++) {
586 for (iext = 0; iext < aGrid->nxalloc[ix]; iext++) {
587 cpl_free(aGrid->xmaps[ix][iext].pix);
590 cpl_free(aGrid->xmaps[ix]);
592 cpl_free(aGrid->xmaps);
594 cpl_free(aGrid->nxmap);
596 cpl_free(aGrid->nxalloc);
597 aGrid->nxalloc = NULL;
#define MUSE_PIXTABLE_XPOS
muse_pixtable_wcs
State of the astrometric calibration of a MUSE pixel table.
double muse_pfits_get_cd(const cpl_propertylist *aHeaders, unsigned int aAxisI, unsigned int aAxisJ)
find out the WCS coordinate at the reference point
muse_pixgrid * muse_pixgrid_2d_create(cpl_table *aTable, double aDX, double aZMin, double aZMax, double aDZ, float *aXMin)
Convert selected rows of a pixel table into 2D pixel grid, linking the grid points to entries (=rows)...
double muse_pfits_get_crval(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS coordinate at the reference point
A structure containing a spatial two-axis WCS.
muse_pixgrid * muse_pixgrid_create(muse_pixtable *aPixtable, cpl_propertylist *aHeader, cpl_size aXSize, cpl_size aYSize, cpl_size aZSize)
Convert selected rows of a pixel table into pixel grid, linking the grid points to entries (=rows) in...
cpl_size muse_pixtable_get_nrow(const muse_pixtable *aPixtable)
get the number of rows within the pixel table
static void muse_wcs_pixel_from_projplane_fast(muse_wcs *aWCS, double aX, double aY, double *aXOut, double *aYOut)
Convert from projection plane coordinates to pixel coordinates.
cpl_table * table
The pixel table.
double muse_pfits_get_crpix(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS reference point
void muse_pixgrid_delete(muse_pixgrid *aGrid)
Delete a pixel grid and remove its memory.
muse_wcs * muse_wcs_new(cpl_propertylist *aHeader)
Create a new WCS structure from a given FITS header.
Structure definition of MUSE pixel table.
muse_pixtable_wcs muse_pixtable_wcs_check(muse_pixtable *aPixtable)
Check the state of the world coordinate system of a pixel table.
static void muse_wcs_pixel_from_celestial_fast(muse_wcs *aWCS, double aRA, double aDEC, double *aX, double *aY)
Convert from celestial spherical coordinates to pixel coordinates.
const char * muse_pfits_get_ctype(const cpl_propertylist *aHeaders, unsigned int aAxis)
find out the WCS axis type string
#define MUSE_PIXTABLE_LAMBDA
static cpl_size muse_pixgrid_get_index(muse_pixgrid *aGrid, cpl_size aX, cpl_size aY, cpl_size aZ, cpl_boolean aAllowOutside)
Get the grid index determined from all three coordinates.
#define MUSE_PIXTABLE_YPOS
static cpl_size muse_pixgrid_get_count(muse_pixgrid *aGrid, cpl_size aIndex)
Return the number of rows stored in one pixel.
cpl_propertylist * header
The FITS header.