33 #include "muse_pixgrid.h"
35 #include "muse_quality.h"
36 #include "muse_utils.h"
62 muse_pixgrid_new(cpl_size aSizeX, cpl_size aSizeY, cpl_size aSizeZ)
65 pixels->size_x = aSizeX;
66 pixels->size_y = aSizeY;
67 pixels->size_z = aSizeZ;
68 cpl_size size = aSizeX * aSizeY * aSizeZ;
69 pixels->pix = cpl_calloc(size,
sizeof(cpl_size));
90 muse_pixgrid_add(
muse_pixgrid *aPixels, cpl_size aIndex, cpl_size aRow)
95 if (aPixels->pix[aIndex] == 0 && aRow > 0) {
97 aPixels->pix[aIndex] = aRow;
98 }
else if (aPixels->pix[aIndex] == 0 && aRow == 0) {
100 cpl_size i_ext = aPixels->n_ext++;
101 if (aPixels->n_ext > aPixels->n_alloc) {
102 aPixels->n_alloc = 2 * aPixels->n_ext;
103 aPixels->ext = cpl_realloc(aPixels->ext,
106 aPixels->ext[i_ext].npix = 1;
107 aPixels->ext[i_ext].pix = cpl_malloc(
sizeof(cpl_size));
108 aPixels->ext[i_ext].pix[0] = aRow ;
109 aPixels->pix[aIndex] = - (i_ext + 1);
110 }
else if (aPixels->pix[aIndex] > 0) {
112 cpl_size i_ext = aPixels->n_ext++;
113 if (aPixels->n_ext > aPixels->n_alloc) {
114 aPixels->n_alloc = 2 * aPixels->n_ext;
115 aPixels->ext = cpl_realloc(aPixels->ext,
118 aPixels->ext[i_ext].npix = 2;
119 aPixels->ext[i_ext].pix = cpl_malloc(2 *
sizeof(cpl_size));
120 aPixels->ext[i_ext].pix[0] = aPixels->pix[aIndex];
121 aPixels->ext[i_ext].pix[1] = aRow;
122 aPixels->pix[aIndex] = - (i_ext + 1);
125 cpl_size i_ext = - aPixels->pix[aIndex] - 1;
126 int i_pix = aPixels->ext[i_ext].npix;
127 aPixels->ext[i_ext].npix++;
128 aPixels->ext[i_ext].pix
129 = cpl_realloc(aPixels->ext[i_ext].pix,
130 aPixels->ext[i_ext].npix *
sizeof(cpl_size));
131 aPixels->ext[i_ext].pix[i_pix] = aRow;
169 cpl_size aXSize, cpl_size aYSize, cpl_size aZSize)
171 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, NULL);
174 cpl_msg_error(__func__,
"Invalid pixel table (no entries?)");
175 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
178 cpl_ensure(aXSize > 0 && aYSize > 0 && aZSize > 0, CPL_ERROR_ILLEGAL_INPUT,
185 double crval3 = cpl_propertylist_get_double(aHeader,
"CRVAL3"),
186 crpix3 = cpl_propertylist_get_double(aHeader,
"CRPIX3"),
187 cd33 = cpl_propertylist_get_double(aHeader,
"CD3_3");
190 cpl_boolean loglambda = !strncmp(cpl_propertylist_get_string(aHeader,
"CTYPE3"),
193 double ptxoff = 0., ptyoff = 0.;
195 ptxoff = cpl_propertylist_get_double(aPixtable->
header,
"CRVAL1");
196 ptyoff = cpl_propertylist_get_double(aPixtable->
header,
"CRVAL2");
198 float *xpos = cpl_table_get_data_float(aPixtable->
table, MUSE_PIXTABLE_XPOS),
199 *ypos = cpl_table_get_data_float(aPixtable->
table, MUSE_PIXTABLE_YPOS),
200 *lbda = cpl_table_get_data_float(aPixtable->
table, MUSE_PIXTABLE_LAMBDA);
201 if (!xpos || !ypos || !lbda) {
202 cpl_msg_error(__func__,
"Missing pixel table column (%p %p %p): %s",
203 (
void *)xpos, (
void *)ypos, (
void *)lbda,
204 cpl_error_get_message());
205 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
208 #ifdef ESO_ENABLE_DEBUG
210 if (getenv(
"MUSE_DEBUG_GRID_CONVERSION")) {
211 debug = atoi(getenv(
"MUSE_DEBUG_GRID_CONVERSION"));
214 printf(
"crpix=%f %f %f, crval=%f %f %f, cd=%e %e %f\n",
215 wcs->crpix1, wcs->
crpix2, crpix3, wcs->crval1, wcs->
crval2, crval3,
216 wcs->cd11, wcs->
cd22, cd33);
220 wcs->crval1 /= CPL_MATH_DEG_RAD;
221 wcs->
crval2 /= CPL_MATH_DEG_RAD;
223 double timeinit = cpl_test_get_walltime(),
224 timeprogress = timeinit,
225 cpuinit = cpl_test_get_cputime();
226 cpl_boolean showprogress = cpl_msg_get_level() == CPL_MSG_DEBUG
227 || cpl_msg_get_log_level() == CPL_MSG_DEBUG;
228 muse_pixgrid *pixgrid = muse_pixgrid_new(aXSize, aYSize, aZSize);
233 cpl_array *asel = cpl_table_where_selected(aPixtable->
table);
234 const cpl_size *sel = cpl_array_get_data_cplsize_const(asel);
235 cpl_size isel, nsel = cpl_array_get_size(asel);
236 for (isel = 0 ; isel < nsel; isel++) {
237 if (showprogress && !((isel+1) % 1000000ll)) {
238 double timenow = cpl_test_get_walltime();
239 if (timenow - timeprogress > 30.) {
240 timeprogress = timenow;
241 double percent = 100. * (isel + 1.) / nsel,
242 elapsed = timeprogress - timeinit,
243 remaining = (100. - percent) * elapsed / percent;
246 cpl_msg_info_overwritable(__func__,
"pixel grid creation is %.1f%% "
247 "complete, %gs elapsed, ~%gs remaining",
248 percent, elapsed, remaining);
251 cpl_size n = sel[isel];
256 (ypos[n] + ptyoff) / CPL_MATH_DEG_RAD, &xpx, &ypx);
261 int x = lround(xpx) - 1,
263 z = lround((lbda[n] - crval3) / cd33 + crpix3) - 1;
265 z = lround(crval3 / cd33 * log(lbda[n] / crval3));
268 #ifdef ESO_ENABLE_DEBUG
270 printf(
"%"CPL_SIZE_FORMAT
": %f %f %f -> %d %d %d (%"CPL_SIZE_FORMAT
")\n",
271 n, xpos[n] + ptxoff, ypos[n] + ptyoff, lbda[n], x, y, z, idx);
276 muse_pixgrid_add(pixgrid, idx, n);
278 cpl_array_delete(asel);
282 pixgrid->ext = cpl_realloc(pixgrid->ext,
284 pixgrid->n_alloc = pixgrid->n_ext;
285 #ifdef ESO_ENABLE_DEBUG
291 cpl_size idx, npix_sum = 0;
292 for (idx = 0; idx < aXSize * aYSize * aZSize; idx++) {
295 double timefini = cpl_test_get_walltime(),
296 cpufini = cpl_test_get_cputime();
297 cpl_msg_debug(__func__,
"pixel grid: %dx%dx%d, %"CPL_SIZE_FORMAT
" pixels "
298 "total, %"CPL_SIZE_FORMAT
" (%.1f%%) in extension map; took %gs "
299 "(wall-clock) and %gs (CPU) to create", (
int)pixgrid->size_x,
300 (
int)pixgrid->size_y, (
int)pixgrid->size_z, npix_sum, pixgrid->n_ext,
301 (
double)pixgrid->n_ext / npix_sum * 100., timefini - timeinit,
331 double aZMin,
double aZMax,
double aDZ,
float *aXMin)
333 cpl_ensure(aTable, CPL_ERROR_NULL_INPUT, NULL);
334 cpl_size nrow = cpl_table_get_nrow(aTable);
336 cpl_msg_error(__func__,
"Invalid pixel table (no entries?)");
337 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
342 float *xpos = cpl_table_get_data_float(aTable, MUSE_PIXTABLE_XPOS),
343 *lbda = cpl_table_get_data_float(aTable, MUSE_PIXTABLE_LAMBDA);
344 if (!xpos || !lbda) {
345 cpl_msg_error(__func__,
"Missing pixel table column (%p %p): %s",
346 (
void *)xpos, (
void *)lbda, cpl_error_get_message());
347 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
352 cpl_array *selection = cpl_table_where_selected(aTable);
353 cpl_size nsel = cpl_array_get_size(selection);
354 const cpl_size *sel = cpl_array_get_data_cplsize_const(selection);
357 float xlo = FLT_MAX, xhi = -FLT_MAX;
359 for (i = 0; i < nsel; i++) {
360 if (xpos[sel[i]] > xhi) xhi = xpos[sel[i]];
361 if (xpos[sel[i]] < xlo) xlo = xpos[sel[i]];
368 cpl_size xsize = ceil((xhi - xlo) / aDX) + 1,
369 zsize = ceil((aZMax - aZMin) / aDZ) + 1;
370 muse_pixgrid *pixgrid = muse_pixgrid_new(xsize, 1, zsize);
373 for (i = 0; i < nsel; i++) {
376 int x = lround((xpos[sel[i]] - xlo) / aDX),
377 z = lround((lbda[sel[i]] - aZMin) / aDZ);
380 muse_pixgrid_add(pixgrid, idx, sel[i]);
382 cpl_array_delete(selection);
384 pixgrid->ext = cpl_realloc(pixgrid->ext,
386 pixgrid->n_alloc = pixgrid->n_ext;
403 cpl_free(aPixels->pix);
405 for (i_ext = 0; i_ext < aPixels->n_ext; i_ext++) {
406 cpl_free(aPixels->ext[i_ext].pix);
409 cpl_free(aPixels->ext);
410 aPixels->n_alloc = 0;
muse_pixtable_wcs
State of the astrometric calibration of a MUSE pixel table.
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 pixgrid, linking the grid points to entries (=rows) in...
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.
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.
void muse_pixgrid_delete(muse_pixgrid *aPixels)
Delete a pixgrid and remove its memory.
static cpl_size muse_pixgrid_get_index(muse_pixgrid *aPixels, cpl_size aX, cpl_size aY, cpl_size aZ, cpl_boolean aAllowOutside)
Get the grid index determined from all three coordinates.
static cpl_size muse_pixgrid_get_count(muse_pixgrid *aPixels, cpl_size aIndex)
Return the number of rows stored in one pixel.
cpl_propertylist * header
The FITS header.