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 <string.h>
00037 #include <math.h>
00038 #include <assert.h>
00039 #include <cpl.h>
00040
00041 #include "irplib_utils.h"
00042 #include "irplib_filter.h"
00043
00044 #include "visir_inputs.h"
00045 #include "visir_utils.h"
00046 #include "visir_pfits.h"
00047 #include "visir_spc_distortion.h"
00048
00049
00050
00051
00052
00053 #define VISIR_BACKGD_START 76
00054 #define VISIR_BACKGD_STOP 172
00055
00056
00062
00063
00064
00065
00066
00067
00068
00069 static double visir_great_circle_dist(double, double, double, double);
00070 static double ra_hms2deg(int, int, double);
00071 static double dec_hms2deg(int, int, double);
00072
00073 static const char * visir_get_capa(const cpl_propertylist *);
00074 static double visir_hcycle_background(const irplib_framelist *, int, int);
00075
00076 #ifdef VISIR_MASK_HAS
00077 static cpl_boolean visir_mask_has(const cpl_mask *, cpl_binary, int);
00078 #endif
00079
00080
00083
00092
00093 double * visir_utils_get_wls(const irplib_framelist * self)
00094 {
00095
00096 const int size = irplib_framelist_get_size(self);
00097 double * wls = NULL;
00098 int i;
00099
00100
00101 skip_if (0);
00102
00103 skip_if(irplib_framelist_contains(self, VISIR_PFITS_DOUBLE_MONOC_POS,
00104 CPL_TYPE_DOUBLE, CPL_FALSE, 0.0));
00105
00106
00107 wls = cpl_malloc(size * sizeof(double));
00108
00109
00110 for (i=0; i < size; i++) {
00111 const cpl_propertylist * plist
00112 = irplib_framelist_get_propertylist_const(self, i);
00113
00114 wls[i] = visir_pfits_get_monoc_pos(plist);
00115
00116 skip_if (0);
00117 }
00118
00119 end_skip;
00120
00121 if (cpl_error_get_code()) {
00122 cpl_free(wls);
00123 wls = NULL;
00124 }
00125
00126 return wls;
00127 }
00128
00129
00139
00140 cpl_image * visir_create_disk_intimage(
00141 int nx,
00142 int ny,
00143 int x_pos,
00144 int y_pos,
00145 int radius)
00146 {
00147 cpl_image * intima;
00148 int * pintima;
00149 double dist;
00150 int i, j;
00151
00152
00153 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00154 pintima = cpl_image_get_data_int(intima);
00155
00156
00157 for (j=0;j<ny ; j++) {
00158 for (i=0;i<nx ; i++) {
00159 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00160 if (dist < radius*radius) {
00161 pintima[i+j*nx] = 1;
00162 } else {
00163 pintima[i+j*nx] = 0;
00164 }
00165 }
00166 }
00167 return intima;
00168 }
00169
00170
00181
00182 cpl_image * visir_create_ring_intimage(
00183 int nx,
00184 int ny,
00185 int x_pos,
00186 int y_pos,
00187 int radius1,
00188 int radius2)
00189 {
00190 cpl_image * intima;
00191 int * pintima;
00192 double dist;
00193 int i, j;
00194
00195
00196 intima = cpl_image_new(nx, ny, CPL_TYPE_INT);
00197 pintima = cpl_image_get_data_int(intima);
00198
00199
00200 for (j=0;j<ny ; j++) {
00201 for (i=0;i<nx ; i++) {
00202 dist = (i+1-x_pos)*(i+1-x_pos)+(j+1-y_pos)*(j+1-y_pos);
00203 if ((dist < radius2*radius2) && (dist > radius1*radius1)) {
00204 pintima[i+j*nx] = 1;
00205 } else {
00206 pintima[i+j*nx] = 0;
00207 }
00208 }
00209 }
00210 return intima;
00211 }
00212
00213
00224
00225 double visir_image_sigma_clip(const cpl_image * self, double * pstdev)
00226 {
00227 const int dimx = cpl_image_get_size_x(self);
00228 const int dimy = cpl_image_get_size_y(self);
00229 const cpl_type type = cpl_image_get_type(self);
00230
00231
00232 cpl_image * noise = cpl_image_new(dimx, dimy, type);
00233 cpl_mask * bpm = NULL;
00234 const int niterations = 5;
00235 const double sigma = 3.0;
00236 const double median_corr = 0.94;
00237 double bgnoise = -1;
00238 int i = -1;
00239
00240
00241 bug_if (0);
00242
00243 bug_if(irplib_image_filter(noise, self, 1, 1, IRPLIB_FILTER_MEDIAN
00244 | IRPLIB_FILTER_BORDER_FILTER));
00245
00246
00247 bug_if (cpl_image_subtract(noise, self));
00248
00249 for (i=0; i < niterations ; i++) {
00250
00251 cpl_stats * stats =
00252 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00253
00254 const double mean = cpl_stats_get_mean(stats);
00255 const double stdev = cpl_stats_get_stdev(stats);
00256
00257
00258 const double low_thresh = mean - sigma * stdev;
00259 const double high_thresh = mean + sigma * stdev;
00260
00261
00262 cpl_stats_delete(stats);
00263
00264
00265 skip_if (0);
00266
00267
00268 bpm = cpl_mask_threshold_image_create(noise, low_thresh, high_thresh);
00269
00270 bug_if (0);
00271
00272 bug_if (cpl_mask_not(bpm));
00273
00274 bug_if (cpl_image_reject_from_mask(noise, bpm));
00275
00276 cpl_mask_delete(bpm);
00277 bpm = NULL;
00278
00279 }
00280
00281 if (pstdev != NULL) {
00282
00283
00284 cpl_stats * stats =
00285 cpl_stats_new_from_image(noise, CPL_STATS_MEAN | CPL_STATS_STDEV);
00286
00287
00288 bgnoise = cpl_stats_get_stdev(stats);
00289 *pstdev = cpl_image_get_median(self) - cpl_stats_get_mean(stats);
00290
00291 cpl_stats_delete(stats);
00292 } else {
00293
00294 bgnoise = cpl_image_get_stdev(noise);
00295 }
00296
00297 bug_if(0);
00298
00299 bgnoise /= median_corr;
00300
00301 end_skip;
00302
00303 if (cpl_error_get_code())
00304 cpl_msg_error(cpl_func, "Computation of background noise using sigma=%g"
00305 " failed in iteration %d of %d", sigma, i+1, niterations);
00306
00307 cpl_mask_delete(bpm);
00308 cpl_image_delete(noise);
00309
00310 return bgnoise;
00311 }
00312
00313
00323
00324 double visir_img_phot_sigma_clip(const cpl_image * self)
00325 {
00326
00327 const double noise = visir_image_sigma_clip(self, NULL);
00328
00329 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), noise);
00330
00331 return noise;
00332
00333 }
00334
00335
00353
00354 int visir_star_find(const cpl_vector * v_ra, const cpl_vector * v_dec,
00355 double ra, double dec, double maxdist, double * pdist)
00356 {
00357 const int nra = cpl_vector_get_size(v_ra);
00358 const int ndec = cpl_vector_get_size(v_dec);
00359 double dmin = 0.0;
00360 int minind = 0;
00361 int i;
00362
00363
00364
00365 cpl_ensure(nra > 0, cpl_error_get_code(), -2);
00366 cpl_ensure(ndec > 0, cpl_error_get_code(), -3);
00367
00368
00369
00370
00371 cpl_ensure(nra == ndec, CPL_ERROR_INCOMPATIBLE_INPUT, -4);
00372
00373 cpl_ensure(maxdist >= 0, CPL_ERROR_ILLEGAL_INPUT, -5);
00374
00375
00376 for (i=0 ; i < nra ; i++) {
00377 const double rai = cpl_vector_get(v_ra, i);
00378 const double deci = cpl_vector_get(v_dec, i);
00379 const double gdist = visir_great_circle_dist(rai, deci, ra, dec);
00380
00381 cpl_msg_debug(cpl_func, "DISTANCE (RAi,DECi)=(%g,%g) <=> "
00382 "(RA,DEC)=(%g,%g): %g", rai, deci, ra, dec, gdist);
00383
00384 if (i == 0 || gdist < dmin) {
00385 minind = i;
00386 dmin = gdist;
00387 }
00388 }
00389
00390 if (pdist != NULL) *pdist = dmin;
00391
00392
00393 if (dmin > maxdist) {
00394 cpl_msg_error(cpl_func, "Nearest standard star (%d of %d) at (RA,DEC)="
00395 "(%g,%g) is too distant from (RA,DEC)=(%g, %g): %g > %g",
00396 1+minind, nra, cpl_vector_get(v_ra, minind),
00397 cpl_vector_get(v_dec, minind), ra, dec, dmin, maxdist);
00398 cpl_ensure(0, CPL_ERROR_DATA_NOT_FOUND, -1);
00399 }
00400
00401 return minind;
00402 }
00403
00404
00423
00424 cpl_error_code visir_star_convert(const char * line, int ra_hh, int ra_mm,
00425 double ra_ss, char isign, int dec_hh,
00426 int dec_mm, double dec_ss,
00427 const double * jys, int njys,
00428 double * pra, double * pdec)
00429 {
00430
00431 double sign;
00432 int i;
00433
00434 assert( line );
00435 assert( pra );
00436 assert( pdec );
00437 assert( jys );
00438 assert( njys > 0 );
00439
00440
00441 if (isign == '+')
00442 sign = 1.0;
00443 else if (isign == '-')
00444 sign = -1.0;
00445 else {
00446 cpl_msg_error(cpl_func, "Line has illegal declination-sign character "
00447 "(%c): %s", isign, line);
00448 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00449 }
00450
00451 if (ra_hh < 0) {
00452 cpl_msg_error(cpl_func, "Line has negative RA hh (%d): %s",
00453 ra_hh, line);
00454 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00455 }
00456 if (ra_mm < 0) {
00457 cpl_msg_error(cpl_func, "Line has negative RA mm (%d): %s",
00458 ra_hh, line);
00459 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00460 }
00461 if (ra_mm >= 60) {
00462 cpl_msg_error(cpl_func, "Line has too large RA mm (%d): %s ",
00463 ra_mm, line);
00464 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00465 }
00466 if (ra_ss < 0) {
00467 cpl_msg_error(cpl_func, "Line has negative RA ss (%g): %s",
00468 ra_ss, line);
00469 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00470 }
00471 if (ra_ss >= 60) {
00472 cpl_msg_error(cpl_func, "Line has too large RA ss (%g): %s ",
00473 ra_ss, line);
00474 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00475 }
00476
00477 if (dec_hh < 0) {
00478 cpl_msg_error(cpl_func, "Line has negative DEC hh (%d): %s",
00479 dec_hh, line);
00480 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00481 }
00482 if (dec_mm < 0) {
00483 cpl_msg_error(cpl_func, "Line has negative DEC mm (%d): %s",
00484 dec_hh, line);
00485 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00486 }
00487 if (dec_mm >= 60) {
00488 cpl_msg_error(cpl_func, "Line has too large DEC mm (%d): %s ",
00489 dec_mm, line);
00490 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00491 }
00492 if (dec_ss < 0) {
00493 cpl_msg_error(cpl_func, "Line has negative DEC ss (%g): %s",
00494 dec_ss, line);
00495 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00496 }
00497 if (dec_ss >= 60) {
00498 cpl_msg_error(cpl_func, "Line has too large DEC ss (%g): %s ",
00499 dec_ss, line);
00500 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00501 }
00502
00503 *pra = ra_hms2deg(ra_hh, ra_mm, ra_ss);
00504 if (*pra >= 360.0) {
00505 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00506 *pra, line);
00507 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00508 }
00509
00510 *pdec = sign * dec_hms2deg(dec_hh, dec_mm, dec_ss);
00511 if (*pdec > 90.0) {
00512 cpl_msg_error(cpl_func, "Line has too large RA (%g): %s ",
00513 *pdec, line);
00514 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00515 }
00516 if (*pdec < -90.0) {
00517 cpl_msg_error(cpl_func, "Line has too small RA (%g): %s ",
00518 *pdec, line);
00519 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00520 }
00521
00522 for (i=0; i < njys; i++) if (jys[i] <= 0.0) {
00523 cpl_msg_error(cpl_func,"Line has non-positive Jy value (%g) at %d: %s ",
00524 jys[i], i+1, line);
00525 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00526 }
00527
00528 return CPL_ERROR_NONE;
00529
00530 }
00531
00532
00545
00546 cpl_table * visir_table_new_xypos(const cpl_imagelist * images,
00547 const char * label)
00548 {
00549 cpl_errorstate cleanstate = cpl_errorstate_get();
00550 const int nsize = cpl_imagelist_get_size(images);
00551 double psigmas[] = {5, 2, 1, 0.5};
00552 cpl_vector * sigmas = NULL;
00553 cpl_table * self = NULL;
00554 const int nsigmas = sizeof(psigmas)/sizeof(double);
00555 int isigma;
00556 int isflux = 0;
00557 int nfail, i;
00558
00559 cpl_ensure(nsize > 0, cpl_error_get_code(), NULL);
00560 cpl_ensure(label, CPL_ERROR_NULL_INPUT, NULL);
00561 cpl_ensure(!strcmp(label, "FLUX") || !strcmp(label, "FWHM"),
00562 CPL_ERROR_UNSUPPORTED_MODE, NULL);
00563
00564 self = cpl_table_new(nsize);
00565
00566 skip_if (cpl_table_new_column(self, "X_POS", CPL_TYPE_DOUBLE));
00567 skip_if (cpl_table_new_column(self, "Y_POS", CPL_TYPE_DOUBLE));
00568
00569 if (!strcmp(label,"FLUX")) {
00570 isflux = 1;
00571 skip_if (cpl_table_new_column(self, label, CPL_TYPE_DOUBLE));
00572 } else {
00573 skip_if (cpl_table_new_column(self, "X_FWHM", CPL_TYPE_DOUBLE));
00574 skip_if (cpl_table_new_column(self, "Y_FWHM", CPL_TYPE_DOUBLE));
00575 }
00576
00577 sigmas = cpl_vector_wrap(4, psigmas);
00578 skip_if (sigmas == NULL);
00579
00580 cpl_msg_info(cpl_func, "Detecting apertures using %d sigma-levels "
00581 "ranging from %g down to %g", nsigmas, psigmas[0],
00582 psigmas[nsigmas-1]);
00583
00584
00585 nfail = 0;
00586 for (i=0 ; i < nsize ; i++) {
00587 const cpl_image * image = cpl_imagelist_get_const(images, i);
00588 cpl_apertures * apert;
00589
00590 double posx = -1;
00591 double posy = -1;
00592 double fwhmx = -1;
00593 double fwhmy = -1;
00594 double flux = -1;
00595 int iflux;
00596
00597 skip_if (0);
00598
00599
00600 apert = cpl_apertures_extract(image, sigmas, &isigma);
00601
00602 if (apert != NULL && cpl_error_get_code()) {
00603
00604 cpl_msg_error(cpl_func, "cpl_apertures_extract() returned non-NULL "
00605 "while setting the CPL error-state to '%s' at '%s'",
00606 cpl_error_get_message(), cpl_error_get_where());
00607 cpl_msg_debug(cpl_func, "Deleting the spurious aperture list at %p:",
00608 (void*)apert);
00609 if (cpl_msg_get_level() <= CPL_MSG_DEBUG)
00610 cpl_apertures_dump(apert, stdout);
00611 cpl_apertures_delete(apert);
00612 apert = NULL;
00613 }
00614
00615 if (apert != NULL &&
00616 !irplib_apertures_find_max_flux(apert, &iflux, 1) &&
00617 cpl_apertures_get_flux(apert, iflux) > 0) {
00618
00619 posx = cpl_apertures_get_centroid_x(apert, iflux);
00620 posy = cpl_apertures_get_centroid_y(apert, iflux);
00621 flux = cpl_apertures_get_flux(apert, iflux);
00622 if (!isflux)
00623 cpl_image_get_fwhm(image, (int)posx, (int)posy, &fwhmx, &fwhmy);
00624
00625 cpl_msg_info(cpl_func, "Detected an aperture with flux=%g at "
00626 "sigma=%g, at position: %g %g", flux,
00627 psigmas[isigma], posx, posy);
00628
00629 }
00630
00631 if (cpl_error_get_code()) {
00632 visir_error_reset("Aperture detection in image %d of %d failed",
00633 i+1, nsize);
00634 nfail++;
00635 } else if (flux <= 0) {
00636 cpl_msg_warning(cpl_func, "Ignoring %d-pixel aperture %d (out of %d) "
00637 "in file %d of %d with non-positive flux: %g",
00638 cpl_apertures_get_npix(apert, iflux), iflux,
00639 cpl_apertures_get_size(apert), i+1, nsize, flux);
00640 nfail++;
00641 }
00642
00643 cpl_apertures_delete(apert);
00644 apert = NULL;
00645
00646 skip_if (cpl_table_set_double(self, "X_POS", i, posx));
00647 skip_if (cpl_table_set_double(self, "Y_POS", i, posy));
00648
00649 if (isflux)
00650 skip_if (cpl_table_set_double(self, "FLUX", i, flux));
00651 else {
00652 skip_if (cpl_table_set_double(self, "X_FWHM", i, fwhmx));
00653 skip_if (cpl_table_set_double(self, "Y_FWHM", i, fwhmy));
00654 }
00655
00656 }
00657
00658
00659 if (nfail == nsize) {
00660 cpl_msg_error(cpl_func, "Aperture detection failed in all %d images",
00661 nsize);
00662 visir_error_set(CPL_ERROR_DATA_NOT_FOUND);
00663 skip_if(1);
00664 }
00665
00666 end_skip;
00667
00668 cpl_vector_unwrap(sigmas);
00669
00670 if (self && cpl_error_get_code()) {
00671 cpl_table_delete(self);
00672 self = NULL;
00673 }
00674
00675 return self;
00676 }
00677
00678
00685
00686 int visir_vector_minpos(const cpl_vector * v)
00687 {
00688 const double * x = cpl_vector_get_data_const(v);
00689 const int n = cpl_vector_get_size(v);
00690 int minpos = 0;
00691 int i;
00692
00693 cpl_ensure(x, CPL_ERROR_NULL_INPUT, -1);
00694
00695 for (i = 1; i < n; i++) if (x[i] < x[minpos]) minpos = i;
00696
00697 return minpos;
00698 }
00699
00700
00715
00716 cpl_error_code visir_bivector_load(cpl_bivector * self, FILE * stream)
00717 {
00718 cpl_vector * v1;
00719 cpl_vector * v2;
00720 int np = 0;
00721 int xsize, ysize;
00722 char line[1024];
00723
00724 cpl_ensure_code(self, CPL_ERROR_NULL_INPUT);
00725 cpl_ensure_code(stream, CPL_ERROR_NULL_INPUT);
00726
00727
00728 v1 = cpl_bivector_get_x(self);
00729 v2 = cpl_bivector_get_y(self);
00730
00731 xsize = cpl_vector_get_size(v1);
00732 ysize = cpl_vector_get_size(v2);
00733
00734 while (fgets(line, 1024, stream) != NULL) {
00735 double x, y;
00736 if (line[0] != '#' && sscanf(line, "%lg %lg", &x, &y) == 2) {
00737
00738
00739
00740
00741 if (np == xsize) {
00742 xsize *= 2;
00743 cpl_vector_set_size(v1, xsize);
00744 }
00745 if (np == ysize) {
00746 ysize *= 2;
00747 cpl_vector_set_size(v2, ysize);
00748 }
00749 cpl_vector_set(v1, np, x);
00750 cpl_vector_set(v2, np, y);
00751 np++;
00752 }
00753 }
00754
00755
00756 cpl_ensure_code(!ferror(stream), CPL_ERROR_FILE_IO);
00757
00758
00759 if (np == 0 || cpl_vector_set_size(v1, np) || cpl_vector_set_size(v2, np)) {
00760 cpl_ensure_code(0, CPL_ERROR_BAD_FILE_FORMAT);
00761 }
00762
00763 return CPL_ERROR_NONE;
00764
00765 }
00766
00767
00780
00781 double visir_star_dist_min(const double * pras, const double * pdecs, int nloc,
00782 int * piloc1, int * piloc2)
00783 {
00784
00785 int i, j;
00786 double dmin = 180;
00787
00788
00789 assert( pras != NULL);
00790 assert( pdecs != NULL);
00791 assert( piloc1 != NULL);
00792 assert( piloc2 != NULL);
00793 assert( nloc > 0 );
00794
00795 for (j = 0; j < nloc; j++) {
00796 for (i = 0; i < j; i++) {
00797 const double dist = visir_great_circle_dist(pras[i], pdecs[i],
00798 pras[j], pdecs[j]);
00799 if (dist < dmin) {
00800 dmin = dist;
00801 *piloc1 = i;
00802 *piloc2 = j;
00803 }
00804 if (dist < VISIR_STAR_MAX_RADIUS)
00805 cpl_msg_warning(cpl_func,"The two stars (%d,%d) have a distance"
00806 ": %g < %g", i, j, dist, VISIR_STAR_MAX_RADIUS);
00807 }
00808 }
00809
00810 return dmin;
00811 }
00812
00813
00814
00828
00829 const char ** visir_framelist_set_tag(irplib_framelist * self,
00830 char * (*pftag)(const cpl_frame *,
00831 const cpl_propertylist *,
00832 int),
00833 int *pntags)
00834 {
00835
00836
00837
00838 const char ** taglist = NULL;
00839 int iframe, size;
00840
00841 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00842 cpl_ensure(self != NULL, CPL_ERROR_NULL_INPUT, NULL);
00843 cpl_ensure(pftag != NULL, CPL_ERROR_NULL_INPUT, NULL);
00844 cpl_ensure(pntags != NULL, CPL_ERROR_NULL_INPUT, NULL);
00845
00846 size = irplib_framelist_get_size(self);
00847
00848 cpl_ensure(size > 0, CPL_ERROR_DATA_NOT_FOUND, NULL);
00849
00850 *pntags = 0;
00851
00852 for (iframe = 0; iframe < size ; iframe++) {
00853 cpl_frame * frame = irplib_framelist_get(self, iframe);
00854 const cpl_propertylist * plist
00855 = irplib_framelist_get_propertylist_const(self, iframe);
00856 char * tag;
00857 const char * newtag;
00858 int i;
00859
00860
00861
00862 cpl_ensure(frame != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00863 cpl_ensure(plist != NULL, CPL_ERROR_ILLEGAL_INPUT, NULL);
00864
00865 tag = (*pftag)(frame, plist, iframe);
00866
00867 cpl_ensure(tag != NULL, cpl_error_get_code(), NULL);
00868
00869
00870
00871 (void)cpl_frame_set_tag(frame, tag);
00872 cpl_free(tag);
00873
00874 newtag = cpl_frame_get_tag(frame);
00875
00876 cpl_ensure(!cpl_error_get_code(), cpl_error_get_code(), NULL);
00877
00878
00879 for (i=0; i < *pntags; i++)
00880 if (strcmp(newtag, taglist[i]) == 0) break;
00881
00882 if (i == *pntags) {
00883
00884
00885 (*pntags)++;
00886 taglist = (const char **)cpl_realloc(taglist, *pntags *
00887 sizeof(const char *));
00888 taglist[i] = newtag;
00889 }
00890
00891 }
00892
00893 return taglist;
00894
00895 }
00896
00897
00907
00908 cpl_error_code visir_qc_append_background(cpl_propertylist * self,
00909 const irplib_framelist * rawframes,
00910 int icol1, int icol2)
00911 {
00912
00913
00914 const double bg_mean = visir_hcycle_background(rawframes, icol1, icol2);
00915
00916 skip_if (0);
00917
00918 bug_if (cpl_propertylist_append_double(self, "ESO QC BACKGD MEAN",
00919 bg_mean));
00920
00921 end_skip;
00922
00923 return cpl_error_get_code();
00924
00925 }
00926
00927
00928
00937
00938 cpl_error_code visir_qc_append_capa(cpl_propertylist * self,
00939 const irplib_framelist * rawframes)
00940 {
00941
00942 cpl_errorstate cleanstate = cpl_errorstate_get();
00943 const cpl_propertylist * plist
00944 = irplib_framelist_get_propertylist_const(rawframes, 0);
00945 const char * capa;
00946
00947
00948 bug_if (0);
00949
00950 capa = visir_get_capa(plist);
00951
00952 if (cpl_error_get_code()) {
00953 visir_error_reset("Could not determine capa");
00954 } else {
00955 bug_if (cpl_propertylist_append_string(self, "ESO QC CAPA", capa));
00956 }
00957
00958 end_skip;
00959
00960 return cpl_error_get_code();
00961
00962 }
00963
00964
00972
00973 cpl_error_code visir_qc_append_filter(cpl_propertylist * self,
00974 const irplib_framelist * rawframes)
00975 {
00976
00977 const cpl_propertylist * plist
00978 = irplib_framelist_get_propertylist_const(rawframes, 0);
00979 const char * value = visir_pfits_get_filter(plist);
00980
00981
00982 skip_if (0);
00983
00984 bug_if (cpl_propertylist_append_string(self, "ESO QC FILTER", value));
00985
00986 end_skip;
00987
00988 return cpl_error_get_code();
00989
00990 }
00991
00992
01000
01001 cpl_error_code visir_qc_append_exptime(cpl_propertylist * self,
01002 const irplib_framelist * rawframes)
01003 {
01004
01005 const cpl_propertylist * plist
01006 = irplib_framelist_get_propertylist_const(rawframes, 0);
01007
01008
01009
01010 const double dit = visir_pfits_get_dit(plist);
01011
01012 const int ndit = visir_pfits_get_ndit(plist);
01013
01014 const int nnod = irplib_framelist_get_size(rawframes);
01015
01016 const int ncycles = visir_pfits_get_chop_ncycles(plist);
01017
01018
01019 const double value = 2 * dit * ndit * nnod * ncycles;
01020
01021
01022 skip_if (0);
01023
01024 if (value <= 0) {
01025 cpl_msg_error(cpl_func, "Illegal exposure time "
01026 "(dit=%g:ndit=%d:ncycles=%d:nnod=%d): %g",
01027 dit, ndit, ncycles, nnod, value);
01028 skip_if(1);
01029 }
01030
01031 bug_if (cpl_propertylist_append_double(self, "ESO QC EXPTIME", value));
01032
01033 end_skip;
01034
01035 return cpl_error_get_code();
01036
01037 }
01038
01041
01052
01053 static double visir_great_circle_dist(double ra1, double dec1,
01054 double ra2, double dec2)
01055 {
01056
01057
01058 const double dra = sin( CPL_MATH_RAD_DEG * (ra2 - ra1 )/2.0 );
01059 const double ddec = sin( CPL_MATH_RAD_DEG * (dec2 - dec1)/2.0 );
01060
01061 dec1 *= CPL_MATH_RAD_DEG;
01062 dec2 *= CPL_MATH_RAD_DEG;
01063
01064 return 2.0 * asin(sqrt( ddec*ddec + cos(dec1)*cos(dec2)*dra*dra))
01065 * CPL_MATH_DEG_RAD;
01066
01067 }
01068
01069
01082
01083 static double ra_hms2deg(int hh, int mm, double ss)
01084 {
01085 return 15.0 * dec_hms2deg(hh, mm, ss);
01086 }
01087
01088
01100
01101 static double dec_hms2deg(int dd, int mm, double ss)
01102 {
01103 return ((double)ss/60.0 + (double)mm)/60.0 + dd;
01104 }
01105
01106
01119
01120 static double visir_hcycle_background(const irplib_framelist * rawframes,
01121 int icol1, int icol2)
01122 {
01123 cpl_imagelist * iset = NULL;
01124
01125 const int nfiles = irplib_framelist_get_size(rawframes);
01126 double bgsum = 0;
01127 double bgmean = -1;
01128 int nsum = 0;
01129 int i, j;
01130
01131
01132 skip_if (nfiles < 1);
01133
01134 if (icol1 == 0) icol1 = VISIR_BACKGD_START;
01135 if (icol2 == 0) icol2 = VISIR_BACKGD_STOP;
01136
01137 cpl_msg_info(cpl_func, "Computing Half-cycle background level from column %d "
01138 "through %d", icol1, icol2);
01139
01140
01141 for (i=0; i < nfiles; i++) {
01142
01143 iset = visir_load_hcycle(rawframes, i);
01144
01145 skip_if (0);
01146
01147 for (j = 0; j < cpl_imagelist_get_size(iset) ; j++) {
01148 const double median =
01149 cpl_image_get_median_window(cpl_imagelist_get(iset, j),
01150 VISIR_BACKGD_START, icol1,
01151 VISIR_BACKGD_STOP, icol2);
01152
01153 skip_if (0);
01154
01155 if (median != median) {
01156 const cpl_frame * frame = irplib_framelist_get_const(rawframes,
01157 i);
01158
01159 cpl_msg_error(cpl_func, "Image window (%d, %d, %d, %d) "
01160 "(image %d of %d) in %s (frame %d of %d) "
01161 "has NaN median",
01162 VISIR_BACKGD_START, icol1,
01163 VISIR_BACKGD_STOP, icol2,
01164 j+1, cpl_imagelist_get_size(iset),
01165 cpl_frame_get_filename(frame), i+1, nfiles);
01166 visir_error_set(CPL_ERROR_BAD_FILE_FORMAT);
01167 skip_if(1);
01168 }
01169 bgsum += median;
01170 }
01171 nsum += j;
01172 cpl_imagelist_delete(iset);
01173 iset = NULL;
01174 }
01175
01176
01177 skip_if (nsum < 1);
01178
01179 bgmean = bgsum / nsum;
01180
01181 end_skip;
01182
01183 cpl_imagelist_delete(iset);
01184
01185
01186 return bgmean - VISIR_HCYCLE_OFFSET;
01187 }
01188
01189
01195
01196 static const char * visir_get_capa(const cpl_propertylist * plist)
01197 {
01198 const char * capa = "Pb with Capa";
01199 const char * sval;
01200 double mean;
01201
01202
01203 skip_if (0);
01204
01205
01206
01207 sval = visir_pfits_get_insmode(plist);
01208 skip_if (0);
01209
01210
01211 if (!strcmp(sval, "IMG")) {
01212
01213 mean = visir_pfits_get_volt1dcta9(plist);
01214 mean += visir_pfits_get_volt1dctb9(plist);
01215 } else if (!strcmp(sval, "SPC") || !strcmp(sval, "SPCIMG")) {
01216
01217 mean = visir_pfits_get_volt2dcta9(plist);
01218 mean += visir_pfits_get_volt2dctb9(plist);
01219 } else
01220 skip_if (1);
01221
01222 skip_if (0);
01223
01224 mean *= 0.5;
01225
01226
01227 if (mean < 1.0) {
01228 capa = "Large Capa";
01229 } else if (mean > 4.5) {
01230 capa = "Small Capa";
01231 }
01232
01233 end_skip;
01234
01235 return capa;
01236 }
01237
01238 #ifdef VISIR_MASK_HAS
01239
01259
01260 static cpl_boolean visir_mask_has(const cpl_mask * self, cpl_binary value,
01261 int ngood)
01262 {
01263 const cpl_binary * pself = cpl_mask_get_data_const(self);
01264 int size = cpl_mask_get_size_x(self)
01265 * cpl_mask_get_size_y(self);
01266 int i;
01267
01268 cpl_ensure(self, CPL_ERROR_NULL_INPUT, CPL_FALSE);
01269 cpl_ensure(ngood >= 0, CPL_ERROR_ILLEGAL_INPUT, CPL_FALSE);
01270 cpl_ensure(ngood <= size, CPL_ERROR_ACCESS_OUT_OF_RANGE, CPL_FALSE);
01271 cpl_ensure(value == CPL_BINARY_0 || value == CPL_BINARY_1,
01272 CPL_ERROR_INCOMPATIBLE_INPUT, CPL_FALSE);
01273
01274 for (i = 0; i < ngood; i++) {
01275
01276 const cpl_binary * ppos = memchr(pself, value, (size_t)size);
01277 if (ppos == NULL) break;
01278
01279 size -= 1 + (int)(ppos - pself);
01280 pself = 1 + ppos;
01281 }
01282
01283 return i == ngood ? CPL_TRUE : CPL_FALSE;
01284 }
01285 #endif