00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifdef HAVE_CONFIG_H
00029 #include <config.h>
00030 #endif
00031
00032
00033
00034
00035
00036 #include <cpl.h>
00037
00038
00039 #ifndef CPL_SIZE_FORMAT
00040 #define CPL_SIZE_FORMAT "d"
00041 #define cpl_size int
00042 #endif
00043
00044
00045 #include "visir_utils.h"
00046
00047 #include "irplib_utils.h"
00048
00049 #include "visir_inputs.h"
00050 #include "visir_pfits.h"
00051 #include "visir_spc_distortion.h"
00052
00053 #include <string.h>
00054 #include <math.h>
00055 #include <assert.h>
00056
00057
00058
00059
00060
00061 #define VISIR_BACKGD_START 76
00062 #define VISIR_BACKGD_STOP 172
00063
00064
00070
00071
00072
00073
00074
00075
00076
00077 static double visir_great_circle_dist(double, double, double, double);
00078 static double ra_hms2deg(int, int, double);
00079 static double dec_hms2deg(int, int, double);
00080
00081 static const char * visir_get_capa(const cpl_propertylist *);
00082 static double visir_hcycle_background(const irplib_framelist *, int, int);
00083
00084 #ifdef VISIR_MASK_HAS
00085 static cpl_boolean visir_mask_has(const cpl_mask *, cpl_binary, int);
00086 #endif
00087
00088
00091
00100
00101 double * visir_utils_get_wls(const irplib_framelist * self)
00102 {
00103
00104 const int size = irplib_framelist_get_size(self);
00105 double * wls = NULL;
00106 int i;
00107
00108
00109 skip_if (0);
00110
00111 skip_if(irplib_framelist_contains(self, VISIR_PFITS_DOUBLE_MONOC_POS,
00112 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00113
00114
00115 wls = cpl_malloc(size * sizeof(double));
00116
00117
00118 for (i=0; i < size; i++) {
00119 const cpl_propertylist * plist
00120 = irplib_framelist_get_propertylist_const(self, i);
00121
00122 wls[i] = visir_pfits_get_monoc_pos(plist);
00123
00124 skip_if (0);
00125 }
00126
00127 end_skip;
00128
00129 if (cpl_error_get_code()) {
00130 cpl_free(wls);
00131 wls = NULL;
00132 }
00133
00134 return wls;
00135 }
00136
00137
00147
00148 cpl_image * visir_create_disk_intimage(
00149 int nx,
00150 int ny,
00151 int x_pos,
00152 int y_pos,
00153 int radius)
00154 {
00155 cpl_image * intima;
00156 int * pintima;
00157 double dist;
00158 int i, j;
00159
00160
00161 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00162 pintima = cpl_image_get_data_int(intima);
00163
00164
00165 for (j=0;j<ny ; j++) {
00166 for (i=0;i<nx ; i++) {
00167 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00168 if (dist < radius*radius) {
00169 pintima[i+j*nx] = 1;
00170 } else {
00171 pintima[i+j*nx] = 0;
00172 }
00173 }
00174 }
00175 return intima;
00176 }
00177
00178
00189
00190 cpl_image * visir_create_ring_intimage(
00191 int nx,
00192 int ny,
00193 int x_pos,
00194 int y_pos,
00195 int radius1,
00196 int radius2)
00197 {
00198 cpl_image * intima;
00199 int * pintima;
00200 double dist;
00201 int i, j;
00202
00203
00204 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00205 pintima = cpl_image_get_data_int(intima);
00206
00207
00208 for (j=0;j<ny ; j++) {
00209 for (i=0;i<nx ; i++) {
00210 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00211 if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
00212 pintima[i+j*nx] = 1;
00213 } else {
00214 pintima[i+j*nx] = 0;
00215 }
00216 }
00217 }
00218 return intima;
00219 }
00220
00221
00232
00233 double visir_image_sigma_clip(const cpl_image * self, double * pstdev)
00234 {
00235 const int dimx = cpl_image_get_size_x(self);
00236 const int dimy = cpl_image_get_size_y(self);
00237 const cpl_type type = cpl_image_get_type(self);
00238
00239
00240 cpl_image * noise = cpl_image_new(dimx, dimy, type);
00241 cpl_mask * bpm = NULL;
00242 cpl_mask * kernel = cpl_mask_new(3, 3);
00243 const int niterations = 5;
00244 const double sigma = 3.0;
00245 const double median_corr = 0.94;
00246 double bgnoise = -1;
00247 int i = -1;
00248
00249
00250 bug_if (0);
00251
00252 bug_if(cpl_mask_not(kernel));
00253 bug_if(cpl_image_filter_mask(noise, self, kernel, CPL_FILTER_MEDIAN,
00254 CPL_BORDER_FILTER));
00255
00256
00257 bug_if (cpl_image_subtract(noise, self));
00258
00259 for (i=0; i < niterations ; i++) {
00260
00261 cpl_stats * stats =
00262 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00263
00264 const double mean = cpl_stats_get_mean(stats);
00265 const double stdev = cpl_stats_get_stdev(stats);
00266
00267
00268 const double low_thresh = mean - sigma * stdev;
00269 const double high_thresh = mean + sigma * stdev;
00270
00271
00272 cpl_stats_delete(stats);
00273
00274
00275 skip_if (0);
00276
00277
00278 bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
00279
00280 bug_if (0);
00281
00282 bug_if (cpl_mask_not(bpm));
00283
00284 bug_if (cpl_image_reject_from_mask(noise, bpm));
00285
00286 cpl_mask_delete(bpm);
00287 bpm = NULL;
00288
00289 }
00290
00291 if (pstdev != NULL) {
00292
00293
00294 cpl_stats * stats =
00295 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00296
00297
00298 bgnoise = cpl_stats_get_stdev(stats);
00299 *pstdev = cpl_image_get_median(self) - cpl_stats_get_mean(stats);
00300
00301 cpl_stats_delete(stats);
00302 } else {
00303
00304 bgnoise = cpl_image_get_stdev(noise);
00305 }
00306
00307 bug_if(0);
00308
00309 bgnoise /= median_corr;
00310
00311 end_skip;
00312
00313 if (cpl_error_get_code())
00314 cpl_msg_error(cpl_func, "Computation of background noise using sigma=%g"
00315 " failed in iteration %d of %d", sigma, i+1, niterations);
00316
00317 cpl_mask_delete(kernel);
00318 cpl_mask_delete(bpm);
00319 cpl_image_delete(noise);
00320
00321 return bgnoise;
00322 }
00323
00324
00334
00335 double visir_img_phot_sigma_clip(const cpl_image * self)
00336 {
00337
00338 const double noise = visir_image_sigma_clip(self, NULL);
00339
00340 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
00341
00342 return noise;
00343
00344 }
00345
00346
00364
00365 int visir_star_find(const cpl_vector * v_ra, const cpl_vector * v_dec,
00366 double ra, double dec, double maxdist, double * pdist)
00367 {
00368 const int nra = cpl_vector_get_size(v_ra);
00369 const int ndec = cpl_vector_get_size(v_dec);
00370 double dmin = 0.0;
00371 int minind = 0;
00372 int i;
00373
00374
00375
00376 cpl_ensure(nra > 0, cpl_error_get_code(), -2);
00377 cpl_ensure(ndec > 0, cpl_error_get_code(), -3);
00378
00379
00380
00381
00382 cpl_ensure(nra == ndec, CPL_ERROR_INCOMPATIBLE_INPUT, -4);
00383
00384 cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
00385
00386
00387 for (i=0 ; i < nra ; i++) {
00388 const double rai = cpl_vector_get(v_ra, i);
00389 const double deci = cpl_vector_get(v_dec, i);
00390 const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
00391
00392 cpl_msg_debug(cpl_func, "DISTANCE (RAi,DECi)=(%g,%g) <=> "
00393 "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
00394
00395 if (i == 0 || gdist < dmin) {
00396 minind = i;
00397 dmin = gdist;
00398 }
00399 }
00400
00401 if (pdist != NULL) *pdist = dmin;
00402
00403
00404 if (dmin > maxdist) {
00405 cpl_msg_error(cpl_func, "Nearest standard star (%d of %d) at (RA,DEC)="
00406 "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
00407 1+minind, nra, cpl_vector_get(v_ra, minind),
00408 cpl_vector_get(v_dec, minind), ra, dec, dmin, maxdist);
00409 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
00410 }
00411
00412 return minind;
00413 }
00414
00415
00434
00435 cpl_error_code visir_star_convert(const char * line, int ra_hh, int ra_mm,
00436 double ra_ss, char isign, int dec_hh,
00437 int dec_mm, double dec_ss,
00438 const double * jys, int njys,
00439 double * pra, double * pdec)
00440 {
00441
00442 double sign;
00443 int i;
00444
00445 assert( line );
00446 assert( pra );
00447 assert( pdec );
00448 assert( jys );
00449 assert( njys > 0 );
00450
00451
00452 if (isign == '+')
00453 sign = 1.0;
00454 else if (isign == '-')
00455 sign = -1.0;
00456 else {
00457 cpl_msg_error(cpl_func, "Line has illegal declination-sign character "
00458 "(%c): %s", isign, line);
00459 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00460 }
00461
00462 if (ra_hh < 0) {
00463 cpl_msg_error(cpl_func, "Line has negative RA hh (%d): %s",
00464 ra_hh, line);
00465 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00466 }
00467 if (ra_mm < 0) {
00468 cpl_msg_error(cpl_func, "Line has negative RA mm (%d): %s",
00469 ra_hh, line);
00470 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00471 }
00472 if (ra_mm >= 60) {
00473 cpl_msg_error(cpl_func, "Line has too large RA mm (%d): %s ",
00474 ra_mm, line);
00475 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00476 }
00477 if (ra_ss < 0) {
00478 cpl_msg_error(cpl_func, "Line has negative RA ss (%g): %s",
00479 ra_ss, line);
00480 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00481 }
00482 if (ra_ss >= 60) {
00483 cpl_msg_error(cpl_func, "Line has too large RA ss (%g): %s ",
00484 ra_ss, line);
00485 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00486 }
00487
00488 if (dec_hh < 0) {
00489 cpl_msg_error(cpl_func, "Line has negative DEC hh (%d): %s",
00490 dec_hh, line);
00491 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00492 }
00493 if (dec_mm < 0) {
00494 cpl_msg_error(cpl_func, "Line has negative DEC mm (%d): %s",
00495 dec_hh, line);
00496 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00497 }
00498 if (dec_mm >= 60) {
00499 cpl_msg_error(cpl_func, "Line has too large DEC mm (%d): %s ",
00500 dec_mm, line);
00501 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00502 }
00503 if (dec_ss < 0) {
00504 cpl_msg_error(cpl_func, "Line has negative DEC ss (%g): %s",
00505 dec_ss, line);
00506 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00507 }
00508 if (dec_ss >= 60) {
00509 cpl_msg_error(cpl_func, "Line has too large DEC ss (%g): %s ",
00510 dec_ss, line);
00511 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00512 }
00513
00514 *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
00515 if (*pra >= 360.0) {
00516 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00517 *pra, line);
00518 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00519 }
00520
00521 *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
00522 if (*pdec > 90.0) {
00523 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00524 *pdec, line);
00525 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00526 }
00527 if (*pdec < -90.0) {
00528 cpl_msg_error(cpl_func, "Line has too small RA (%g): %s ",
00529 *pdec, line);
00530 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00531 }
00532
00533 for (i=0; i < njys; i++) if (jys[i] <= 0.0) {
00534 cpl_msg_error(cpl_func,"Line has non-positive Jy value (%g) at %d: %s ",
00535 jys[i], i+1, line);
00536 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00537 }
00538
00539 return CPL_ERROR_NONE;
00540
00541 }
00542
00543
00556
00557 cpl_table * visir_table_new_xypos(const cpl_imagelist * images,
00558 const char * label)
00559 {
00560 cpl_errorstate cleanstate = cpl_errorstate_get();
00561 const int nsize = cpl_imagelist_get_size(images);
00562 double psigmas[] = {5, 2, 1, 0.5};
00563 cpl_vector * sigmas = NULL;
00564 cpl_table * self = NULL;
00565 const int nsigmas = sizeof(psigmas)/sizeof(double);
00566 int isflux = 0;
00567 int nfail, i;
00568
00569 cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
00570 cpl_ensure(label, CPL_ERROR_NULL_INPUT, NULL);
00571 cpl_ensure(!strcmp(label, "FLUX") || !strcmp(label, "FWHM"),
00572 CPL_ERROR_UNSUPPORTED_MODE, NULL);
00573
00574 self = cpl_table_new(nsize);
00575
00576 skip_if (cpl_table_new_column(self, "X_POS", CPL_TYPE_DOUBLE));
00577 skip_if (cpl_table_new_column(self, "Y_POS", CPL_TYPE_DOUBLE));
00578
00579 if (!strcmp(label,"FLUX")) {
00580 isflux = 1;
00581 skip_if (cpl_table_new_column(self, label, CPL_TYPE_DOUBLE));
00582 } else {
00583 skip_if (cpl_table_new_column(self, "X_FWHM", CPL_TYPE_DOUBLE));
00584 skip_if (cpl_table_new_column(self, "Y_FWHM", CPL_TYPE_DOUBLE));
00585 }
00586
00587 sigmas = cpl_vector_wrap(4, psigmas);
00588 skip_if (sigmas == NULL);
00589
00590 cpl_msg_info(cpl_func, "Detecting apertures using %d sigma-levels "
00591 "ranging from %g down to %g", nsigmas, psigmas[0],
00592 psigmas[nsigmas-1]);
00593
00594
00595 nfail = 0;
00596 for (i=0 ; i < nsize ; i++) {
00597 const cpl_image * image = cpl_imagelist_get_const(images, i);
00598 cpl_apertures * apert;
00599 cpl_size isigma;
00600
00601
00602 double posx = -1;
00603 double posy = -1;
00604 double fwhmx = -1;
00605 double fwhmy = -1;
00606 double flux = -1;
00607 int iflux;
00608
00609 skip_if (0);
00610
00611
00612 apert = cpl_apertures_extract(image, sigmas, &isigma);
00613
00614 if (apert != NULL && cpl_error_get_code()) {
00615
00616 cpl_msg_error(cpl_func, "cpl_apertures_extract() returned non-NULL "
00617 "while setting the CPL error-state to '%s' at '%s'",
00618 cpl_error_get_message(), cpl_error_get_where());
00619 cpl_msg_debug(cpl_func, "Deleting the spurious aperture list at %p:",
00620 (void*)apert);
00621 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
00622 cpl_apertures_dump(apert, stdout);
00623 cpl_apertures_delete(apert);
00624 apert = NULL;
00625 }
00626
00627 if (apert != NULL &&
00628 !irplib_apertures_find_max_flux(apert, &iflux, 1) &&
00629 cpl_apertures_get_flux(apert, iflux) > 0) {
00630
00631 posx = cpl_apertures_get_centroid_x(apert, iflux);
00632 posy = cpl_apertures_get_centroid_y(apert, iflux);
00633 flux = cpl_apertures_get_flux(apert, iflux);
00634 if (!isflux)
00635 cpl_image_get_fwhm(image, (int)posx, (int)posy, &fwhmx, &fwhmy);
00636
00637 cpl_msg_info(cpl_func, "Detected an aperture with flux=%g at "
00638 "sigma=%g, at position: %g %g", flux,
00639 psigmas[isigma], posx, posy);
00640
00641 }
00642
00643 if (apert == NULL || cpl_error_get_code()) {
00644 visir_error_reset("Aperture detection in image %d of %d failed",
00645 i+1, nsize);
00646 nfail++;
00647 } else if (flux <= 0) {
00648 cpl_msg_warning(cpl_func, "Ignoring %d-pixel aperture %d (out of "
00649 "%d) in file %d of %d with non-positive flux: %g",
00650 (int)cpl_apertures_get_npix(apert, iflux), iflux,
00651 (int)cpl_apertures_get_size(apert), i+1, nsize,
00652 flux);
00653 nfail++;
00654 }
00655
00656 cpl_apertures_delete(apert);
00657 apert = NULL;
00658
00659 skip_if (cpl_table_set_double(self, "X_POS", i, posx));
00660 skip_if (cpl_table_set_double(self, "Y_POS", i, posy));
00661
00662 if (isflux)
00663 skip_if (cpl_table_set_double(self, "FLUX", i, flux));
00664 else {
00665 skip_if (cpl_table_set_double(self, "X_FWHM", i, fwhmx));
00666 skip_if (cpl_table_set_double(self, "Y_FWHM", i, fwhmy));
00667 }
00668
00669 }
00670
00671
00672 if (nfail == nsize) {
00673 cpl_msg_error(cpl_func, "Aperture detection failed in all %d images",
00674 nsize);
00675 visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
00676 skip_if(1);
00677 }
00678
00679 end_skip;
00680
00681 cpl_vector_unwrap(sigmas);
00682
00683 if (self && cpl_error_get_code()) {
00684 cpl_table_delete(self);
00685 self = NULL;
00686 }
00687
00688 return self;
00689 }
00690
00691
00698
00699 int visir_vector_minpos(const cpl_vector * v)
00700 {
00701 const double * x = cpl_vector_get_data_const(v);
00702 const int n = cpl_vector_get_size(v);
00703 int minpos = 0;
00704 int i;
00705
00706 cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
00707
00708 for (i = 1; i < n; i++) if (x[i] < x[minpos]) minpos = i;
00709
00710 return minpos;
00711 }
00712
00713
00728
00729 cpl_error_code visir_bivector_load(cpl_bivector * self, FILE * stream)
00730 {
00731 cpl_vector * v1;
00732 cpl_vector * v2;
00733 int np = 0;
00734 int xsize, ysize;
00735 char line[1024];
00736
00737 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00738 cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
00739
00740
00741 v1 = cpl_bivector_get_x(self);
00742 v2 = cpl_bivector_get_y(self);
00743
00744 xsize = cpl_vector_get_size(v1);
00745 ysize = cpl_vector_get_size(v2);
00746
00747 while (fgets(line, 1024, stream) != NULL) {
00748 double x, y;
00749 if (line[0] != '#' && sscanf(line, "%lg %lg", &x, &y) == 2) {
00750
00751
00752
00753
00754 if (np == xsize) {
00755 xsize *= 2;
00756 cpl_vector_set_size(v1, xsize);
00757 }
00758 if (np == ysize) {
00759 ysize *= 2;
00760 cpl_vector_set_size(v2, ysize);
00761 }
00762 cpl_vector_set(v1, np, x);
00763 cpl_vector_set(v2, np, y);
00764 np++;
00765 }
00766 }
00767
00768
00769 cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
00770
00771
00772 if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
00773 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00774 }
00775
00776 return CPL_ERROR_NONE;
00777
00778 }
00779
00780
00793
00794 double visir_star_dist_min(const double * pras, const double * pdecs, int nloc,
00795 int * piloc1, int * piloc2)
00796 {
00797
00798 int i, j;
00799 double dmin = 180;
00800
00801
00802 assert( pras != NULL);
00803 assert( pdecs != NULL);
00804 assert( piloc1 != NULL);
00805 assert( piloc2 != NULL);
00806 assert( nloc > 0 );
00807
00808 for (j = 0; j < nloc; j++) {
00809 for (i = 0; i < j; i++) {
00810 const double dist = visir_great_circle_dist(pras[i], pdecs[i],
00811 pras[j], pdecs[j]);
00812 if (dist < dmin) {
00813 dmin = dist;
00814 *piloc1 = i;
00815 *piloc2 = j;
00816 }
00817 if (dist < VISIR_STAR_MAX_RADIUS)
00818 cpl_msg_warning(cpl_func,"The two stars (%d,%d) have a distance"
00819 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
00820 }
00821 }
00822
00823 return dmin;
00824 }
00825
00826
00827
00841
00842 const char ** visir_framelist_set_tag(irplib_framelist * self,
00843 char * (*pftag)(const cpl_frame *,
00844 const cpl_propertylist *,
00845 int),
00846 int *pntags)
00847 {
00848
00849
00850
00851 const char ** taglist = NULL;
00852 int iframe, size;
00853
00854 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00855 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00856 cpl_ensure(pftag != NULL, CPL_ERROR_NULL_INPUT, NULL);
00857 cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
00858
00859 size = irplib_framelist_get_size(self);
00860
00861 cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
00862
00863 *pntags = 0;
00864
00865 for (iframe = 0; iframe < size ; iframe++) {
00866 cpl_frame * frame = irplib_framelist_get(self, iframe);
00867 const cpl_propertylist * plist
00868 = irplib_framelist_get_propertylist_const(self, iframe);
00869 char * tag;
00870 const char * newtag;
00871 int i;
00872
00873
00874
00875 cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00876 cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00877
00878 tag = (*pftag)(frame, plist, iframe);
00879
00880 cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
00881
00882
00883
00884 (void)cpl_frame_set_tag(frame, tag);
00885 cpl_free(tag);
00886
00887 newtag = cpl_frame_get_tag(frame);
00888
00889 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00890
00891
00892 for (i=0; i < *pntags; i++)
00893 if (strcmp(newtag, taglist[i]) == 0) break;
00894
00895 if (i == *pntags) {
00896
00897
00898 (*pntags)++;
00899 taglist = (const char **)cpl_realloc(taglist, *pntags *
00900 sizeof(const char *));
00901 taglist[i] = newtag;
00902 }
00903
00904 }
00905
00906 return taglist;
00907
00908 }
00909
00910
00920
00921 cpl_error_code visir_qc_append_background(cpl_propertylist * self,
00922 const irplib_framelist * rawframes,
00923 int icol1, int icol2)
00924 {
00925
00926
00927 const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
00928
00929 skip_if (0);
00930
00931 bug_if (cpl_propertylist_append_double(self, "ESO QC BACKGD MEAN",
00932 bg_mean));
00933
00934 end_skip;
00935
00936 return cpl_error_get_code();
00937
00938 }
00939
00940
00941
00950
00951 cpl_error_code visir_qc_append_capa(cpl_propertylist * self,
00952 const irplib_framelist * rawframes)
00953 {
00954
00955 cpl_errorstate cleanstate = cpl_errorstate_get();
00956 const cpl_propertylist * plist
00957 = irplib_framelist_get_propertylist_const(rawframes, 0);
00958 const char * capa;
00959
00960
00961 bug_if (0);
00962
00963 capa = visir_get_capa(plist);
00964
00965 if (cpl_error_get_code()) {
00966 visir_error_reset("Could not determine capa");
00967 } else {
00968 bug_if (cpl_propertylist_append_string(self, "ESO QC CAPA", capa));
00969 }
00970
00971 end_skip;
00972
00973 return cpl_error_get_code();
00974
00975 }
00976
00977
00985
00986 cpl_error_code visir_qc_append_filter(cpl_propertylist * self,
00987 const irplib_framelist * rawframes)
00988 {
00989
00990 const cpl_propertylist * plist
00991 = irplib_framelist_get_propertylist_const(rawframes, 0);
00992 const char * value = visir_pfits_get_filter(plist);
00993
00994
00995 skip_if (0);
00996
00997 bug_if (cpl_propertylist_append_string(self, "ESO QC FILTER", value));
00998
00999 end_skip;
01000
01001 return cpl_error_get_code();
01002
01003 }
01004
01005
01013
01014 cpl_error_code visir_qc_append_exptime(cpl_propertylist * self,
01015 const irplib_framelist * rawframes)
01016 {
01017
01018 const cpl_propertylist * plist
01019 = irplib_framelist_get_propertylist_const(rawframes, 0);
01020
01021
01022
01023 const double dit = visir_pfits_get_dit(plist);
01024
01025 const int ndit = visir_pfits_get_ndit(plist);
01026
01027 const int nnod = irplib_framelist_get_size(rawframes);
01028
01029 const int ncycles = visir_pfits_get_chop_ncycles(plist);
01030
01031
01032 const double value = 2 * dit * ndit * nnod * ncycles;
01033
01034
01035 skip_if (0);
01036
01037 if (value <= 0) {
01038 cpl_msg_error(cpl_func, "Illegal exposure time "
01039 "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
01040 dit, ndit, ncycles, nnod, value);
01041 skip_if(1);
01042 }
01043
01044 bug_if (cpl_propertylist_append_double(self, "ESO QC EXPTIME", value));
01045
01046 end_skip;
01047
01048 return cpl_error_get_code();
01049
01050 }
01051
01054
01065
01066 static double visir_great_circle_dist(double ra1, double dec1,
01067 double ra2, double dec2)
01068 {
01069
01070
01071 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
01072 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
01073
01074 dec1 *= CPL_MATH_RAD_DEG;
01075 dec2 *= CPL_MATH_RAD_DEG;
01076
01077 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
01078 * CPL_MATH_DEG_RAD;
01079
01080 }
01081
01082
01095
01096 static double ra_hms2deg(int hh, int mm, double ss)
01097 {
01098 return 15.0 * dec_hms2deg(hh, mm, ss);
01099 }
01100
01101
01113
01114 static double dec_hms2deg(int dd, int mm, double ss)
01115 {
01116 return ((double)ss/60.0 + (double)mm)/60.0 + dd;
01117 }
01118
01119
01132
01133 static double visir_hcycle_background(const irplib_framelist * rawframes,
01134 int icol1, int icol2)
01135 {
01136 cpl_imagelist * iset = NULL;
01137
01138 const int nfiles = irplib_framelist_get_size(rawframes);
01139 double bgsum = 0;
01140 double bgmean = -1;
01141 int nsum = 0;
01142 int i, j;
01143
01144
01145 skip_if (nfiles < 1);
01146
01147 if (icol1 == 0) icol1 = VISIR_BACKGD_START;
01148 if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
01149
01150 cpl_msg_info(cpl_func, "Computing Half-cycle background level from column %d "
01151 "through %d", icol1, icol2);
01152
01153
01154 for (i=0; i < nfiles; i++) {
01155
01156 iset = visir_load_hcycle(rawframes, i);
01157
01158 skip_if (0);
01159
01160 for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
01161 const double median =
01162 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
01163 VISIR_BACKGD_START, icol1,
01164 VISIR_BACKGD_STOP, icol2);
01165
01166 skip_if (0);
01167
01168 if (median != median) {
01169 const cpl_frame * frame = irplib_framelist_get_const(rawframes,
01170 i);
01171
01172 cpl_msg_error(cpl_func, "Image window (%d, %d, %d, %d) "
01173 "(image %d of %d) in %s (frame %d of %d) "
01174 "has NaN median",
01175 VISIR_BACKGD_START, icol1,
01176 VISIR_BACKGD_STOP, icol2,
01177 j+1, (int)cpl_imagelist_get_size(iset),
01178 cpl_frame_get_filename(frame), i+1, nfiles);
01179 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01180 skip_if(1);
01181 }
01182 bgsum += median;
01183 }
01184 nsum += j;
01185 cpl_imagelist_delete(iset);
01186 iset = NULL;
01187 }
01188
01189
01190 skip_if (nsum < 1);
01191
01192 bgmean = bgsum / nsum;
01193
01194 end_skip;
01195
01196 cpl_imagelist_delete(iset);
01197
01198
01199 return bgmean - VISIR_HCYCLE_OFFSET;
01200 }
01201
01202
01203
01214
01215 cpl_error_code
01216 visir_get_subpixel_maxpos(const cpl_image * img, cpl_size x, cpl_size y,
01217 double * xsub, double * ysub)
01218 {
01219 int bad;
01220 const cpl_size nx = cpl_image_get_size_x(img);
01221 const cpl_size ny = cpl_image_get_size_y(img);
01222
01223 *xsub = 0;
01224 *ysub = 0;
01225 if (x - 1 > 0 && x + 1 <= nx) {
01226 double sub[] = {
01227 cpl_image_get(img, x - 1, y, &bad),
01228 cpl_image_get(img, x - 0, y, &bad),
01229 cpl_image_get(img, x + 1, y, &bad),
01230 };
01231 if (!bad)
01232 *xsub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
01233 }
01234 if (y - 1 > 0 && y + 1 <= ny) {
01235 double sub[] = {
01236 cpl_image_get(img, x, y - 1, &bad),
01237 cpl_image_get(img, x, y - 0, &bad),
01238 cpl_image_get(img, x, y + 1, &bad),
01239 };
01240 if (!bad)
01241 *ysub = 0.5 * (sub[0] - sub[2])/(sub[0] - 2*sub[1] + sub[2]);
01242 }
01243
01244 return cpl_error_get_code();
01245 }
01246
01247
01248
01259
01260 cpl_error_code
01261 visir_fftxcorrelate(const cpl_image * atemplate, const cpl_image * aimg,
01262 cpl_boolean normalize, double * xshift, double * yshift)
01263 {
01264 cpl_size Nx = cpl_image_get_size_x(aimg);
01265 cpl_size Ny = cpl_image_get_size_y(aimg);
01266 const cpl_size nsquare = abs(Nx-Ny);
01267 cpl_size Nxe = 2 * (Nx + (Ny > Nx ? nsquare : 0)) - 1;
01268 cpl_size Nye = 2 * (Ny + (Nx > Ny ? nsquare : 0)) - 1;
01269 cpl_size txshift, tyshift;
01270 double subx = 0, suby = 0;
01271 double * bzimg = cpl_calloc(Nxe * Nye, sizeof(double));
01272 double * bztemp = cpl_calloc(Nxe * Nye, sizeof(double));
01273 cpl_image * template = cpl_image_cast(atemplate, CPL_TYPE_DOUBLE);
01274 cpl_image * img = NULL;
01275 cpl_image * zimg = NULL;
01276 cpl_image * ztemp = NULL;
01277 cpl_image * fft1 = NULL;
01278 cpl_image * fft2 = NULL;
01279 cpl_image * res = NULL;
01280
01281 zimg = cpl_image_wrap(Nxe, Nye, CPL_TYPE_DOUBLE, bzimg);
01282 ztemp = cpl_image_wrap(Nxe, Nye, CPL_TYPE_DOUBLE, bztemp);
01283
01284 if (Nx > Ny)
01285 Ny += nsquare;
01286 else
01287 Nx += nsquare;
01288
01289 cpl_ensure_code(Nx == Ny, CPL_ERROR_ILLEGAL_INPUT);
01290
01291 if (cpl_image_get_type(aimg) != CPL_TYPE_DOUBLE)
01292 img = cpl_image_cast(aimg, CPL_TYPE_DOUBLE);
01293 else
01294 img = cpl_image_duplicate(aimg);
01295
01296 skip_if(img == NULL);
01297
01298 cpl_image_fill_rejected(img, 0);
01299 cpl_image_fill_rejected(template, 0);
01300
01301
01302 if (normalize) {
01303 skip_if(cpl_image_subtract_scalar(img, cpl_image_get_mean(img)));
01304 skip_if(cpl_image_divide_scalar(img, cpl_image_get_stdev(img)));
01305 skip_if(cpl_image_subtract_scalar(template, cpl_image_get_mean(template)));
01306 skip_if(cpl_image_divide_scalar(template, cpl_image_get_stdev(template)));
01307 }
01308
01309
01310 skip_if(cpl_image_copy(zimg, img, 1, 1));
01311 skip_if(cpl_image_copy(ztemp, template, Nx, Ny));
01312
01313 fft1 = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE_COMPLEX);
01314 fft2 = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE_COMPLEX);
01315 res = cpl_image_new(Nxe, Nye, CPL_TYPE_DOUBLE);
01316
01317
01318
01319
01320 skip_if(cpl_image_flip(zimg, 1));
01321 skip_if(cpl_image_flip(zimg, 3));
01322
01323 skip_if(cpl_fft_image(fft1, zimg, CPL_FFT_FORWARD));
01324 skip_if(cpl_fft_image(fft2, ztemp, CPL_FFT_FORWARD));
01325
01326
01327 skip_if(cpl_image_multiply(fft1, fft2));
01328
01329 skip_if(cpl_fft_image(res, fft1, CPL_FFT_BACKWARD));
01330
01331 skip_if(cpl_image_get_maxpos(res, &txshift, &tyshift));
01332 skip_if(visir_get_subpixel_maxpos(res, txshift, tyshift, &subx, &suby));
01333 *xshift = txshift - (Nx - 1) + subx;
01334 *xshift *= -1;
01335 *yshift = tyshift - (Ny - 1) + suby;
01336 *yshift *= -1;
01337
01338 end_skip;
01339
01340 cpl_image_delete(fft1);
01341 cpl_image_delete(fft2);
01342 cpl_image_delete(img);
01343 cpl_image_delete(template);
01344 cpl_image_delete(zimg);
01345 cpl_image_delete(ztemp);
01346 cpl_image_delete(res);
01347
01348 return cpl_error_get_code();
01349 }
01350
01351
01352
01358
01359 static const char * visir_get_capa(const cpl_propertylist * plist)
01360 {
01361 const char * capa = "Pb with Capa";
01362 const char * sval;
01363 double mean;
01364
01365
01366 skip_if (0);
01367
01368
01369
01370 sval = visir_pfits_get_insmode(plist);
01371 skip_if (0);
01372
01373
01374 if (!strcmp(sval, "IMG")) {
01375
01376 mean = visir_pfits_get_volt1dcta9(plist);
01377 mean += visir_pfits_get_volt1dctb9(plist);
01378 } else if (!strcmp(sval, "SPC") || !strcmp(sval, "SPCIMG")) {
01379
01380 mean = visir_pfits_get_volt2dcta9(plist);
01381 mean += visir_pfits_get_volt2dctb9(plist);
01382 } else
01383 skip_if (1);
01384
01385 skip_if (0);
01386
01387 mean *= 0.5;
01388
01389
01390 if (mean < 1.0) {
01391 capa = "Large Capa";
01392 } else if (mean > 4.5) {
01393 capa = "Small Capa";
01394 }
01395
01396 end_skip;
01397
01398 return capa;
01399 }
01400
01401 #ifdef VISIR_MASK_HAS
01402
01422
01423 static cpl_boolean visir_mask_has(const cpl_mask * self, cpl_binary value,
01424 int ngood)
01425 {
01426 const cpl_binary * pself = cpl_mask_get_data_const(self);
01427 int size = cpl_mask_get_size_x(self)
01428 * cpl_mask_get_size_y(self);
01429 int i;
01430
01431 cpl_ensure(self, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01432 cpl_ensure(ngood >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01433 cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
01434 cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
01435 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
01436
01437 for (i = 0; i < ngood; i++) {
01438
01439 const cpl_binary * ppos = memchr(pself, value, (size_t)size);
01440 if (ppos == NULL) break;
01441
01442 size -= 1 + (int)(ppos - pself);
01443 pself = 1 + ppos;
01444 }
01445
01446 return i == ngood ? CPL_TRUE : CPL_FALSE;
01447 }
01448 #endif