00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifdef HAVE_CONFIG_H
00023 #include <config.h>
00024 #endif
00025
00026
00027
00028
00029 #include <cpl.h>
00030 #include <math.h>
00031 #include <string.h>
00032
00033 #include "muse_pixgrid.h"
00034
00035 #include "muse_pfits.h"
00036 #include "muse_quality.h"
00037 #include "muse_utils.h"
00038 #include "muse_wcs.h"
00039
00040
00048
00049
00052
00061
00062 static muse_pixgrid *
00063 muse_pixgrid_new(cpl_size aSizeX, cpl_size aSizeY, cpl_size aSizeZ)
00064 {
00065 muse_pixgrid *pixels = cpl_calloc(1, sizeof(muse_pixgrid));
00066 pixels->size_x = aSizeX;
00067 pixels->size_y = aSizeY;
00068 pixels->size_z = aSizeZ;
00069 cpl_size size = aSizeX * aSizeY * aSizeZ;
00070 pixels->pix = cpl_calloc(size, sizeof(cpl_size));
00071 return pixels;
00072 }
00073
00074
00089
00090 static void
00091 muse_pixgrid_add(muse_pixgrid *aPixels, cpl_size aIndex, cpl_size aRow)
00092 {
00093 if (aIndex < 0) {
00094 return;
00095 }
00096 if (aPixels->pix[aIndex] == 0 && aRow > 0) {
00097
00098 aPixels->pix[aIndex] = aRow;
00099 } else if (aPixels->pix[aIndex] == 0 && aRow == 0) {
00100
00101 cpl_size i_ext = aPixels->n_ext++;
00102 if (aPixels->n_ext > aPixels->n_alloc) {
00103 aPixels->n_alloc = 2 * aPixels->n_ext;
00104 aPixels->ext = cpl_realloc(aPixels->ext,
00105 aPixels->n_alloc * sizeof(muse_pixels_ext));
00106 }
00107 aPixels->ext[i_ext].npix = 1;
00108 aPixels->ext[i_ext].pix = cpl_malloc(sizeof(cpl_size));
00109 aPixels->ext[i_ext].pix[0] = aRow ;
00110 aPixels->pix[aIndex] = - (i_ext + 1);
00111 } else if (aPixels->pix[aIndex] > 0) {
00112
00113 cpl_size i_ext = aPixels->n_ext++;
00114 if (aPixels->n_ext > aPixels->n_alloc) {
00115 aPixels->n_alloc = 2 * aPixels->n_ext;
00116 aPixels->ext = cpl_realloc(aPixels->ext,
00117 aPixels->n_alloc * sizeof(muse_pixels_ext));
00118 }
00119 aPixels->ext[i_ext].npix = 2;
00120 aPixels->ext[i_ext].pix = cpl_malloc(2 * sizeof(cpl_size));
00121 aPixels->ext[i_ext].pix[0] = aPixels->pix[aIndex];
00122 aPixels->ext[i_ext].pix[1] = aRow;
00123 aPixels->pix[aIndex] = - (i_ext + 1);
00124 } else {
00125
00126 cpl_size i_ext = - aPixels->pix[aIndex] - 1;
00127 int i_pix = aPixels->ext[i_ext].npix;
00128 aPixels->ext[i_ext].npix++;
00129 aPixels->ext[i_ext].pix
00130 = cpl_realloc(aPixels->ext[i_ext].pix,
00131 aPixels->ext[i_ext].npix * sizeof(cpl_size));
00132 aPixels->ext[i_ext].pix[i_pix] = aRow;
00133 }
00134 }
00135
00136
00167
00168 muse_pixgrid *
00169 muse_pixgrid_create(muse_pixtable *aPixtable, cpl_propertylist *aHeader,
00170 cpl_size aXSize, cpl_size aYSize, cpl_size aZSize)
00171 {
00172 cpl_ensure(aPixtable, CPL_ERROR_NULL_INPUT, NULL);
00173 cpl_size nrow = muse_pixtable_get_nrow(aPixtable);
00174 if (nrow == 0) {
00175 cpl_msg_error(__func__, "Invalid pixel table (no entries?)");
00176 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
00177 return NULL;
00178 }
00179 cpl_ensure(aXSize > 0 && aYSize > 0 && aZSize > 0, CPL_ERROR_ILLEGAL_INPUT,
00180 NULL);
00181 muse_pixtable_wcs wcstype = muse_pixtable_wcs_check(aPixtable);
00182 cpl_ensure(wcstype == MUSE_PIXTABLE_WCS_CELSPH ||
00183 wcstype == MUSE_PIXTABLE_WCS_PIXEL, CPL_ERROR_UNSUPPORTED_MODE,
00184 NULL);
00185
00186 double crval3 = muse_pfits_get_crval(aHeader, 3),
00187 crpix3 = muse_pfits_get_crpix(aHeader, 3),
00188 cd33 = muse_pfits_get_cd(aHeader, 3, 3);
00189 const char *ctype3 = muse_pfits_get_ctype(aHeader, 3);
00190 muse_wcs *wcs = muse_wcs_new(aHeader);
00191 wcs->iscelsph = wcstype == MUSE_PIXTABLE_WCS_CELSPH;
00192 cpl_boolean loglambda = ctype3 && (!strncmp(ctype3, "AWAV-LOG", 9) ||
00193 !strncmp(ctype3, "WAVE-LOG", 9));
00194
00195 double ptxoff = 0., ptyoff = 0.;
00196 if (wcs->iscelsph) {
00197 ptxoff = muse_pfits_get_crval(aPixtable->header, 1);
00198 ptyoff = muse_pfits_get_crval(aPixtable->header, 2);
00199 }
00200 float *xpos = cpl_table_get_data_float(aPixtable->table, MUSE_PIXTABLE_XPOS),
00201 *ypos = cpl_table_get_data_float(aPixtable->table, MUSE_PIXTABLE_YPOS),
00202 *lbda = cpl_table_get_data_float(aPixtable->table, MUSE_PIXTABLE_LAMBDA);
00203 if (!xpos || !ypos || !lbda) {
00204 cpl_msg_error(__func__, "Missing pixel table column (%p %p %p): %s",
00205 (void *)xpos, (void *)ypos, (void *)lbda,
00206 cpl_error_get_message());
00207 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
00208 return NULL;
00209 }
00210 #ifdef ESO_ENABLE_DEBUG
00211 int debug = 0;
00212 if (getenv("MUSE_DEBUG_GRID_CONVERSION")) {
00213 debug = atoi(getenv("MUSE_DEBUG_GRID_CONVERSION"));
00214 }
00215 if (debug) {
00216 printf("crpix=%f %f %f, crval=%f %f %f, cd=%e %e %f\n",
00217 wcs->crpix1, wcs->crpix2, crpix3, wcs->crval1, wcs->crval2, crval3,
00218 wcs->cd11, wcs->cd22, cd33);
00219 }
00220 #endif
00221 if (wcs->iscelsph) {
00222 wcs->crval1 /= CPL_MATH_DEG_RAD;
00223 wcs->crval2 /= CPL_MATH_DEG_RAD;
00224 }
00225 double timeinit = cpl_test_get_walltime(),
00226 timeprogress = timeinit,
00227 cpuinit = cpl_test_get_cputime();
00228 cpl_boolean showprogress = cpl_msg_get_level() == CPL_MSG_DEBUG
00229 || cpl_msg_get_log_level() == CPL_MSG_DEBUG;
00230 muse_pixgrid *pixgrid = muse_pixgrid_new(aXSize, aYSize, aZSize);
00231
00232
00233
00234
00235 cpl_array *asel = cpl_table_where_selected(aPixtable->table);
00236 const cpl_size *sel = cpl_array_get_data_cplsize_const(asel);
00237 cpl_size isel, nsel = cpl_array_get_size(asel);
00238 for (isel = 0 ; isel < nsel; isel++) {
00239 if (showprogress && !((isel+1) % 1000000ll)) {
00240 double timenow = cpl_test_get_walltime();
00241 if (timenow - timeprogress > 30.) {
00242 timeprogress = timenow;
00243 double percent = 100. * (isel + 1.) / nsel,
00244 elapsed = timeprogress - timeinit,
00245 remaining = (100. - percent) * elapsed / percent;
00246
00247
00248 cpl_msg_info_overwritable(__func__, "pixel grid creation is %.1f%% "
00249 "complete, %gs elapsed, ~%gs remaining",
00250 percent, elapsed, remaining);
00251 }
00252 }
00253 cpl_size n = sel[isel];
00254
00255 double xpx, ypx;
00256 if (wcs->iscelsph) {
00257 muse_wcs_pixel_from_celestial_fast(wcs, (xpos[n] + ptxoff) / CPL_MATH_DEG_RAD,
00258 (ypos[n] + ptyoff) / CPL_MATH_DEG_RAD, &xpx, &ypx);
00259 } else {
00260 muse_wcs_pixel_from_projplane_fast(wcs, xpos[n], ypos[n],
00261 &xpx, &ypx);
00262 }
00263 int x = lround(xpx) - 1,
00264 y = lround(ypx) - 1,
00265 z = lround((lbda[n] - crval3) / cd33 + crpix3) - 1;
00266 if (loglambda) {
00267 z = lround(crval3 / cd33 * log(lbda[n] / crval3)) + crpix3 - 1;
00268 }
00269 cpl_size idx = muse_pixgrid_get_index(pixgrid, x, y, z, CPL_TRUE);
00270 #ifdef ESO_ENABLE_DEBUG
00271 if (debug) {
00272 printf("%"CPL_SIZE_FORMAT": %f %f %f -> %d %d %d (%"CPL_SIZE_FORMAT")\n",
00273 n, xpos[n] + ptxoff, ypos[n] + ptyoff, lbda[n], x, y, z, idx);
00274 }
00275 #endif
00276
00277
00278 muse_pixgrid_add(pixgrid, idx, n);
00279 }
00280 cpl_array_delete(asel);
00281 cpl_free(wcs);
00282
00283
00284 pixgrid->ext = cpl_realloc(pixgrid->ext,
00285 pixgrid->n_ext * sizeof(muse_pixels_ext));
00286 pixgrid->n_alloc = pixgrid->n_ext;
00287 #ifdef ESO_ENABLE_DEBUG
00288 if (debug) {
00289 fflush(stdout);
00290 }
00291 #endif
00292
00293 cpl_size idx, npix_sum = 0;
00294 for (idx = 0; idx < aXSize * aYSize * aZSize; idx++) {
00295 npix_sum += muse_pixgrid_get_count(pixgrid, idx);
00296 }
00297 double timefini = cpl_test_get_walltime(),
00298 cpufini = cpl_test_get_cputime();
00299 cpl_msg_debug(__func__, "pixel grid: %dx%dx%d, %"CPL_SIZE_FORMAT" pixels "
00300 "total, %"CPL_SIZE_FORMAT" (%.1f%%) in extension map; took %gs "
00301 "(wall-clock) and %gs (CPU) to create", (int)pixgrid->size_x,
00302 (int)pixgrid->size_y, (int)pixgrid->size_z, npix_sum, pixgrid->n_ext,
00303 (double)pixgrid->n_ext / npix_sum * 100., timefini - timeinit,
00304 cpufini - cpuinit);
00305
00306 return pixgrid;
00307 }
00308
00309
00330
00331 muse_pixgrid *
00332 muse_pixgrid_2d_create(cpl_table *aTable, double aDX,
00333 double aZMin, double aZMax, double aDZ, float *aXMin)
00334 {
00335 cpl_ensure(aTable, CPL_ERROR_NULL_INPUT, NULL);
00336 cpl_size nrow = cpl_table_get_nrow(aTable);
00337 if (nrow == 0) {
00338 cpl_msg_error(__func__, "Invalid pixel table (no entries?)");
00339 cpl_error_set(__func__, CPL_ERROR_NULL_INPUT);
00340 return NULL;
00341 }
00342
00343
00344 float *xpos = cpl_table_get_data_float(aTable, MUSE_PIXTABLE_XPOS),
00345 *lbda = cpl_table_get_data_float(aTable, MUSE_PIXTABLE_LAMBDA);
00346 if (!xpos || !lbda) {
00347 cpl_msg_error(__func__, "Missing pixel table column (%p %p): %s",
00348 (void *)xpos, (void *)lbda, cpl_error_get_message());
00349 cpl_error_set(__func__, CPL_ERROR_DATA_NOT_FOUND);
00350 return NULL;
00351 }
00352
00353
00354 cpl_array *selection = cpl_table_where_selected(aTable);
00355 cpl_size nsel = cpl_array_get_size(selection);
00356 const cpl_size *sel = cpl_array_get_data_cplsize_const(selection);
00357
00358
00359 float xlo = FLT_MAX, xhi = -FLT_MAX;
00360 cpl_size i;
00361 for (i = 0; i < nsel; i++) {
00362 if (xpos[sel[i]] > xhi) xhi = xpos[sel[i]];
00363 if (xpos[sel[i]] < xlo) xlo = xpos[sel[i]];
00364 }
00365 if (aXMin) {
00366 *aXMin = xlo;
00367 }
00368
00369
00370 cpl_size xsize = ceil((xhi - xlo) / aDX) + 1,
00371 zsize = ceil((aZMax - aZMin) / aDZ) + 1;
00372 muse_pixgrid *pixgrid = muse_pixgrid_new(xsize, 1, zsize);
00373
00374
00375 for (i = 0; i < nsel; i++) {
00376
00377
00378 int x = lround((xpos[sel[i]] - xlo) / aDX),
00379 z = lround((lbda[sel[i]] - aZMin) / aDZ);
00380 cpl_size idx = muse_pixgrid_get_index(pixgrid, x, 0, z, CPL_TRUE);
00381
00382 muse_pixgrid_add(pixgrid, idx, sel[i]);
00383 }
00384 cpl_array_delete(selection);
00385
00386 pixgrid->ext = cpl_realloc(pixgrid->ext,
00387 pixgrid->n_ext * sizeof(muse_pixels_ext));
00388 pixgrid->n_alloc = pixgrid->n_ext;
00389
00390 return pixgrid;
00391 }
00392
00393
00398
00399 void
00400 muse_pixgrid_delete(muse_pixgrid *aPixels)
00401 {
00402 if (!aPixels) {
00403 return;
00404 }
00405 cpl_free(aPixels->pix);
00406 cpl_size i_ext;
00407 for (i_ext = 0; i_ext < aPixels->n_ext; i_ext++) {
00408 cpl_free(aPixels->ext[i_ext].pix);
00409 }
00410 aPixels->n_ext = 0;
00411 cpl_free(aPixels->ext);
00412 aPixels->n_alloc = 0;
00413 cpl_free(aPixels);
00414 }
00415
00416