X-shooter Pipeline Reference Manual 3.8.15
xsh_utils.c
Go to the documentation of this file.
1/* *
2 * This file is part of the ESO X-shooter Pipeline *
3 * Copyright (C) 2006 European Southern Observatory *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18 * */
19
20/*
21 * $Author: amodigli $
22 * $Date: 2013-04-15 06:43:42 $
23 * $Revision: 1.238 $
24 * $Name: not supported by cvs2svn $
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*----------------------------------------------------------------------------
32 Includes
33 ----------------------------------------------------------------------------*/
34#include <assert.h>
35#include <stdarg.h>
36#include <time.h>
37#include <math.h>
38#include <stdlib.h>
39#include <fcntl.h> /* used for fileutils_copy/move */
40#include <sys/stat.h>/* used for fileutils_copy/move */
41
42#include "xsh_utils.h"
43#include <xsh_utils_wrappers.h>
44#include <xsh_dfs.h>
45#include <xsh_data_pre.h>
46#include <xsh_dump.h>
47#include <xsh_error.h>
48#include <xsh_msg.h>
49#include <xsh_parameters.h>
50#include <xsh_data_spectrum.h>
51#include <xsh_data_atmos_ext.h>
52#include <xsh_pfits.h>
53#include <xsh_pfits_qc.h>
54
55#include <cpl.h>
56#include <ctype.h>
57#include <stdbool.h>
58
59#include <gsl/gsl_rng.h>
60#include <gsl/gsl_randist.h>
61#include <gsl/gsl_vector.h>
62#include <gsl/gsl_blas.h>
63#include <gsl/gsl_multifit_nlin.h>
64#include <gsl/gsl_version.h>
65
66/*----------------------------------------------------------------------------
67 Variables
68 ----------------------------------------------------------------------------*/
70static int XshTimeStamp = FALSE ;
71
72/*----------------------------------------------------------------------------
73 Defines
74 ----------------------------------------------------------------------------*/
75#define MAXIMUM(x, y) ((x) > (y)) ? (x) : (y)
76/* Caveat: multiple evalutation of arguments */
77
78#define DEV_BLOCKSIZE 4096 /* used for fileutils_copy/move */
79#define XSH_ATM_EXT_UVB_WAV_MIN 310.
80/*---------------------------------------------------------------------------*/
88/*---------------------------------------------------------------------------*/
89
91/*
92#define CPL_TYPE double
93#define CPL_TYPE_T CPL_TYPE_DOUBLE
94#define CPL_IMAGE_GET_DATA cpl_image_get_data_double
95#define CPL_IMAGE_GET_DATA_CONST cpl_image_get_data_double_const
96#define CPL_IMAGE_GET_MEDIAN cpl_tools_get_median_double
97*/
98
99#define CPL_TYPE float
100#define CPL_TYPE_T CPL_TYPE_FLOAT
101#define CPL_IMAGE_GET_DATA cpl_image_get_data_float
102#define CPL_IMAGE_GET_DATA_CONST cpl_image_get_data_float_const
103#define CPL_IMAGE_GET_MEDIAN cpl_tools_get_median_float
104
105
106
107
108void
110{
111 time_t t;
112
113 /* Intializes random number generator */
114 srand((unsigned) time(&t));
115
116 return;
117}
118/*----------------------------------------------------------------------------*/
126/*----------------------------------------------------------------------------*/
127int
128xsh_get_random_int_window(const int v1, const int v2) {
129
130 long double a=(double)v1,b=(double)v2;
131 long double x1;
132 //srand((unsigned)time(NULL));
133
134 // x1 will be an element of [a,b]
135 x1=( (long double) rand() / RAND_MAX ) * (b-a) + a;
136
137 return (int)x1;
138}
139
140/*----------------------------------------------------------------------------*/
148/*----------------------------------------------------------------------------*/
149double
150xsh_get_random_double_window(const double v1, const double v2) {
151
152 long double a=v1,b=v2;
153 long double x1;
154
155 srand((unsigned)time(NULL));
156
157 /* x1 will be an element of [a,b] */
158 x1=((long double)rand()/RAND_MAX)*(b-a) + a;
159
160 return x1;
161}
162
163
192/*----------------------------------------------------------------------------*/
194 const cpl_imagelist * imlist,
195 double sigma_low,
196 double sigma_upp,
197 const int niter)
198
199{
200 const cpl_image * cur_ima=NULL ;
201 int ni, nx, ny ;
202 cpl_table * time_line=NULL ;
203 cpl_image * out_ima=NULL ;
204 double out_val ;
205 //int nb_val ;
206 double mean, stdev ;
207 double low_thresh, high_thresh ;
208 int i, j, k ;
209
210 /* Check inputs */
211 cpl_ensure(imlist != NULL, CPL_ERROR_NULL_INPUT, NULL);
212 cpl_ensure(cpl_imagelist_is_uniform(imlist)==0, CPL_ERROR_ILLEGAL_INPUT,
213 NULL);
214 cpl_ensure(sigma_low>1., CPL_ERROR_ILLEGAL_INPUT, NULL);
215 cpl_ensure(sigma_upp>1., CPL_ERROR_ILLEGAL_INPUT, NULL);
216 cpl_ensure(niter > 0, CPL_ERROR_NULL_INPUT, NULL);
217
218 ni = cpl_imagelist_get_size(imlist) ;
219
220 cur_ima = cpl_imagelist_get_const(imlist, 0) ;
221 nx = cpl_image_get_size_x(cur_ima) ;
222 ny = cpl_image_get_size_y(cur_ima) ;
223
224
225 /* Create the table to hold pixel points */
226 time_line = cpl_table_new(ni) ;
227
228
229 /* Switch on the data type */
230
231
232 //case CPL_TYPE_T:
233 {
234
235 CPL_TYPE * pout_ima ;
236 const CPL_TYPE * pcur_ima ;
237 int n=0;
238 int nbad=0;
239 CPL_TYPE * ptime_line ;
240
241 cpl_table_new_column(time_line,"VAL",CPL_TYPE_T);
242 cpl_table_fill_column_window(time_line,"VAL",0,ni,0);
243 if (CPL_TYPE_T == CPL_TYPE_DOUBLE) {
244 ptime_line = (CPL_TYPE*) cpl_table_get_data_double(time_line,"VAL") ;
245 } else if (CPL_TYPE_T == CPL_TYPE_FLOAT) {
246 ptime_line = (CPL_TYPE*) cpl_table_get_data_float(time_line,"VAL") ;
247 } else {
248 ptime_line = (CPL_TYPE*) cpl_table_get_data_int(time_line,"VAL") ;
249 }
250 out_ima = cpl_image_new(nx, ny, CPL_TYPE_T) ;
251 pout_ima = CPL_IMAGE_GET_DATA(out_ima) ;
252 /* Loop on the pixels */
253 for (j=0 ; j<ny ; j++) {
254 for (i=0 ; i<nx ; i++) {
255 /* Fill the vector */
256
257 for (k=0 ; k<ni ; k++) {
258 cur_ima = cpl_imagelist_get_const(imlist, k) ;
259 pcur_ima = CPL_IMAGE_GET_DATA_CONST(cur_ima) ;
260 ptime_line[k] = (CPL_TYPE)pcur_ima[i+j*nx] ;
261 }
262
263 /* do kappa-sigma clip */
264
265 for(n=0, nbad=0;(n<niter) && (nbad<ni-1);n++) {
266 /* Get the mean and stdev */
267 check(mean = cpl_table_get_column_mean(time_line,"VAL")) ;
268 check(stdev = cpl_table_get_column_stdev(time_line,"VAL")) ;
269 low_thresh = mean - sigma_low * stdev ;
270 high_thresh = mean + sigma_upp * stdev ;
271
272 /* Compute the final value */
273 out_val = 0.0 ;
274 //nb_val = 0 ;
275 for (k=0 ; k<ni ; k++) {
276 if (ptime_line[k]<=high_thresh &&
277 ptime_line[k]>=low_thresh) {
278 /* good pixel */
279 } else {
280 cpl_table_set_invalid(time_line,"VAL",k);
281 nbad++;
282 }
283 }
284 }
285 /* set out value equal to now clean mean of inputs */
286 out_val = cpl_table_get_column_mean(time_line,"VAL") ;
287 /* Set the output image pixel value */
288 pout_ima[i+j*nx] = (CPL_TYPE)out_val ;
289 }
290 }
291 //break ;
292 }
293
294 cleanup:
295 cpl_table_delete(time_line) ;
296
297
298 /* Return */
299 return out_ima ;
300}
301
302
303
304
311double
312xsh_hms2deg(const double hms)
313{
314 int hrs=0;
315 int min=0;
316 double sec=0;
317 double deg=0;
318 double rest=hms;
319 int sign=1;
320
321 if(hms<0) {
322 sign=-1;
323 rest=-hms;
324 }
325
326 hrs=(int)(rest/10000.);
327 rest=rest-(double)(hrs*10000.);
328 min=(int)(rest/100.);
329 sec=rest-(double)(min*100.);
330 deg=hrs*15+(double)(min/4.)+(double)(sec/240.);
331 deg=sign*deg;
332
333 return deg;
334
335}
336
337
344double
345xsh_sess2deg(const double sess)
346{
347 int grad=0;
348 int min=0;
349 double sec=0;
350 double deg=0;
351 double rest=sess;
352 int sign=1;
353
354 if(sess<0) {
355 sign=-1;
356 rest=-sess;
357 }
358 grad=(int)(rest/10000.);
359 rest=rest-(double)(grad*10000.);
360 min=(int)(rest/100.);
361 sec=rest-(double)(min*100.);
362 deg=grad+(double)(min/60.)+(double)(sec/3600.);
363 deg=sign*deg;
364
365 return deg;
366
367}
368
374cpl_error_code
376{
377
378 cpl_propertylist* plist=NULL;
379 const char* name=NULL;
380 int binx=0;
381 int biny=0;
382
383 if(in==NULL) {
384 cpl_error_set(cpl_func, CPL_ERROR_NULL_INPUT);
385 return cpl_error_get_code();
386 }
387 name=cpl_frame_get_filename(in);
388 plist=cpl_propertylist_load(name,0);
389
392
393 xsh_free_propertylist(&plist);
394 if(binx*biny > 1) {
395 xsh_msg_error("This recipe expects unbinned input raw frames. Exit");
396 cpl_error_set(cpl_func, CPL_ERROR_ILLEGAL_INPUT);
397 }
398 return cpl_error_get_code();
399
400}
401
402
403/*
404^L
405*/
406
407/*
408 * @brief
409 * Copy a file.
410 *
411 * @param srcpath Source file name.
412 * @param dstpath Destination file name.
413 *
414 * @return The function returns 0 if no error occurred, otherwise -1 is
415 * returned and errno is set appropriately.
416 *
417 * The function provides a very basic way to copy the source file
418 * @em srcpath to a destination file @em dstpath.
419 *
420 * The implementation just uses @b read() and @b write() to do the job.
421 * It is by far not comparable with the @b cp shell command. Actually it
422 * just writes the source file contents into a new file with the
423 * appropriate output name.
424 *
425 * If an error occurs the destination file is removed before the function
426 * returns.
427 */
428
429int xsh_fileutils_copy (const char * srcpath, const char * dstpath)
430
431{
432char *buf;
433
434int src, dst;
435int rbytes = 0;
436int wbytes = 0;
437int blksize = DEV_BLOCKSIZE;
438
439struct stat sb, db;
440
441
442
443
444if ((stat(srcpath,&sb) == 0) && (stat(dstpath,&db) == 0))
445 {
446 if (sb.st_ino == db.st_ino)
447 return 99; /* if inodes are the same we are done already... */
448 }
449
450if ((src = open (srcpath, O_RDONLY)) == -1) return (-1);
451
452if ((fstat (src, &sb) == -1) || (!S_ISREG (sb.st_mode)))
453 {
454 (void) close (src);
455 return -2;
456 }
457
458if ((dst = open (dstpath, O_CREAT | O_WRONLY | O_TRUNC, sb.st_mode)) == -1)
459 {
460 (void) close (src);
461 return -3;
462 }
463
464if ((fstat (dst, &db) == -1) || (!S_ISREG (db.st_mode)))
465 {
466 (void) close (src);
467 (void) close (dst);
468 (void) unlink (dstpath);
469 return -4;
470 }
471
472#ifdef HAVE_ST_BLKSIZE
473blksize = db.st_blksize;
474#else
475# ifdef DEV_BSIZE
476blksize = DEV_BSIZE;
477# endif
478#endif
479
480if ((buf = (char *) cpl_malloc ((size_t)blksize)) == NULL)
481 {
482 (void) close (src);
483 (void) close (dst);
484 (void) unlink (dstpath);
485 return -5;
486 }
487
488while ((rbytes = (int) read (src, buf, (size_t)blksize)) > 0)
489 {
490 if ((wbytes = (int) write (dst, buf, (size_t)rbytes)) != rbytes)
491 {
492 wbytes = -1;
493 break;
494 }
495 }
496
497(void) close (src);
498(void) close (dst);
499cpl_free (buf);
500
501
502if ((rbytes == -1) || (wbytes == -1))
503 {
504 (void) unlink (dstpath);
505 return -6;
506 }
507
508return 0;
509
510}
511
512
513/*
514^L
515*/
516
517/*
518 * @brief
519 * Move a file.
520 *
521 * @param srcpath Source file name.
522 * @param dstpath Destination file name.
523 *
524 * @return The function returns 0 if no error occurred, otherwise -1 is
525 * returned and errno is set appropriately.
526 *
527 * The function moves the source file @em srcpath to the given
528 * destination path @em dstpath.
529 *
530 * If an error occurs the destination file is removed before the function
531 * returns and the source file is left untouched.
532 */
533
534int xsh_fileutils_move (const char *srcpath, const char *dstpath)
535
536{
537int ii;
538
539struct stat sb;
540
541
542
543if ((ii = xsh_fileutils_copy (srcpath, dstpath)) != 0)
544 {
545 if (ii == 99) /* different path name, but same inode */
546 return 99; /* => it's the same file - do nothing */
547 else
548 return (-2);
549 }
550
551
552/*
553Remove the source, but if the source file cannot be checked or is not
554writable revert to the original state, i.e. remove the file copy.
555*/
556
557if (stat (srcpath, &sb) == -1 || !(sb.st_mode & S_IWUSR))
558 {
559 (void) unlink (dstpath);
560 return -1;
561 }
562
563 (void) unlink (srcpath);
564return 0;
565
566}
567
568/*---------------------------------------------------------------------------*/
574/*---------------------------------------------------------------------------*/
575const char*
577{
578 const char* sky_prefix=NULL;
579 if(strstr(rec_prefix,"SCI") != NULL) {
580 sky_prefix="SKY_SLIT";
581 } else if(strstr(rec_prefix,"TELL") != NULL) {
582 sky_prefix="SKY_SLIT";
583 } else if(strstr(rec_prefix,"FLUX") != NULL) {
584 sky_prefix="SKY_SLIT";
585 } else {
586 sky_prefix="CAL_SLIT_SKY";
587 }
588
589 return sky_prefix;
590
591}
592/*---------------------------------------------------------------------------*/
599/*---------------------------------------------------------------------------*/
600char*
601xsh_set_recipe_file_prefix(cpl_frameset* raw,const char* recipe)
602{
603
604 cpl_frame* frm=NULL;
605 cpl_propertylist* plist=NULL;
606 const char* obj=NULL;
607 char* prefix=NULL;
608
609 const char* dpr_catg=NULL;
610 //const char* dpr_tech=NULL;
611 const char* dpr_type=NULL;
612 const char* filename=NULL;
613
614 check(frm=cpl_frameset_get_frame(raw,0));
615 filename=cpl_frame_get_filename(frm);
616 plist=cpl_propertylist_load(filename,0);
617 dpr_catg=xsh_pfits_get_dpr_catg(plist);
618 //dpr_tech=xsh_pfits_get_dpr_tech(plist);
619 dpr_type=xsh_pfits_get_dpr_type(plist);
620
621 if(strstr(dpr_catg,"SCIENCE")!=NULL) {
622 if(strstr(dpr_type,"SKY")!=NULL) {
623 obj="SKY";
624 } else {
625 obj="SCI";
626 }
627 } else if(strstr(dpr_catg,"CALIB")!=NULL) {
628 if(strstr(dpr_type,"FLUX")!=NULL) {
629 obj="FLUX";
630 } else if(strstr(dpr_type,"TELLURIC")!=NULL) {
631 obj="TELL";
632 } else {
633 obj="CAL";
634 }
635 } else {
636 obj="OBJ";
637 }
638
639 if(strstr(recipe,"respon_slit_stare")!=NULL) {
640 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
641 } else if(strstr(recipe,"respon_slit_offset")!=NULL) {
642 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
643 } else if(strstr(recipe,"respon_slit_nod")!=NULL) {
644 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
645 } else if(strstr(recipe,"scired_slit_stare")!=NULL) {
646 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
647 } else if(strstr(recipe,"scired_slit_offset")!=NULL) {
648 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
649 } else if(strstr(recipe,"scired_slit_nod")!=NULL) {
650 prefix=xsh_stringcat_any(obj,"_SLIT",(void*)NULL);
651 } else if(strstr(recipe,"scired_ifu_stare")!=NULL) {
652 prefix=xsh_stringcat_any(obj,"_IFU",(void*)NULL);
653 } else if(strstr(recipe,"scired_ifu_offset")!=NULL) {
654 prefix=xsh_stringcat_any(obj,"_IFU",(void*)NULL);
655 } else if(strstr(recipe,"geom_ifu")!=NULL) {
656 prefix=xsh_stringcat_any(obj,"_IFU",(void*)NULL);
657 } else {
658 xsh_msg_warning("recipe %s not supported",recipe);
659 prefix=xsh_stringcat_any(obj,"",(void*)NULL);
660 }
661
662
663 cleanup:
664 xsh_free_propertylist(&plist);
665
666 return prefix;
667}
668
669/*---------------------------------------------------------------------------*/
675/*---------------------------------------------------------------------------*/
676cpl_error_code xsh_set_cd_matrix(cpl_propertylist* plist)
677{
678
679 int naxis=0;
680 naxis=xsh_pfits_get_naxis(plist);
681 switch (naxis) {
682
683 case 1: xsh_set_cd_matrix1d(plist);break;
684
685 case 2: xsh_set_cd_matrix2d(plist);break;
686
687 case 3: xsh_set_cd_matrix3d(plist);break;
688
689 default: xsh_msg_error("Naxis: %d unsupported",naxis);
690 }
691
692 return cpl_error_get_code();
693}
694/*---------------------------------------------------------------------------*/
700/*---------------------------------------------------------------------------*/
701cpl_error_code xsh_set_cd_matrix1d(cpl_propertylist* plist)
702{
703 double cdelt1=xsh_pfits_get_cdelt1(plist);
704 xsh_pfits_set_cd1(plist,cdelt1);
705
706 return cpl_error_get_code();
707
708}
709
710
711/*---------------------------------------------------------------------------*/
717/*---------------------------------------------------------------------------*/
718cpl_error_code xsh_set_cd_matrix2d(cpl_propertylist* plist)
719{
720 double cdelt1=0;
721 double cdelt2=0;
722
723 /* dummy values */
724 check(cdelt1=xsh_pfits_get_cdelt1(plist));
725 check(cdelt2=xsh_pfits_get_cdelt2(plist));
726 check(xsh_pfits_set_cd11(plist,cdelt1));
727 check(xsh_pfits_set_cd12(plist,0.));
728 check(xsh_pfits_set_cd21(plist,0.));
729 check(xsh_pfits_set_cd22(plist,cdelt2));
730
731 cleanup:
732
733 return cpl_error_get_code();
734
735}
736
737/*---------------------------------------------------------------------------*/
743/*---------------------------------------------------------------------------*/
744cpl_error_code xsh_set_cd_matrix3d(cpl_propertylist* plist)
745{
746
747 double cdelt3=0;
748 check(cdelt3=xsh_pfits_get_cdelt3(plist));
749
750 check(xsh_pfits_set_cd31(plist,0.));
751 check(xsh_pfits_set_cd13(plist,0.));
752 check(xsh_pfits_set_cd32(plist,0.));
753 check(xsh_pfits_set_cd23(plist,0.));
754 check(xsh_pfits_set_cd33(plist,cdelt3));
755
756 cleanup:
757
758 return cpl_error_get_code();
759
760}
761
762/*---------------------------------------------------------------------------*/
768/*---------------------------------------------------------------------------*/
769
770cpl_parameterlist*
771xsh_parameterlist_duplicate(const cpl_parameterlist* pin){
772
773 cpl_parameter* p=NULL;
774 cpl_parameterlist* pout=NULL;
775
776 pout=cpl_parameterlist_new();
777 p=cpl_parameterlist_get_first((cpl_parameterlist*)pin);
778 while (p != NULL)
779 {
780 cpl_parameterlist_append(pout,p);
781 p=cpl_parameterlist_get_next((cpl_parameterlist*)pin);
782 }
783 return pout;
784
785}
786
787
788/*---------------------------------------------------------------------------*/
795/*---------------------------------------------------------------------------*/
796static void
797xsh_property_dump(cpl_property *property)
798{
799
800 const char *name = cpl_property_get_name(property);
801 const char *comment = cpl_property_get_comment(property);
802
803 char c;
804
805 long size = cpl_property_get_size(property);
806
807 cpl_type type = cpl_property_get_type(property);
808
809
810 fprintf(stderr, "Property at address %p\n", property);
811 fprintf(stderr, "\tname : %p '%s'\n", name, name);
812 fprintf(stderr, "\tcomment: %p '%s'\n", comment, comment);
813 fprintf(stderr, "\ttype : %#09x\n", type);
814 fprintf(stderr, "\tsize : %ld\n", size);
815 fprintf(stderr, "\tvalue : ");
816
817
818 switch (type) {
819 case CPL_TYPE_CHAR:
820 c = cpl_property_get_char(property);
821 if (!c)
822 fprintf(stderr, "''");
823 else
824 fprintf(stderr, "'%c'", c);
825 break;
826
827 case CPL_TYPE_BOOL:
828 fprintf(stderr, "%d", cpl_property_get_bool(property));
829 break;
830
831 case CPL_TYPE_INT:
832 fprintf(stderr, "%d", cpl_property_get_int(property));
833 break;
834
835 case CPL_TYPE_LONG:
836 fprintf(stderr, "%ld", cpl_property_get_long(property));
837 break;
838
839 case CPL_TYPE_FLOAT:
840 fprintf(stderr, "%.7g", cpl_property_get_float(property));
841 break;
842
843 case CPL_TYPE_DOUBLE:
844 fprintf(stderr, "%.15g", cpl_property_get_double(property));
845 break;
846
847 case CPL_TYPE_STRING:
848 fprintf(stderr, "'%s'", cpl_property_get_string(property));
849 break;
850
851 default:
852 fprintf(stderr, "unknown.");
853 break;
854
855 }
856
857 fprintf(stderr, "\n");
858
859 return;
860
861}
862
863/*---------------------------------------------------------------------------*/
872/*---------------------------------------------------------------------------*/
873
874cpl_frame*
875xsh_frameset_average(cpl_frameset *set, const char* tag)
876{
877 cpl_frame* result=NULL;
878 cpl_frame* frame=NULL;
879 cpl_image* image=NULL;
880 cpl_imagelist* iml=NULL;
881 cpl_propertylist* plist=NULL;
882 char name_o[256];
883 const char* name=NULL;
884 int i=0;
885 int size=0;
886
887 check(size=cpl_frameset_get_size(set));
888 iml=cpl_imagelist_new();
889 for(i=0;i<size;i++) {
890 frame=cpl_frameset_get_frame(set,i);
891 name=cpl_frame_get_filename(frame);
892 image=cpl_image_load(name,CPL_TYPE_FLOAT,0,0);
893 cpl_imagelist_set(iml,cpl_image_duplicate(image),i);
894 xsh_free_image(&image);
895 }
896 image=cpl_imagelist_collapse_create(iml);
897 frame=cpl_frameset_get_frame(set,0);
898 name=cpl_frame_get_filename(frame);
899 plist=cpl_propertylist_load(name,0);
900
901 sprintf(name_o,"%s.fits",tag);
902 cpl_image_save(image,name_o,CPL_BPP_IEEE_FLOAT,plist,CPL_IO_DEFAULT);
903 result=xsh_frame_product(name_o,tag,CPL_FRAME_TYPE_IMAGE,
904 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
905
906 cleanup:
907 xsh_free_image(&image);
908 xsh_free_imagelist(&iml);
909 xsh_free_propertylist(&plist);
910
911 return result;
912}
913/*---------------------------------------------------------------------------*/
914/*---------------------------------------------------------------------------*/
921cpl_frame* xsh_frameset_add( cpl_frameset *set, xsh_instrument* instr,const int decode_bp)
922{
923 int iset, i, j, set_size = 0;
924 cpl_frame *result = NULL;
925 xsh_pre **pre_list = NULL;
926 xsh_pre *pre_res = NULL;
927 float *res_flux = NULL;
928 float *res_errs = NULL;
929 int *res_qual = NULL;
930 int nx, ny;
931
933
934 check( set_size = cpl_frameset_get_size( set));
935
936 if (set_size > 0){
937 XSH_CALLOC( pre_list, xsh_pre*, set_size);
938
939 for( iset=0; iset< set_size; iset++){
940 xsh_pre* pre = NULL;
941 cpl_frame *frame = NULL;
942
943 check( frame = cpl_frameset_get_frame( set, iset));
944 check( pre = xsh_pre_load( frame, instr));
945
946 pre_list[iset] = pre;
947 }
948
949 pre_res = xsh_pre_duplicate( pre_list[0]);
950 nx = pre_res->nx;
951 ny = pre_res->ny;
952 check( res_flux = cpl_image_get_data_float( xsh_pre_get_data( pre_res)));
953 check( res_errs = cpl_image_get_data_float( xsh_pre_get_errs( pre_res)));
954 check( res_qual = cpl_image_get_data_int( xsh_pre_get_qual( pre_res)));
955
956 for( j=0; j< ny; j++){
957 for( i=0; i< nx; i++){
958 int good =0;
959 float good_flux=0, bad_flux=0;
960 float good_errs=0, bad_errs=0;
961 int good_qual=QFLAG_GOOD_PIXEL, bad_qual=QFLAG_GOOD_PIXEL;
962 int idx;
963
964 idx = i+j*nx;
965
966 for(iset = 0; iset < set_size; iset++){
967 float *img_flux = NULL;
968 float *img_errs = NULL;
969 int *img_qual = NULL;
970
971 check( img_flux = cpl_image_get_data_float( xsh_pre_get_data( pre_list[iset])));
972 check( img_errs = cpl_image_get_data_float( xsh_pre_get_errs( pre_list[iset])));
973 check( img_qual = cpl_image_get_data_int( xsh_pre_get_qual( pre_list[iset])));
974
975 if ( (img_qual[idx] & decode_bp) == 0 ){
976 /* good pix */
977 good++;
978 good_qual|=img_qual[idx];
979 good_flux += img_flux[idx];
980 good_errs += img_errs[idx]*img_errs[idx];
981 }
982 else{
983 bad_qual |= img_qual[idx];
984 bad_flux += img_flux[idx];
985 bad_errs += img_errs[idx]*img_errs[idx];
986 }
987 }
988
989 if ( good == 0){
990 res_flux[idx] = bad_flux;
991 res_errs[idx] = sqrt( bad_errs);
992 res_qual[idx] |= bad_qual;
993 }
994 else{
995 res_flux[idx] = good_flux*set_size/good;
996 res_errs[idx] = sqrt( good_errs)*set_size/good;
997 res_qual[idx] |= good_qual;
998 }
999 }
1000 }
1001 check( result = xsh_pre_save( pre_res, "COADD.fits", "COADD", 1));
1002
1003 }
1004 cleanup:
1005 if (cpl_error_get_code() != CPL_ERROR_NONE){
1006 xsh_free_frame( &result);
1007 }
1008 xsh_pre_free( &pre_res);
1009 for( i=0; i< set_size; i++){
1010 xsh_pre_free( &(pre_list[i]));
1011 }
1012 XSH_FREE( pre_list);
1013 return result;
1014}
1015/*---------------------------------------------------------------------------*/
1016
1017/*---------------------------------------------------------------------------*/
1024/*---------------------------------------------------------------------------*/
1025void
1026xsh_plist_dump(cpl_propertylist *plist)
1027{
1028
1029 long i=0;
1030 long sz = cpl_propertylist_get_size(plist);
1031
1032
1033 fprintf(stderr, "Property list at address %p:\n", plist);
1034
1035 for (i = 0; i < sz; i++) {
1036 cpl_property *p = cpl_propertylist_get(plist, i);
1038 }
1039
1040 return;
1041
1042}
1043
1044
1045/*---------------------------------------------------------------------------*/
1052/*---------------------------------------------------------------------------*/
1053cpl_error_code
1054xsh_frameset_dump(cpl_frameset* set)
1055{
1056
1057 const cpl_frame* f=NULL;
1058 int n=0;
1059 int i=0;
1060 const char* name=NULL;
1061 const char* tag=NULL;
1062 int group=0;
1063 n=cpl_frameset_get_size(set);
1064 xsh_msg("files present in set");
1065 for(i=0;i<n;i++) {
1066
1067 f=cpl_frameset_get_frame(set,i);
1068 name=cpl_frame_get_filename(f);
1069 tag=cpl_frame_get_tag(f);
1070 group=cpl_frame_get_group(f);
1071 xsh_msg("filename=%s tag=%s group=%d",name,tag,group);
1072
1073 }
1074
1075 return cpl_error_get_code();
1076
1077}
1078
1079/*---------------------------------------------------------------------------*/
1086/*---------------------------------------------------------------------------*/
1087cpl_error_code
1089{
1090
1091 const cpl_frame* f=NULL;
1092 int n=0;
1093 int i=0;
1094 const char* name=NULL;
1095 const char* tag=NULL;
1096 cpl_propertylist* plist=NULL;
1097
1098 double cum_off_y=0;
1099 double nod_throw=0;
1100 double jitter_width=0;
1101
1102
1103 n=cpl_frameset_get_size(set);
1104 xsh_msg("files present in set");
1105 for(i=0;i<n;i++) {
1106
1107 f=cpl_frameset_get_frame(set,i);
1108 name=cpl_frame_get_filename(f);
1109 tag=cpl_frame_get_tag(f);
1110
1111
1112 plist=cpl_propertylist_load(name,0);
1113 if(cpl_propertylist_has(plist,XSH_NOD_CUMULATIVE_OFFSETY)) {
1114 cum_off_y=xsh_pfits_get_cumoffsety(plist);
1115 } else {
1116
1118 }
1119
1120 if(cpl_propertylist_has(plist,XSH_NOD_THROW)) {
1121 nod_throw=xsh_pfits_get_nodthrow(plist);
1122 } else {
1124 }
1125
1126
1127 if(cpl_propertylist_has(plist,XSH_NOD_JITTER_BOX)) {
1128 jitter_width= xsh_pfits_get_nod_jitterwidth(plist);
1129 } else {
1130 xsh_msg_warning("missing %s",XSH_NOD_JITTER_BOX);
1131 }
1132
1133
1134
1135
1136 xsh_msg("filename=%s tag=%s cum_off_y=%f nod_throw=%f jitter_width=%f",
1137 name,tag,cum_off_y,nod_throw,jitter_width);
1138 xsh_free_propertylist(&plist);
1139 }
1140
1141 return cpl_error_get_code();
1142
1143}
1144
1145
1146
1147/*---------------------------------------------------------------------------*/
1158/*---------------------------------------------------------------------------*/
1159void
1161{
1162 xsh_error_reset ();
1163 xsh_msg_init ();
1164}
1165
1166
1173/*---------------------------------------------------------------------------*/
1174
1175char * xsh_get_basename(const char *filename)
1176{
1177 char *p ;
1178 p = strrchr (filename, '/');
1179 return p ? p + 1 : (char *) filename;
1180}
1181
1182
1183/*---------------------------------------------------------------------------*/
1191/*---------------------------------------------------------------------------*/
1192const char *
1194{
1195 const char *xsh_license =
1196 "This file is part of the X-shooter Instrument Pipeline\n"
1197 "Copyright (C) 2006 European Southern Observatory\n"
1198 "\n"
1199 "This program is free software; you can redistribute it and/or modify\n"
1200 "it under the terms of the GNU General Public License as published by\n"
1201 "the Free Software Foundation; either version 2 of the License, or\n"
1202 "(at your option) any later version.\n"
1203 "\n"
1204 "This program is distributed in the hope that it will be useful,\n"
1205 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
1206 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
1207 "GNU General Public License for more details.\n"
1208 "\n"
1209 "You should have received a copy of the GNU General Public License\n"
1210 "along with this program; if not, write to the Free Software\n"
1211 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, \n"
1212 "MA 02111-1307 USA";
1213 return xsh_license;
1214}
1215
1216/*---------------------------------------------------------------------------*/
1242/*---------------------------------------------------------------------------*/
1243cpl_error_code
1244xsh_begin (cpl_frameset * frames,
1245 const cpl_parameterlist * parameters,
1247 cpl_frameset ** raws,
1248 cpl_frameset ** calib,
1249 const char * tag_list[],
1250 int tag_list_size,
1251 const char *recipe_id,
1252 unsigned int binary_version,
1253 const char *short_descr)
1254{
1255 char *recipe_string = NULL;
1256 char *recipe_version = NULL;
1257 char *stars = NULL; /* A string of stars */
1258 char *spaces1 = NULL;
1259 char *spaces2 = NULL;
1260 char *spaces3 = NULL;
1261 char *spaces4 = NULL;
1262 int decode_bp=0;
1263 cpl_parameter* p=NULL;
1264 int nraws=0;
1265/* CPL 3.0 and later incarnations have a cpl_get_version().
1266 If the pipeline needs a certain version of CPL in order to function
1267 properly (say 3.1.2 but not 3.0), then validate the version
1268 number here. A compile time check on the version number
1269 is not a guarantee for correct linking, because linktime = runtime.
1270
1271 const char *version_cpl;
1272 check( version_cpl = cpl_get_version() );
1273 if (version_cpl < required_version)
1274 {
1275 xsh_warning("Detected version: %s ; Required version: %s",
1276 version_cpl, required_version);
1277 }
1278*/
1279
1280 {
1281 int lvl;
1282 //int ts ;
1283
1284 lvl = xsh_parameters_get_temporary( recipe_id, parameters ) ;
1285 if ( lvl == 0 )
1286 xsh_msg( "Keep Temporary File = no" ) ;
1287 else
1288 xsh_msg( "Keep Temporary File = yes" ) ;
1289
1290 lvl = xsh_parameters_debug_level_get( recipe_id, parameters ) ;
1291 xsh_msg( "Xsh Debug Level = %s", xsh_debug_level_tostring() ) ;
1292
1293 //ts = xsh_parameters_time_stamp_get( recipe_id, parameters ) ;
1294 }
1295
1296 /* Print welcome message
1297
1298 *********************************
1299 *** PACKAGE_STRING ***
1300 *** Recipe: recipe_id version ***
1301 *********************************
1302 Short description of recipe
1303
1304 */
1305
1306 /* Calculate recipe string */
1307 {
1308 int version_string_length;
1309 int major_version, minor_version, micro_version;
1310
1311 major_version = binary_version / 10000;
1312 minor_version = (binary_version % 10000) / 100;
1313 micro_version = binary_version % 100;
1314
1315 /* Allocate space for version numbers up to 99.99.99 */
1316 assure (major_version < 100, CPL_ERROR_UNSUPPORTED_MODE,
1317 "Major version: %d", major_version);
1318
1319 version_string_length = strlen ("XX.YY.ZZ");
1320 recipe_version = cpl_calloc (sizeof (char), version_string_length + 1);
1321
1322 snprintf (recipe_version, version_string_length + 1,
1323 "%d.%d.%d", major_version, minor_version, micro_version);
1324
1325 recipe_string =
1326 xsh_stringcat_4 ("Recipe: ", recipe_id, " ", recipe_version);
1327 }
1328
1329 {
1330 int field = MAXIMUM (strlen (PACKAGE_STRING), strlen (recipe_string));
1331 int nstars = 3 + 1 + field + 1 + 3;
1332 int nspaces1, nspaces2, nspaces3, nspaces4;
1333 int i;
1334
1335 /* ' ' padding */
1336 nspaces1 = (field - strlen (PACKAGE_STRING)) / 2;
1337 nspaces2 = field - strlen (PACKAGE_STRING) - nspaces1;
1338
1339 nspaces3 = (field - strlen (recipe_string)) / 2;
1340 nspaces4 = field - strlen (recipe_string) - nspaces3;
1341
1342 spaces1 = cpl_calloc (sizeof (char), nspaces1 + 1);
1343 for (i = 0; i < nspaces1; i++)
1344 spaces1[i] = ' ';
1345 spaces2 = cpl_calloc (sizeof (char), nspaces2 + 1);
1346 for (i = 0; i < nspaces2; i++)
1347 spaces2[i] = ' ';
1348 spaces3 = cpl_calloc (sizeof (char), nspaces3 + 1);
1349 for (i = 0; i < nspaces3; i++)
1350 spaces3[i] = ' ';
1351 spaces4 = cpl_calloc (sizeof (char), nspaces4 + 1);
1352 for (i = 0; i < nspaces4; i++)
1353 spaces4[i] = ' ';
1354
1355 stars = cpl_calloc (sizeof (char), nstars + 1);
1356 for (i = 0; i < nstars; i++)
1357 stars[i] = '*';
1358
1359 xsh_msg ("%s", stars);
1360 xsh_msg ("*** %s%s%s ***", spaces1, PACKAGE_STRING, spaces2);
1361 xsh_msg ("*** %s%s%s ***", spaces3, recipe_string, spaces4);
1362 xsh_msg ("%s", stars);
1363 }
1364
1365 xsh_msg (" %s", short_descr);
1366
1367 check( *instrument = xsh_dfs_set_groups( frames));
1369 p=xsh_parameters_find((cpl_parameterlist *)parameters,recipe_id,"decode-bp");
1370 decode_bp=cpl_parameter_get_int(p);
1372 XSH_NEW_FRAMESET( *raws);
1373 XSH_NEW_FRAMESET( *calib);
1374 check( xsh_dfs_split_in_group( frames, *raws, *calib));
1375 check( xsh_dfs_filter( *raws, tag_list, tag_list_size));
1376 XSH_ASSURE_NOT_NULL( *raws);
1379 nraws=cpl_frameset_get_size(*raws);
1380
1381
1382 /* Print input frames */
1383 xsh_msg("RAW files");
1384 check( xsh_print_cpl_frameset( *raws));
1385 xsh_msg("CALIB files");
1386 check( xsh_print_cpl_frameset( *calib));
1387
1388 if ((strcmp(recipe_id, "xsh_util_physmod") != 0)
1389 && (strcmp(recipe_id, "xsh_util_compute_response") != 0)) {
1390
1392 "Provide at least a valid input raw frame");
1393
1394 /* special case: in NIR-JH wwe need to correct input tables */
1397 if ((strcmp(recipe_id, "xsh_lingain") != 0)
1398 && (strcmp(recipe_id, "xsh_mdark") != 0)) {
1399 check(
1401 }
1402 xsh_calib_nir_corr_if_JH(*calib, *instrument, recipe_id);
1403 }
1404
1405 }
1406 cleanup:
1407 cpl_free (recipe_string);
1408 cpl_free (recipe_version);
1409 cpl_free (stars);
1410 cpl_free (spaces1);
1411 cpl_free (spaces2);
1412 cpl_free (spaces3);
1413 cpl_free (spaces4);
1414 return cpl_error_get_code ();
1415}
1416
1417
1418
1419static char **TempFiles = NULL ;
1420static int NbTemp = 0 ;
1421static char **ProdFiles = NULL ;
1422static int NbProducts = 0 ;
1423
1424/*---------------------------------------------------------------------------*/
1431/*---------------------------------------------------------------------------*/
1432void xsh_add_temporary_file( const char *name)
1433{
1434 if ( TempFiles == NULL ){
1435 TempFiles = cpl_malloc( sizeof( char*));
1436 }
1437 else {
1438 TempFiles = cpl_realloc( TempFiles, (NbTemp + 1)*sizeof( char *));
1439 }
1440 TempFiles[NbTemp] = cpl_malloc( strlen( name) + 1);
1441 strcpy( TempFiles[NbTemp], name);
1442 NbTemp++;
1443}
1444
1445/*---------------------------------------------------------------------------*/
1450/*---------------------------------------------------------------------------*/
1452{
1453 int i;
1454 //xsh_msg("free temporary files");
1455 for( i = 0 ; i<NbTemp ; i++){
1456 //xsh_msg("free file %s",TempFiles[i]);
1457 cpl_free( TempFiles[i]);
1458 }
1459 cpl_free( TempFiles);
1460 TempFiles = NULL;
1461 NbTemp=0;
1462}
1463
1464/*---------------------------------------------------------------------------*/
1471/*---------------------------------------------------------------------------*/
1472void xsh_add_product_file( const char *name)
1473{
1474 if ( ProdFiles == NULL ){
1475 ProdFiles = cpl_malloc( sizeof( char*));
1476 }
1477 else {
1478 ProdFiles = cpl_realloc( ProdFiles, (NbProducts + 1)*sizeof( char *));
1479 }
1480 ProdFiles[NbProducts] = cpl_malloc( strlen( name) + 1);
1481 strcpy( ProdFiles[NbProducts], name);
1482 NbProducts++;
1483}
1484
1485/*---------------------------------------------------------------------------*/
1490/*---------------------------------------------------------------------------*/
1492{
1493 int i;
1494
1495 for( i = 0 ; i<NbProducts ; i++){
1496 cpl_free( ProdFiles[i]);
1497 }
1498 cpl_free( ProdFiles);
1499 ProdFiles=NULL;
1500 NbProducts=0;
1501}
1502
1503
1504/*---------------------------------------------------------------------------*/
1517/*---------------------------------------------------------------------------*/
1518cpl_error_code
1519xsh_end (const char *recipe_id,
1520 cpl_frameset * frames,
1521 cpl_parameterlist * parameters )
1522{
1523 int i;
1524 int warnings = xsh_msg_get_warnings ();
1525
1526 /* Print product frames */
1527 {
1528 cpl_frame * current = NULL;
1529 int nframes = 0, j;
1530
1531 nframes = cpl_frameset_get_size( frames ) ;
1532 for( j = 0 ; j<nframes ; j++ ) {
1533 current = cpl_frameset_get_frame( frames, j);
1534 if ( cpl_frame_get_group( current ) == CPL_FRAME_GROUP_PRODUCT ) {
1535 xsh_print_cpl_frame( current ) ;
1536 }
1537 }
1538 }
1539 (void) frames ; /* suppress warning */
1540
1541 //If we need to delete some frames (like those with group=PRODUCT,
1542 //level=TEMPORARY,INTERMEDIATE), this would be the place to do it
1543 if ( xsh_parameters_get_temporary( recipe_id, parameters ) == 0 ) {
1544 xsh_msg( "---- Deleting Temporary Files" ) ;
1545 for( i = 0 ; i<NbTemp ; i++ ) {
1546 xsh_msg( " '%s'", TempFiles[i] ) ;
1547 unlink( TempFiles[i] ) ;
1548
1549 }
1550 } else {
1551 /* This to possibly remove duplicates frames
1552 xsh_msg( "---- Deleting Double copies of Product Files" ) ;
1553 for( i = 0 ; i<NbProducts ; i++ ) {
1554 xsh_msg( " '%s'", ProdFiles[i] ) ;
1555 unlink( ProdFiles[i] ) ;
1556 }
1557 */
1558 }
1559
1560 /* Summarize warnings, if any */
1561 if (warnings > 0) {
1562 xsh_msg_warning ("Recipe '%s' produced %d warning %s (excluding this one)",
1563 recipe_id, xsh_msg_get_warnings (),
1564 /* Plural? */ (warnings > 1) ? "s" : "");
1565 }
1566
1567 /* in all case free the memory at the end */
1570 return cpl_error_get_code ();
1571}
1572
1573/*---------------------------------------------------------------------------*/
1598/*---------------------------------------------------------------------------*/
1599cpl_error_code
1600xsh_get_property_value (const cpl_propertylist * plist,
1601 const char *keyword,
1602 cpl_type keywordtype,
1603 void *result)
1604{
1605 cpl_type t;
1606
1607 /* Check input */
1608 assure (plist != NULL, CPL_ERROR_NULL_INPUT, "Null property list");
1609 assure (keyword != NULL, CPL_ERROR_NULL_INPUT, "Null keyword");
1610 /* Check for existence... */
1611 assure (cpl_propertylist_has (plist, keyword), CPL_ERROR_DATA_NOT_FOUND,
1612 "Keyword %s does not exist", keyword);
1613 /* ...and type of keyword */
1614 check_msg (t = cpl_propertylist_get_type (plist, keyword),
1615 "Could not read type of keyword '%s'", keyword);
1616 assure (t == keywordtype, CPL_ERROR_TYPE_MISMATCH,
1617 "Keyword '%s' has wrong type (%s). %s expected",
1618 keyword, xsh_tostring_cpl_type (t),
1619 xsh_tostring_cpl_type (keywordtype));
1620 /* Read the keyword */
1621 switch (keywordtype) {
1622 case CPL_TYPE_INT:
1623 check_msg (*((int *) result) = cpl_propertylist_get_int (plist, keyword),
1624 "Could not get (integer) value of %s", keyword);
1625 break;
1626 case CPL_TYPE_BOOL:
1627 check_msg (*((bool *) result) = cpl_propertylist_get_bool (plist, keyword),
1628 "Could not get (boolean) value of %s", keyword);
1629 break;
1630 case CPL_TYPE_DOUBLE:
1631 check_msg (*((double *) result) =
1632 cpl_propertylist_get_double (plist, keyword),
1633 "Could not get (double) value of %s", keyword);
1634 break;
1635 case CPL_TYPE_STRING:
1636 check_msg (*((const char **) result) =
1637 cpl_propertylist_get_string (plist, keyword),
1638 "Could not get (string) value of %s", keyword);
1639 break;
1640 default:
1641 assure (false, CPL_ERROR_INVALID_TYPE, "Unknown type");
1642 }
1643
1644cleanup:
1645 return cpl_error_get_code ();
1646}
1647
1648/*---------------------------------------------------------------------------*/
1656/*---------------------------------------------------------------------------*/
1657char *
1658xsh_stringdup (const char *s)
1659{
1660 char *result = NULL;
1661
1662 assure (s != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1663
1664 result = cpl_calloc (sizeof (char), strlen (s) + 1);
1665 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1666 "Memory allocation failed");
1667
1668 sprintf (result, "%s", s);
1669
1670cleanup:
1671 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1672 cpl_free (result);
1673 result = NULL;
1674 }
1675
1676 return result;
1677}
1678
1690char *
1691xsh_sdate_utc( time_t *now )
1692{
1693 char *date = NULL;
1694 struct tm ttm;
1695
1696 ttm = *gmtime( now ) ;
1697 XSH_CALLOC( date, char, 16);
1698
1699 sprintf( date, "%04d%02d%02d-%02d%02d%02d",
1700 ttm.tm_year+1900, ttm.tm_mon+1, ttm.tm_mday,
1701 ttm.tm_hour, ttm.tm_min, ttm.tm_sec ) ;
1702
1703 cleanup:
1704 return date ;
1705
1706}
1707
1708/*---------------------------------------------------------------------------*/
1717/*---------------------------------------------------------------------------*/
1718char *
1719xsh_stringcat (const char *s1, const char *s2)
1720{
1721 char *result = NULL;
1722
1723 assure (s1 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1724 assure (s2 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1725
1726 result = cpl_calloc (sizeof (char), strlen (s1) + strlen (s2) + 1);
1727 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1728 "Memory allocation failed");
1729
1730 sprintf (result, "%s%s", s1, s2);
1731
1732cleanup:
1733 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1734 cpl_free (result);
1735 result = NULL;
1736 }
1737
1738 return result;
1739}
1740
1741/*---------------------------------------------------------------------------*/
1751/*---------------------------------------------------------------------------*/
1752char *
1753xsh_stringcat_3 (const char *s1, const char *s2, const char *s3)
1754{
1755 char *result = NULL;
1756
1757 assure (s1 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1758 assure (s2 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1759 assure (s3 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1760
1761 result =
1762 cpl_calloc (sizeof (char), strlen (s1) + strlen (s2) + strlen (s3) + 1);
1763 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1764 "Memory allocation failed");
1765
1766 sprintf (result, "%s%s%s", s1, s2, s3);
1767
1768cleanup:
1769 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1770 cpl_free (result);
1771 result = NULL;
1772 }
1773
1774 return result;
1775}
1776
1777/*---------------------------------------------------------------------------*/
1789/*---------------------------------------------------------------------------*/
1790char *
1791xsh_stringcat_4 (const char *s1, const char *s2, const char *s3,const char *s4)
1792{
1793 char *result = NULL;
1794
1795 assure (s1 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1796 assure (s2 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1797 assure (s3 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1798 assure (s4 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1799
1800 result = cpl_calloc (sizeof (char), strlen (s1) + strlen (s2) +
1801 strlen (s3) + strlen (s4) + 1);
1802 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1803 "Memory allocation failed");
1804
1805 sprintf (result, "%s%s%s%s", s1, s2, s3, s4);
1806
1807cleanup:
1808 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1809 cpl_free (result);
1810 result = NULL;
1811 }
1812
1813 return result;
1814}
1815
1816/*---------------------------------------------------------------------------*/
1829/*---------------------------------------------------------------------------*/
1830char *
1831xsh_stringcat_5 (const char *s1, const char *s2, const char *s3,
1832 const char *s4, const char *s5)
1833{
1834 char *result = NULL;
1835
1836 assure (s1 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1837 assure (s2 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1838 assure (s3 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1839 assure (s4 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1840 assure (s5 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1841
1842 result = cpl_calloc (sizeof (char), strlen (s1) + strlen (s2) +
1843 strlen (s3) +strlen (s4) + strlen (s5) + 1);
1844 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1845 "Memory allocation failed");
1846
1847 sprintf (result, "%s%s%s%s%s", s1, s2, s3, s4, s5);
1848
1849cleanup:
1850 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1851 cpl_free (result);
1852 result = NULL;
1853 }
1854
1855 return result;
1856}
1857
1858/*---------------------------------------------------------------------------*/
1873/*---------------------------------------------------------------------------*/
1874char *
1875xsh_stringcat_6 (const char *s1, const char *s2, const char *s3,
1876 const char *s4, const char *s5, const char *s6)
1877{
1878 char *result = NULL;
1879
1880 assure (s1 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1881 assure (s2 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1882 assure (s3 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1883 assure (s4 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1884 assure (s5 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1885 assure (s6 != NULL, CPL_ERROR_NULL_INPUT, "Null string");
1886
1887 result = cpl_calloc (sizeof (char),
1888 strlen (s1) + strlen (s2) + strlen (s3) +
1889 strlen (s4) + strlen (s5) + strlen (s6) + 1);
1890 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1891 "Memory allocation failed");
1892
1893 sprintf (result, "%s%s%s%s%s%s", s1, s2, s3, s4, s5, s6);
1894
1895cleanup:
1896 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1897 cpl_free (result);
1898 result = NULL;
1899 }
1900
1901 return result;
1902}
1903
1924char *
1925xsh_stringcat_any (const char *s, ...)
1926{
1927 char *result = NULL;
1928 int size = 2;
1929 va_list av;
1930
1931 va_start (av, s);
1932 result = cpl_malloc (2);
1933 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1934 "Memory allocation failed");
1935 result[0] = '\0';
1936 for (;;) {
1937 size += strlen (s) + 2;
1938 result = cpl_realloc (result, size);
1939 assure (result != NULL, CPL_ERROR_ILLEGAL_OUTPUT,
1940 "Memory allocation failed");
1941 strcat (result, s);
1942 s = va_arg (av, char *);
1943 if (s == NULL || *s == '\0')
1944 break;
1945 }
1946
1947cleanup:
1948 if (cpl_error_get_code () != CPL_ERROR_NONE) {
1949 cpl_free (result);
1950 result = NULL;
1951 }
1952
1953 va_end (av);
1954 return result;
1955}
1956
1957/*---------------------------------------------------------------------------*/
1965/*---------------------------------------------------------------------------*/
1966int* xsh_sort(void* base, size_t nmemb, size_t size,
1967 int (*compar)(const void *, const void *)) {
1968
1969 int i = 0;
1970 int * idx = NULL;
1971 xsh_sort_data* sort = NULL;
1972
1973 /* check input parameters */
1974 XSH_ASSURE_NOT_NULL(base);
1975 XSH_ASSURE_NOT_ILLEGAL(nmemb > 0);
1977 XSH_ASSURE_NOT_NULL(compar);
1978
1979 /* allocate memory */
1980 XSH_MALLOC(idx,int,nmemb);
1981 XSH_MALLOC(sort,xsh_sort_data,nmemb);
1982
1983 /* fill the sort structure */
1984 for( i=0; i< (int)nmemb; i++) {
1985 sort[i].data = (void*)((size_t)base+i*size);
1986 sort[i].idx = i;
1987 }
1988
1989 /* do the sort */
1990 qsort(sort,nmemb,sizeof(xsh_sort_data),compar);
1991
1992 /* fill the index */
1993 for( i=0; i< (int)nmemb; i++) {
1994 idx[i] = sort[i].idx;
1995 }
1996
1997 cleanup:
1998 XSH_FREE(sort);
1999 return idx;
2000}
2001
2008void xsh_reindex(double* data, int* idx, int size) {
2009 int i;
2010
2011 /* check input parameters */
2015
2016 for(i=0; i< size; i++){
2017 int id;
2018 double temp;
2019
2020 id = idx[i];
2021 while (id < i){
2022 id = idx[id];
2023 }
2024 temp = data[i];
2025 data[i] = data[id];
2026 data[id] = temp;
2027 }
2028 cleanup:
2029 return;
2030}
2031
2038void xsh_reindex_float(float * data, int* idx, int size)
2039{
2040 int i;
2041
2042 /* check input parameters */
2046
2047 for(i=0; i< size; i++){
2048 int id;
2049 float temp;
2050
2051 id = idx[i];
2052 while (id < i){
2053 id = idx[id];
2054 }
2055 temp = data[i];
2056 data[i] = data[id];
2057 data[id] = temp;
2058 }
2059 cleanup:
2060 return;
2061}
2062
2063
2070void xsh_reindex_int( int * data, int* idx, int size)
2071{
2072 int i;
2073
2074 /* check input parameters */
2078
2079 for(i=0; i< size; i++){
2080 int id;
2081 int temp;
2082
2083 id = idx[i];
2084 while (id < i){
2085 id = idx[id];
2086 }
2087 temp = data[i];
2088 data[i] = data[id];
2089 data[id] = temp;
2090 }
2091 cleanup:
2092 return;
2093}
2094
2095
2096/*---------------------------------------------------------------------------*/
2101/*---------------------------------------------------------------------------*/
2102void xsh_free(const void *mem)
2103{
2104 cpl_free((void *)mem); /* No, it is not a bug. The cast is safe */
2105 return;
2106}
2107
2108
2109/*---------------------------------------------------------------------------*/
2114/*---------------------------------------------------------------------------*/
2115void
2116xsh_free_image (cpl_image ** i)
2117{
2118 if (i && *i) {
2119 cpl_image_delete (*i);
2120 *i = NULL;
2121 }
2122}
2123
2124
2125
2126/*---------------------------------------------------------------------------*/
2131/*---------------------------------------------------------------------------*/
2132void
2133xsh_free_table (cpl_table ** t)
2134{
2135 if (t && *t) {
2136 cpl_table_delete (*t);
2137 *t = NULL;
2138 }
2139}
2140
2141
2142/*---------------------------------------------------------------------------*/
2147/*---------------------------------------------------------------------------*/
2148void
2149xsh_free_mask (cpl_mask ** m)
2150{
2151 if (m && *m) {
2152 cpl_mask_delete (*m);
2153 *m = NULL;
2154 }
2155}
2156
2157/*---------------------------------------------------------------------------*/
2162/*---------------------------------------------------------------------------*/
2163void
2164xsh_free_imagelist (cpl_imagelist ** i)
2165{
2166 if (i && *i) {
2167 cpl_imagelist_delete (*i);
2168 *i = NULL;
2169 }
2170}
2171
2172/*---------------------------------------------------------------------------*/
2177/*---------------------------------------------------------------------------*/
2178void
2179xsh_free_propertylist (cpl_propertylist ** p)
2180{
2181 if (p && *p) {
2182 cpl_propertylist_delete (*p);
2183 *p = NULL;
2184 }
2185}
2186
2187/*---------------------------------------------------------------------------*/
2192/*---------------------------------------------------------------------------*/
2193void
2194xsh_free_polynomial (cpl_polynomial ** p)
2195{
2196 if (p && *p) {
2197 cpl_polynomial_delete (*p);
2198 *p = NULL;
2199 }
2200}
2201
2202/*---------------------------------------------------------------------------*/
2207/*---------------------------------------------------------------------------*/
2208void
2209xsh_free_matrix (cpl_matrix ** m)
2210{
2211 if (m && *m) {
2212 cpl_matrix_delete (*m);
2213 *m = NULL;
2214 }
2215}
2216
2217/*---------------------------------------------------------------------------*/
2222/*---------------------------------------------------------------------------*/
2223void
2224xsh_free_parameterlist (cpl_parameterlist ** p)
2225{
2226 if (p && *p) {
2227 cpl_parameterlist_delete (*p);
2228 *p = NULL;
2229 }
2230}
2231
2232/*---------------------------------------------------------------------------*/
2237/*---------------------------------------------------------------------------*/
2238void
2239xsh_free_parameter (cpl_parameter ** p)
2240{
2241 if (p && *p) {
2242 cpl_parameter_delete (*p);
2243 *p = NULL;
2244 }
2245}
2246
2247/*---------------------------------------------------------------------------*/
2252/*---------------------------------------------------------------------------*/
2253void
2254xsh_free_frameset (cpl_frameset ** f)
2255{
2256 if (f && *f) {
2257 cpl_frameset_delete (*f);
2258 *f = NULL;
2259 }
2260}
2261
2262/*---------------------------------------------------------------------------*/
2267/*---------------------------------------------------------------------------*/
2268void
2269xsh_free_frame (cpl_frame ** f)
2270{
2271 if (f && *f) {
2272 cpl_frame_delete (*f);
2273 *f = NULL;
2274 }
2275}
2276
2277/*---------------------------------------------------------------------------*/
2282/*---------------------------------------------------------------------------*/
2283void
2284xsh_free_vector (cpl_vector ** v)
2285{
2286 if (v && *v) {
2287 cpl_vector_delete (*v);
2288 *v = NULL;
2289 }
2290}
2291
2292/*---------------------------------------------------------------------------*/
2297/*---------------------------------------------------------------------------*/
2298void
2299xsh_free_array (cpl_array ** m)
2300{
2301 if (m && *m) {
2302 cpl_array_delete (*m);
2303 *m = NULL;
2304 }
2305}
2306
2307/*---------------------------------------------------------------------------*/
2312/*---------------------------------------------------------------------------*/
2313void
2314xsh_free_stats (cpl_stats ** s)
2315{
2316 if (s && *s) {
2317 cpl_stats_delete (*s);
2318 *s = NULL;
2319 }
2320}
2321
2322/*---------------------------------------------------------------------------*/
2329/*---------------------------------------------------------------------------*/
2330void xsh_unwrap_image( cpl_image **i)
2331{
2332 if ( i && *i) {
2333 cpl_image_unwrap( *i);
2334 *i = NULL;
2335 }
2336}
2337
2338/*---------------------------------------------------------------------------*/
2343/*---------------------------------------------------------------------------*/
2344void
2345xsh_unwrap_vector (cpl_vector ** v)
2346{
2347 if (v && *v) {
2348 cpl_vector_unwrap (*v);
2349 *v = NULL;
2350 }
2351}
2352
2353
2354/*---------------------------------------------------------------------------*/
2359/*---------------------------------------------------------------------------*/
2360void
2361xsh_unwrap_array (cpl_array ** a)
2362{
2363 if (a && *a) {
2364 cpl_array_unwrap (*a);
2365 *a = NULL;
2366 }
2367}
2368
2369/*----------------------------------------------------------------------------*/
2374/*---------------------------------------------------------------------------*/
2375void
2377{
2378 if (b && *b) {
2379 cpl_bivector_unwrap_vectors (*b);
2380 *b = NULL;
2381 }
2382}
2383/*---------------------------------------------------------------------------*/
2384
2389void xsh_show_time( const char *comment )
2390{
2391 struct rusage tm0 ;
2392
2393 getrusage( 0, &tm0 ) ;
2394 xsh_msg( "%s - User: %u.%06u - Syst: %u.%06u",
2395 comment, (unsigned)tm0.ru_utime.tv_sec,
2396 (unsigned)tm0.ru_utime.tv_usec,
2397 (unsigned)tm0.ru_stime.tv_sec,
2398 (unsigned)tm0.ru_stime.tv_usec ) ;
2399 return ;
2400}
2401
2402/* Swap macros */
2403#define XSH_DOUBLE_SWAP(a,b) { register double t=(a);(a)=(b);(b)=t; }
2404#define XSH_FLOAT_SWAP(a,b) { register float t=(a);(a)=(b);(b)=t; }
2405#define XSH_INT_SWAP(a,b) { register int t=(a);(a)=(b);(b)=t; }
2406
2407#define XSH_PIX_STACK_SIZE 50
2408
2409
2410/*----------------------------------------------------------------------------*/
2420void
2421xsh_tools_get_statistics(double* tab, int size, double* median,
2422 double* mean, double* stdev)
2423{
2424 cpl_vector* tab_vec = NULL;
2425 int i = 0;
2426
2427 /* check input parameters */
2428 XSH_ASSURE_NOT_NULL( tab);
2430 XSH_ASSURE_NOT_NULL( median);
2431 XSH_ASSURE_NOT_NULL( mean);
2432 XSH_ASSURE_NOT_NULL( stdev);
2433
2434 /* Created vector */
2435 check (tab_vec = cpl_vector_new( size));
2436 for( i=0; i< size; i++){
2437 check( cpl_vector_set( tab_vec, i, tab[i]));
2438 }
2439
2440 check( *median = cpl_vector_get_median( tab_vec));
2441 check( *stdev = cpl_vector_get_stdev( tab_vec));
2442 check( *mean = cpl_vector_get_mean( tab_vec));
2443
2444 cleanup:
2445 xsh_free_vector( &tab_vec);
2446 return;
2447}
2459/*----------------------------------------------------------------------------*/
2460cpl_error_code
2461xsh_tools_sort_double( double * pix_arr, int n )
2462{
2463 int i, ir, j, k, l;
2464 int * i_stack ;
2465 int j_stack ;
2466 double a ;
2467
2468 /* Check entries */
2469 if ( pix_arr == NULL ) {
2470 return CPL_ERROR_NULL_INPUT ;
2471 }
2472
2473 ir = n ;
2474 l = 1 ;
2475 j_stack = 0 ;
2476 i_stack = cpl_malloc(XSH_PIX_STACK_SIZE * sizeof(double)) ;
2477 for (;;) {
2478 if (ir-l < 7) {
2479 for (j=l+1 ; j<=ir ; j++) {
2480 a = pix_arr[j-1];
2481 for (i=j-1 ; i>=1 ; i--) {
2482 if (pix_arr[i-1] <= a) break;
2483 pix_arr[i] = pix_arr[i-1];
2484 }
2485 pix_arr[i] = a;
2486 }
2487 if (j_stack == 0) break;
2488 ir = i_stack[j_stack-- -1];
2489 l = i_stack[j_stack-- -1];
2490 } else {
2491 k = (l+ir) >> 1;
2492 XSH_DOUBLE_SWAP(pix_arr[k-1], pix_arr[l])
2493 if (pix_arr[l] > pix_arr[ir-1]) {
2494 XSH_DOUBLE_SWAP(pix_arr[l], pix_arr[ir-1])
2495 }
2496 if (pix_arr[l-1] > pix_arr[ir-1]) {
2497 XSH_DOUBLE_SWAP(pix_arr[l-1], pix_arr[ir-1])
2498 }
2499 if (pix_arr[l] > pix_arr[l-1]) {
2500 XSH_DOUBLE_SWAP(pix_arr[l], pix_arr[l-1])
2501 }
2502 i = l+1;
2503 j = ir;
2504 a = pix_arr[l-1];
2505 for (;;) {
2506 do i++; while (pix_arr[i-1] < a);
2507 do j--; while (pix_arr[j-1] > a);
2508 if (j < i) break;
2509 XSH_DOUBLE_SWAP(pix_arr[i-1], pix_arr[j-1]);
2510 }
2511 pix_arr[l-1] = pix_arr[j-1];
2512 pix_arr[j-1] = a;
2513 j_stack += 2;
2514 if (j_stack > XSH_PIX_STACK_SIZE) {
2515 /* Should never reach here */
2516 cpl_free(i_stack);
2517 return CPL_ERROR_ILLEGAL_INPUT ;
2518 }
2519 if (ir-i+1 >= j-l) {
2520 i_stack[j_stack-1] = ir;
2521 i_stack[j_stack-2] = i;
2522 ir = j-1;
2523 } else {
2524 i_stack[j_stack-1] = j-1;
2525 i_stack[j_stack-2] = l;
2526 l = i;
2527 }
2528 }
2529 }
2530 cpl_free(i_stack) ;
2531 return CPL_ERROR_NONE ;
2532}
2533
2534
2546/*----------------------------------------------------------------------------*/
2547cpl_error_code
2548xsh_tools_sort_float( float * pix_arr, int n )
2549{
2550 int i, ir, j, k, l;
2551 int * i_stack ;
2552 int j_stack ;
2553 float a ;
2554
2555 /* Check entries */
2556 if ( pix_arr == NULL ) {
2557 return CPL_ERROR_NULL_INPUT ;
2558 }
2559
2560 ir = n ;
2561 l = 1 ;
2562 j_stack = 0 ;
2563 i_stack = cpl_malloc(XSH_PIX_STACK_SIZE * sizeof(float)) ;
2564 for (;;) {
2565 if (ir-l < 7) {
2566 for (j=l+1 ; j<=ir ; j++) {
2567 a = pix_arr[j-1];
2568 for (i=j-1 ; i>=1 ; i--) {
2569 if (pix_arr[i-1] <= a) break;
2570 pix_arr[i] = pix_arr[i-1];
2571 }
2572 pix_arr[i] = a;
2573 }
2574 if (j_stack == 0) break;
2575 ir = i_stack[j_stack-- -1];
2576 l = i_stack[j_stack-- -1];
2577 } else {
2578 k = (l+ir) >> 1;
2579 XSH_FLOAT_SWAP(pix_arr[k-1], pix_arr[l])
2580 if (pix_arr[l] > pix_arr[ir-1]) {
2581 XSH_FLOAT_SWAP(pix_arr[l], pix_arr[ir-1])
2582 }
2583 if (pix_arr[l-1] > pix_arr[ir-1]) {
2584 XSH_FLOAT_SWAP(pix_arr[l-1], pix_arr[ir-1])
2585 }
2586 if (pix_arr[l] > pix_arr[l-1]) {
2587 XSH_FLOAT_SWAP(pix_arr[l], pix_arr[l-1])
2588 }
2589 i = l+1;
2590 j = ir;
2591 a = pix_arr[l-1];
2592 for (;;) {
2593 do i++; while (pix_arr[i-1] < a);
2594 do j--; while (pix_arr[j-1] > a);
2595 if (j < i) break;
2596 XSH_FLOAT_SWAP(pix_arr[i-1], pix_arr[j-1]);
2597 }
2598 pix_arr[l-1] = pix_arr[j-1];
2599 pix_arr[j-1] = a;
2600 j_stack += 2;
2601 if (j_stack > XSH_PIX_STACK_SIZE) {
2602 /* Should never reach here */
2603 cpl_free(i_stack);
2604 return CPL_ERROR_ILLEGAL_INPUT ;
2605 }
2606 if (ir-i+1 >= j-l) {
2607 i_stack[j_stack-1] = ir;
2608 i_stack[j_stack-2] = i;
2609 ir = j-1;
2610 } else {
2611 i_stack[j_stack-1] = j-1;
2612 i_stack[j_stack-2] = l;
2613 l = i;
2614 }
2615 }
2616 }
2617 cpl_free(i_stack) ;
2618 return CPL_ERROR_NONE ;
2619}
2620
2621
2632cpl_error_code
2633xsh_tools_sort_int( int * pix_arr, int n)
2634{
2635 int i, ir, j, k, l;
2636 int * i_stack ;
2637 int j_stack ;
2638 int a ;
2639
2640 /* Check entries */
2641 if ( pix_arr == NULL ) {
2642 return CPL_ERROR_NULL_INPUT ;
2643 }
2644
2645 ir = n ;
2646 l = 1 ;
2647 j_stack = 0 ;
2648 i_stack = cpl_malloc(XSH_PIX_STACK_SIZE * sizeof(double)) ;
2649 for (;;) {
2650 if (ir-l < 7) {
2651 for (j=l+1 ; j<=ir ; j++) {
2652 a = pix_arr[j-1];
2653 for (i=j-1 ; i>=1 ; i--) {
2654 if (pix_arr[i-1] <= a) break;
2655 pix_arr[i] = pix_arr[i-1];
2656 }
2657 pix_arr[i] = a;
2658 }
2659 if (j_stack == 0) break;
2660 ir = i_stack[j_stack-- -1];
2661 l = i_stack[j_stack-- -1];
2662 } else {
2663 k = (l+ir) >> 1;
2664 XSH_INT_SWAP(pix_arr[k-1], pix_arr[l])
2665 if (pix_arr[l] > pix_arr[ir-1]) {
2666 XSH_INT_SWAP(pix_arr[l], pix_arr[ir-1])
2667 }
2668 if (pix_arr[l-1] > pix_arr[ir-1]) {
2669 XSH_INT_SWAP(pix_arr[l-1], pix_arr[ir-1])
2670 }
2671 if (pix_arr[l] > pix_arr[l-1]) {
2672 XSH_INT_SWAP(pix_arr[l], pix_arr[l-1])
2673 }
2674 i = l+1;
2675 j = ir;
2676 a = pix_arr[l-1];
2677 for (;;) {
2678 do i++; while (pix_arr[i-1] < a);
2679 do j--; while (pix_arr[j-1] > a);
2680 if (j < i) break;
2681 XSH_INT_SWAP(pix_arr[i-1], pix_arr[j-1]);
2682 }
2683 pix_arr[l-1] = pix_arr[j-1];
2684 pix_arr[j-1] = a;
2685 j_stack += 2;
2686 if (j_stack > XSH_PIX_STACK_SIZE) {
2687 /* Should never reach here */
2688 cpl_free(i_stack);
2689 return CPL_ERROR_ILLEGAL_INPUT ;
2690 }
2691 if (ir-i+1 >= j-l) {
2692 i_stack[j_stack-1] = ir;
2693 i_stack[j_stack-2] = i;
2694 ir = j-1;
2695 } else {
2696 i_stack[j_stack-1] = j-1;
2697 i_stack[j_stack-2] = l;
2698 l = i;
2699 }
2700 }
2701 }
2702 cpl_free(i_stack) ;
2703 return CPL_ERROR_NONE ;
2704}
2705
2721double xsh_tools_get_median_double( double *array, int size )
2722{
2723 double result = 0. ;
2724
2725 /* First sort array */
2726 xsh_tools_sort_double( array, size ) ;
2727
2728 /* Then get median */
2729 if ( (size % 2) == 1 ) result = *(array+(size/2)) ;
2730 else {
2731 double min, max ;
2732
2733 min = *(array+(size/2)-1) ;
2734 max = *(array+(size/2) ) ;
2735 result = (min+max)/2. ;
2736 }
2737
2738 return result ;
2739}
2740
2747int
2748xsh_tools_running_median_1d_get_max( double * tab, int size, int wsize )
2749{
2750 int position = 0;
2751 int i ;
2752 double /*wtab[128] ;*/ * wtab = NULL ;
2753 double max = -1000000. ;
2754
2755 XSH_ASSURE_NOT_NULL( tab ) ;
2756 XSH_MALLOC( wtab, double, (wsize*2)*2 ) ;
2757 /*
2758 loop over tab
2759 get window
2760 get median
2761 if > max, keep position
2762 */
2763 //xsh_msg( ">>>> Running Median" ) ;
2764
2765 for( i = wsize ; i<(size-wsize) ; i++ ) {
2766 int j, k ;
2767 double f_max;
2768
2769 //xsh_msg( " Position: %d (%d elem)", i, (wsize*2)+1 ) ;
2770 for( k=0, j = i-wsize ; j<=(i+wsize) ; j++, k++ ) {
2771 wtab[k] = tab[j] ;
2772 //xsh_msg( " Value[%d]: %lf", k, wtab[k] ) ;
2773 }
2774 if ( (f_max=xsh_tools_get_median_double(wtab, (wsize*2) + 1)) > max ) {
2775 max = f_max ;
2776 position = i ;
2777 }
2778 }
2779
2780
2781 cleanup:
2782 XSH_FREE( wtab ) ;
2783 return position ;
2784}
2785
2786
2787/*----------------------------------------------------------------------------*/
2796/*----------------------------------------------------------------------------*/
2797
2798
2799void xsh_tools_min_max(int size, double *tab, double *min, double *max)
2800{
2801
2802 int i;
2803
2808
2809 *min = tab[0];
2810 *max = tab[0];
2811
2812 for(i=1; i < size; i++) {
2813 if (tab[i] < *min){
2814 *min = tab[i];
2815 }
2816 else if ( tab[i] > *max) {
2817 *max = tab[i];
2818 }
2819 }
2820
2821 cleanup:
2822 return;
2823}
2824
2836cpl_vector* xsh_tools_tchebitchev_poly_eval( int n, double X)
2837{
2838 cpl_vector *result = NULL;
2839
2841 check( result = cpl_vector_new( n+1));
2842 check( cpl_vector_set(result, 0, 1.0));
2843
2844 if (n > 0){
2845 int indice = 2;
2846 check( cpl_vector_set(result, 1, X));
2847 while( indice <= n){
2848 double T_indice = 0.0;
2849 double T_indice_1 = 0.0;
2850 double T_indice_2 = 0.0;
2851
2852 check( T_indice_1 = cpl_vector_get( result, indice-1));
2853 check( T_indice_2 = cpl_vector_get( result, indice-2));
2854 T_indice = 2*X*T_indice_1-T_indice_2;
2855 check( cpl_vector_set( result, indice, T_indice));
2856 indice++;
2857 }
2858 }
2859 cleanup:
2860 if ( cpl_error_get_code() != CPL_ERROR_NONE){
2861 xsh_free_vector( &result);
2862 }
2863 return result;
2864}
2865
2866
2867/*----------------------------------------------------------------------------*/
2877/*----------------------------------------------------------------------------*/
2878
2879
2880void
2881xsh_tools_tchebitchev_transform_tab(int size, double* pos, double min,
2882 double max, double* tcheb_pos)
2883{
2884 int i;
2885 double a,b;
2886
2888 XSH_ASSURE_NOT_NULL(tcheb_pos);
2891
2892 a = 2/ (max-min);
2893 b = 1-2*max/(max-min);
2894
2895 for(i=0; i < size; i++) {
2896 tcheb_pos[i] = pos[i]*a+b;
2897 if ( tcheb_pos[i] < -1. ) tcheb_pos[i] = -1. ;
2898 if ( tcheb_pos[i] > 1. ) tcheb_pos[i] = 1. ;
2899 }
2900
2901 cleanup:
2902 return;
2903}
2904
2905
2906/*----------------------------------------------------------------------------*/
2914/*----------------------------------------------------------------------------*/
2915
2916double
2917xsh_tools_tchebitchev_transform(double pos, double min, double max)
2918{
2919 double a,b;
2920 double res = 0.0;
2921
2923
2924 a = 2/ (max-min);
2925 b = 1-2*max/(max-min);
2926
2927 res = pos*a+b;
2928 if(res <= -1.000001) {
2929 xsh_msg_dbg_medium("OUT_OF_RANGE res <= -1.000001 for %f [%f,%f]",
2930 pos, min , max);
2931 }
2932 if(res >= +1.000001) {
2933 xsh_msg_dbg_medium("OUT_OF_RANGE res >= +1.000001 for %f [%f,%f]",
2934 pos, min , max);
2935 }
2936
2937 //XSH_ASSURE_NOT_ILLEGAL( res >= -1.000001);
2938 //XSH_ASSURE_NOT_ILLEGAL( res <= 1.000001);
2939
2940 cleanup:
2941 return res;
2942}
2943
2944/*----------------------------------------------------------------------------*/
2952/*----------------------------------------------------------------------------*/
2953double
2954xsh_tools_tchebitchev_reverse_transform(double pos, double min, double max)
2955{
2956 double a,b;
2957 double res = 0.0;
2958
2960
2961 a = 2/ (max-min);
2962 b = 1-2*max/(max-min);
2963
2964 res = (pos-b)/a;
2965
2966 cleanup:
2967 return res;
2968}
2969
2970
2971/*----------------------------------------------------------------------------*/
2978/*----------------------------------------------------------------------------*/
2979void
2980xsh_image_fit_spline(cpl_image* img, xsh_grid* grid)
2981{
2982 int nx, ny;
2983 int i = 0, ja, jb, idx = 0, vxsize, size;
2984 double *data = NULL;
2985 int *ylines = NULL;
2986 int *xline = NULL;
2987 double *vline = NULL;
2988 int nbylines;
2989 xsh_grid_point *pointA = NULL;
2990 xsh_grid_point *pointB = NULL;
2991
2992 /* check input parameters */
2993 XSH_ASSURE_NOT_NULL( img);
2994 XSH_ASSURE_NOT_NULL( grid);
2995 XSH_ASSURE_NOT_ILLEGAL( cpl_image_get_type(img) == CPL_TYPE_DOUBLE);
2996
2997 check( data = cpl_image_get_data_double(img));
2998 check( nx = cpl_image_get_size_x(img));
2999 check( ny = cpl_image_get_size_y(img));
3000 check( size = xsh_grid_get_index(grid));
3001
3002 ja = 0;
3003 jb = ja+1;
3004 nbylines = 0;
3005 vxsize = 0;
3006
3007 XSH_MALLOC( ylines, int, ny);
3008 XSH_MALLOC( xline, int, nx);
3009 XSH_MALLOC( vline, double, nx);
3010
3011 /* interpolate in X direction */
3012 while( jb < size) {
3013 double a = 0.0, b = 0.0;
3014 int cur_y;
3015
3016 nbylines++;
3017 vxsize = 1;
3018 /* get first point of the line */
3019 check( pointA = xsh_grid_point_get( grid, ja));
3020 check( pointB = xsh_grid_point_get( grid, jb));
3021
3022 cur_y = pointA->y-1;
3023 ylines[nbylines-1]= cur_y;
3024 xline[vxsize-1] = pointA->x-1;
3025 vline[vxsize-1] = pointA->v;
3026
3027 while( ( jb < size) && ( pointA->y == pointB->y) ){
3028 check( pointB = xsh_grid_point_get( grid, jb));
3029
3030 if ( (pointB->x-1) != xline[vxsize-1]){
3031 xline[vxsize] = pointB->x-1;
3032 vline[vxsize] = pointB->v;
3033 vxsize++;
3034 }
3035 jb++;
3036 }
3037 XSH_ASSURE_NOT_ILLEGAL( vxsize >=2);
3038
3039 for(idx=0; idx<vxsize-1; idx++){
3040 int nbpix = 0;
3041 int xa, xb;
3042 double va, vb;
3043
3044 xa = xline[idx];
3045 xb = xline[idx+1];
3046
3047 va = vline[idx];
3048 vb = vline[idx+1];
3049
3050 a = ( vb - va) / ( xb - xa);
3051 b = va-a*xa;
3052
3053 nbpix = xb-xa;
3054
3055 for(i=0; i<= nbpix; i++){
3056 data[xa+i+cur_y*nx] = a*(xa+i)+b;
3057 }
3058 }
3059 ja=jb;
3060 jb=ja+1;
3061 }
3062 /* interpolate in Y direction */
3063
3064 xsh_msg("interpolate in Y ");
3065
3066 for( ja=0; ja< nbylines-1; ja++) {
3067 int line1 = ylines[ja];
3068 int line2 = ylines[ja+1];
3069
3070 for(i=0; i< nx; i++){
3071 double val1 = data[i+line1*nx];
3072 double val2 = data[i+line2*nx];
3073 double a = (val2-val1)/(line2-line1);
3074 double b = val1;
3075 int k;
3076
3077 for(k=line1+1; k < line2; k++){
3078 data[i+k*nx] = a*(k-line1)+b;
3079 }
3080 }
3081 }
3082
3083 cleanup:
3084 XSH_FREE( ylines);
3085 XSH_FREE( xline);
3086 XSH_FREE( vline);
3087 return;
3088}
3089
3090/*----------------------------------------------------------------------------*/
3099/*----------------------------------------------------------------------------*/
3100void
3102 cpl_vector * y,
3103 XSH_GAUSSIAN_FIT * result )
3104{
3107 XSH_ASSURE_NOT_NULL( result ) ;
3108
3109 cpl_vector_fit_gaussian( x, NULL, y, NULL, CPL_FIT_ALL, &result->peakpos,
3110 &result->sigma,
3111 &result->area, &result->offset, &result->mse,
3112 NULL, NULL ) ;
3113 cleanup:
3114 return ;
3115}
3116
3117/*----------------------------------------------------------------------------*/
3124/*----------------------------------------------------------------------------*/
3125int xsh_debug_level_set( int level )
3126{
3127 int prev = XshDebugLevel ;
3128
3129 XshDebugLevel = level ;
3130
3131 return prev ;
3132}
3133
3134/*----------------------------------------------------------------------------*/
3140/*----------------------------------------------------------------------------*/
3141int
3143{
3144 return XshDebugLevel ;
3145}
3146
3147/*----------------------------------------------------------------------------*/
3153/*----------------------------------------------------------------------------*/
3154const char *
3156{
3157 switch ( XshDebugLevel ) {
3159 return "none" ;
3161 return "low" ;
3163 return "medium" ;
3165 return "high" ;
3166 default:
3167 return "unknown" ;
3168 }
3169}
3170/*----------------------------------------------------------------------------*/
3177/*----------------------------------------------------------------------------*/
3178int
3180{
3181 int prev = XshTimeStamp ;
3182
3183 XshTimeStamp = ts ;
3184
3185 return prev ;
3186}
3187
3188/*----------------------------------------------------------------------------*/
3194/*----------------------------------------------------------------------------*/
3195int
3197{
3198 return XshTimeStamp ;
3199}
3200
3207void
3208xsh_mem_dump( const char * prompt)
3209{
3210 fprintf( stderr, "\n******** %s *******\n", prompt ) ;
3211 cpl_memory_dump() ;
3212}
3213
3214/* Binning functions */
3215/*---------------------------------------------------------------------------*/
3216/*
3217 @brief
3218 Convert binning positions into unbin positions
3219 @param bin_data
3220 The binning position
3221 @param binning
3222 The binning factor
3223 @return
3224 The no bin position
3225*/
3226/*---------------------------------------------------------------------------*/
3227double
3228convert_bin_to_data( double bin_data, int binning)
3229{
3230 return (bin_data*binning-0.5*(binning-1));
3231}
3232
3233/*---------------------------------------------------------------------------*/
3234/*
3235 @brief
3236 Convert unbin positions into binning positions
3237 @param data
3238 The no bin position
3239 @param binning
3240 The binning factor
3241 @return
3242 The binning position
3243*/
3244/*---------------------------------------------------------------------------*/
3245double
3246convert_data_to_bin( double data, int binning)
3247{
3248 return (data+0.5*(binning-1))/binning;
3249}
3250
3251/*
3252 Function to order a set of frames by DATE-OBS Keyword
3253*/
3254static double
3255date_to_double( const char * the_date )
3256{
3257 int yy, mm, dd, hh, min, sec, millis ;
3258 int date, temps ;
3259 double fdate = 0 ;
3260
3261
3262 XSH_ASSURE_NOT_NULL( the_date ) ;
3263
3264 sscanf( the_date, "%64d%*c%64d%*c%64d%*c%64d%*c%64d%*c%64d%*c%64d",
3265 &yy, &mm, &dd, &hh, &min, &sec, &millis ) ;
3266
3267 date = yy*10000 + mm*100 + dd ;
3268 temps = hh*10000000 + min*100000 + sec*1000 + millis ;
3269 fdate = (double)date + (double)temps/1000000000. ;
3270
3271 cleanup:
3272 return fdate ;
3273
3274}
3275
3276typedef struct {
3277 double frame_date ;
3279 cpl_frame * frame ;
3280 const char * frame_name ;
3282
3283static int
3284compare_frame_date( const void * one, const void * two )
3285{
3287 * scnd = (FRAME_DATE_IDX *)two ;
3288
3289 if ( first->frame_date > scnd->frame_date ) return 1 ;
3290 else if ( first->frame_date == scnd->frame_date ) return 0 ;
3291 else return -1 ;
3292}
3293
3294/******************************************************************************/
3295/******************************************************************************/
3296
3297/*----------------------------------------------------------------------------*/
3304/*----------------------------------------------------------------------------*/
3305cpl_frameset*
3306xsh_order_frameset_by_date( cpl_frameset *frameset)
3307{
3308 int nb, i ;
3309 FRAME_DATE_IDX *frame_date = NULL;
3310 cpl_frameset *result = NULL ;
3311 cpl_propertylist *header = NULL;
3312
3313 XSH_ASSURE_NOT_NULL( frameset);
3314
3315 check( nb = cpl_frameset_get_size( frameset));
3316 if ( nb <= 1 ) {
3317 check( result = cpl_frameset_duplicate( frameset));
3318 }
3319 else{
3320 XSH_CALLOC( frame_date, FRAME_DATE_IDX, nb);
3321
3322 /* Read all dates and convert into computable format */
3323 for( i = 0 ; i < nb ; i++){
3324 const char *fname = NULL ;
3325 cpl_frame *frame = NULL ;
3326 const char *the_date = NULL;
3327
3328 /* Get frame file name */
3329 check( frame = cpl_frameset_get_frame( frameset, i));
3330 check( fname = cpl_frame_get_filename( frame));
3331
3332 /* Load frame propertylist */
3333 check( header = cpl_propertylist_load( fname, 0));
3334 /* Get date as a string */
3335 check( the_date = xsh_pfits_get_date_obs( header));
3336 /* Convert and store */
3337 frame_date[i].frame_date = date_to_double( the_date);
3338 frame_date[i].frame_idx = i;
3339 frame_date[i].frame = frame;
3340 frame_date[i].frame_name = fname;
3341
3342 xsh_free_propertylist( &header);
3343 }
3344 /* Now order by date */
3345 qsort( frame_date, nb, sizeof( FRAME_DATE_IDX ), compare_frame_date ) ;
3346
3348 for( i = 0 ; i<nb ; i++ ) {
3349 xsh_msg( "%d: %.9lf '%s'", frame_date[i].frame_idx,
3350 frame_date[i].frame_date, frame_date[i].frame_name);
3351 }
3352 }
3353 /* Create the ordered frameset */
3354 check( result = cpl_frameset_new() ) ;
3355
3356 /* Populate the new frameset */
3357 for( i = 0 ; i <nb ; i++ ){
3358 check( cpl_frameset_insert( result,
3359 cpl_frame_duplicate(frame_date[i].frame)));
3360 }
3361 }
3362 cleanup:
3363 if ( cpl_error_get_code() != CPL_ERROR_NONE){
3364 xsh_free_frameset( &result);
3365 }
3366 xsh_free_propertylist( &header);
3367 XSH_FREE( frame_date);
3368 return result;
3369}
3370/******************************************************************************/
3371
3372/*----------------------------------------------------------------------------*/
3420/*----------------------------------------------------------------------------*/
3421
3422polynomial *
3423xsh_polynomial_regression_2d(cpl_table *t, const char *X1, const char *X2,
3424 const char *Y, const char *sigmaY, int degree1, int degree2,
3425 const char *polynomial_fit, const char *residual_square,
3426 const char *variance_fit, double *mse, double *red_chisq,
3427 polynomial **variance, double kappa, double min_reject) {
3428 int N;
3429 int rejected;
3430 int total_rejected;
3431 double *x1 = NULL;
3432 double *x2 = NULL;
3433 double *y = NULL;
3434 double *res = NULL;
3435 double *sy = NULL;
3436 polynomial *p = NULL; /* Result */
3437 polynomial *variance_local = NULL;
3438 cpl_vector *vx1 = NULL;
3439 cpl_vector *vx2 = NULL;
3440 cpl_bivector *vx = NULL;
3441 cpl_vector *vy = NULL;
3442 cpl_vector *vsy = NULL;
3443 cpl_type type;
3444
3445 /* Check input */
3446 assure( t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
3447 assure( cpl_table_has_column(t, X1), CPL_ERROR_ILLEGAL_INPUT,
3448 "No such column: %s", X1);
3449 assure( cpl_table_has_column(t, X2), CPL_ERROR_ILLEGAL_INPUT,
3450 "No such column: %s", X2);
3451 assure( cpl_table_has_column(t, Y), CPL_ERROR_ILLEGAL_INPUT,
3452 "No such column: %s", Y);
3453 assure( (variance == NULL && variance_fit == NULL) || sigmaY != NULL,
3454 CPL_ERROR_INCOMPATIBLE_INPUT,
3455 "Cannot calculate variances without sigmaY");
3456 if (sigmaY != NULL) {
3457 assure( cpl_table_has_column(t, sigmaY), CPL_ERROR_ILLEGAL_INPUT,
3458 "No such column: %s", sigmaY);
3459 }
3460 if (polynomial_fit != NULL) {
3461 assure( !cpl_table_has_column(t, polynomial_fit), CPL_ERROR_ILLEGAL_INPUT,
3462 "Table already has '%s' column", polynomial_fit);
3463 }
3464 if (residual_square != NULL) {
3465 assure( !cpl_table_has_column(t, residual_square), CPL_ERROR_ILLEGAL_INPUT,
3466 "Table already has '%s' column", residual_square);
3467 }
3468 if (variance_fit != NULL) {
3469 assure( !cpl_table_has_column(t, variance_fit), CPL_ERROR_ILLEGAL_INPUT,
3470 "Table already has '%s' column", variance_fit);
3471 }
3472
3473 /* Check column types */
3474 type = cpl_table_get_column_type(t, X1);
3475 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE,
3476 CPL_ERROR_INVALID_TYPE,
3477 "Input column '%s' has wrong type (%s)", X1, xsh_tostring_cpl_type(type));
3478 type = cpl_table_get_column_type(t, X2);
3479 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE,
3480 CPL_ERROR_INVALID_TYPE,
3481 "Input column '%s' has wrong type (%s)", X2, xsh_tostring_cpl_type(type));
3482 type = cpl_table_get_column_type(t, Y);
3483 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE,
3484 CPL_ERROR_INVALID_TYPE,
3485 "Input column '%s' has wrong type (%s)", Y, xsh_tostring_cpl_type(type));
3486 if (sigmaY != NULL) {
3487 type = cpl_table_get_column_type(t, sigmaY);
3488 assure(
3489 type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE,
3490 CPL_ERROR_INVALID_TYPE,
3491 "Input column '%s' has wrong type (%s)", sigmaY, xsh_tostring_cpl_type(type));
3492 }
3493
3494 /* In the case that these temporary columns already exist, a run-time error will occur */
3495 check_msg( cpl_table_cast_column(t, X1, "_X1_double", CPL_TYPE_DOUBLE),
3496 "Could not cast table column to double");
3497 check_msg( cpl_table_cast_column(t, X2, "_X2_double", CPL_TYPE_DOUBLE),
3498 "Could not cast table column to double");
3499 check_msg( cpl_table_cast_column(t, Y, "_Y_double", CPL_TYPE_DOUBLE),
3500 "Could not cast table column to double");
3501 if (sigmaY != NULL) {
3502 check_msg( cpl_table_cast_column(t, sigmaY, "_sY_double", CPL_TYPE_DOUBLE),
3503 "Could not cast table column to double");
3504 }
3505
3506 total_rejected = 0;
3507 rejected = 0;
3508 check_msg( cpl_table_new_column(t, "_residual_square", CPL_TYPE_DOUBLE),
3509 "Could not create column");
3510
3511 do {
3512 /* WARNING!!! Code duplication (see below). Be careful
3513 when updating */
3514 check_msg(
3515 ( N = cpl_table_get_nrow(t), x1 = cpl_table_get_data_double(t, "_X1_double"), x2 = cpl_table_get_data_double(t, "_X2_double"), y = cpl_table_get_data_double(t, "_Y_double"), res= cpl_table_get_data_double(t, "_residual_square")),
3516 "Could not read table data");
3517
3518 if (sigmaY != NULL) {
3519 check_msg(sy = cpl_table_get_data_double(t, "_sY_double"),
3520 "Could not read table data");
3521 } else {
3522 sy = NULL;
3523 }
3524
3525 assure( N > 0, CPL_ERROR_ILLEGAL_INPUT, "Empty table");
3526
3527 /* Wrap vectors */
3528 xsh_unwrap_vector(&vx1);
3529 xsh_unwrap_vector(&vx2);
3530 xsh_unwrap_vector(&vy);
3531
3532 vx1 = cpl_vector_wrap(N, x1);
3533 vx2 = cpl_vector_wrap(N, x2);
3534 vy = cpl_vector_wrap(N, y);
3535 if (sy != NULL) {
3536 xsh_unwrap_vector(&vsy);
3537 vsy = cpl_vector_wrap(N, sy);
3538 } else {
3539 vsy = NULL;
3540 }
3541
3542 /* Wrap up the bi-vector */
3544 vx = cpl_bivector_wrap_vectors(vx1, vx2);
3545
3546 /* Fit! */
3548 check_msg(
3549 p = xsh_polynomial_fit_2d(vx, vy, vsy, degree1, degree2, NULL, NULL, NULL),
3550 "Could not fit polynomial");
3551
3552 /* If requested, calculate residuals and perform kappa-sigma clipping */
3553 if (kappa > 0) {
3554 double sigma2; /* sigma squared */
3555 int i;
3556
3557 cpl_table_fill_column_window_double(t, "_residual_square", 0,
3558 cpl_table_get_nrow(t), 0.0);
3559
3560 for (i = 0; i < N; i++) {
3561 double yval, yfit;
3562
3563 yval = y[i];
3564 yfit = xsh_polynomial_evaluate_2d(p, x1[i], x2[i]);
3565 res[i] = (yfit - yval) * (yfit - yval);
3566 }
3567
3568 /* For robustness, estimate sigma as (third quartile) / 0.6744
3569 * (68% is within 1 sigma, 50% is within 3rd quartile, so sigma is > 3rd quartile)
3570 * The third quartile is estimated as the median of the absolute residuals,
3571 * so sigma ~= median(|residual|) / 0.6744 , i.e.
3572 * sigma^2 ~= median(residual^2) / 0.6744^2
3573 */
3574 sigma2 = cpl_table_get_column_median(t, "_residual_square")
3575 / (0.6744 * 0.6744);
3576
3577 /* Remove points with residual^2 > kappa^2 * sigma^2 */
3578 check_msg(
3579 rejected = xsh_erase_table_rows(t, "_residual_square", CPL_GREATER_THAN, kappa*kappa*sigma2),
3580 "Could not remove outlier points");
3581 /* Note! All pointers to table data are now invalid! */
3582
3584 "%d of %d points rejected in kappa-sigma clipping. rms=%f", rejected, N, sqrt(sigma2));
3585
3586 /* Update */
3587 total_rejected += rejected;
3588 N = cpl_table_get_nrow(t);
3589 }
3590
3591 /* Stop also if there are too few points left to make the fit.
3592 * Needed number of points = (degree1+1)(degree2+1) coefficients
3593 * plus one extra point for chi^2 computation. */
3594 } while (rejected > 0 && rejected > min_reject * (N + rejected)
3595 && N >= (degree1 + 1) * (degree2 + 1) + 1);
3596
3597 if (kappa > 0) {
3599 "%d of %d points (%f %%) rejected in kappa-sigma clipping", total_rejected, N + total_rejected, (100.0*total_rejected)/(N + total_rejected));
3600 }
3601
3602 /* Final fit */
3603 {
3604 /* Need to convert to vector again. */
3605
3606 /* WARNING!!! Code duplication (see above). Be careful
3607 when updating */
3608 check_msg(
3609 ( N = cpl_table_get_nrow(t), x1 = cpl_table_get_data_double(t, "_X1_double"), x2 = cpl_table_get_data_double(t, "_X2_double"), y = cpl_table_get_data_double(t, "_Y_double"), res= cpl_table_get_data_double(t, "_residual_square")),
3610 "Could not read table data");
3611
3612 if (sigmaY != NULL) {
3613 check_msg(sy = cpl_table_get_data_double(t, "_sY_double"),
3614 "Could not read table data");
3615 } else {
3616 sy = NULL;
3617 }
3618
3619 assure( N > 0, CPL_ERROR_ILLEGAL_INPUT, "Empty table");
3620
3621 /* Wrap vectors */
3622 xsh_unwrap_vector(&vx1);
3623 xsh_unwrap_vector(&vx2);
3624 xsh_unwrap_vector(&vy);
3625
3626 vx1 = cpl_vector_wrap(N, x1);
3627 vx2 = cpl_vector_wrap(N, x2);
3628 vy = cpl_vector_wrap(N, y);
3629 if (sy != NULL) {
3630 xsh_unwrap_vector(&vsy);
3631 vsy = cpl_vector_wrap(N, sy);
3632 } else {
3633 vsy = NULL;
3634 }
3635
3636 /* Wrap up the bi-vector */
3638 vx = cpl_bivector_wrap_vectors(vx1, vx2);
3639 }
3640
3642 if (variance_fit != NULL || variance != NULL) {
3643 /* If requested, also compute variance */
3644 check_msg(
3645 p = xsh_polynomial_fit_2d(vx, vy, vsy, degree1, degree2, mse, red_chisq, &variance_local),
3646 "Could not fit polynomial");
3647 } else {
3648 check_msg(
3649 p = xsh_polynomial_fit_2d(vx, vy, vsy, degree1, degree2, mse, red_chisq, NULL),
3650 "Could not fit polynomial");
3651 }
3652
3653 cpl_table_erase_column(t, "_residual_square");
3654
3655 /* Add the fitted values to table as requested */
3656 if (polynomial_fit != NULL || residual_square != NULL) {
3657 int i;
3658 double *pf;
3659
3660 check_msg( cpl_table_new_column(t, "_polynomial_fit", CPL_TYPE_DOUBLE),
3661 "Could not create column");
3662
3663 cpl_table_fill_column_window_double(t, "_polynomial_fit", 0,
3664 cpl_table_get_nrow(t), 0.0);
3665
3666 x1 = cpl_table_get_data_double(t, "_X1_double");
3667 x2 = cpl_table_get_data_double(t, "_X2_double");
3668 pf = cpl_table_get_data_double(t, "_polynomial_fit");
3669
3670 for (i = 0; i < N; i++) {
3671#if 0
3672 double x1val, x2val, yfit;
3673
3674 check_msg(( x1val = cpl_table_get_double(t, "_X1_double", i, NULL),
3675 x2val = cpl_table_get_double(t, "_X2_double", i, NULL),
3676 yfit = xsh_polynomial_evaluate_2d(p, x1val, x2val),
3677
3678 cpl_table_set_double(t, "_polynomial_fit", i, yfit)),
3679 "Could not evaluate polynomial");
3680
3681#else
3682 pf[i] = xsh_polynomial_evaluate_2d(p, x1[i], x2[i]);
3683#endif
3684 }
3685
3686 /* Add residual^2 = (Polynomial fit - Y)^2 if requested */
3687 if (residual_square != NULL) {
3688 check_msg(( cpl_table_duplicate_column(t, residual_square, /* RS := PF */
3689 t, "_polynomial_fit"), cpl_table_subtract_columns(t, residual_square, Y), /* RS := RS - Y */
3690 cpl_table_multiply_columns(t, residual_square, residual_square)),
3691 /* RS := RS^2 */
3692 "Could not calculate Residual of fit");
3693 }
3694
3695 /* Keep the polynomial_fit column if requested */
3696 if (polynomial_fit != NULL) {
3697 cpl_table_name_column(t, "_polynomial_fit", polynomial_fit);
3698 } else {
3699 cpl_table_erase_column(t, "_polynomial_fit");
3700 }
3701 }
3702
3703 /* Add variance of poly_fit if requested */
3704 if (variance_fit != NULL) {
3705 int i;
3706 double *vf;
3707
3708 check_msg( cpl_table_new_column(t, variance_fit, CPL_TYPE_DOUBLE),
3709 "Could not create column");
3710
3711 cpl_table_fill_column_window_double(t, variance_fit, 0,
3712 cpl_table_get_nrow(t), 0.0);
3713
3714 x1 = cpl_table_get_data_double(t, "_X1_double");
3715 x2 = cpl_table_get_data_double(t, "_X2_double");
3716 vf = cpl_table_get_data_double(t, variance_fit);
3717
3718 for (i = 0; i < N; i++) {
3719#if 0
3720 double x1val, x2val, yfit_variance;
3721 check_msg(( x1val = cpl_table_get_double(t, "_X1_double", i, NULL),
3722 x2val = cpl_table_get_double(t, "_X2_double", i, NULL),
3723 yfit_variance = xsh_polynomial_evaluate_2d(variance_local,
3724 x1val, x2val),
3725
3726 cpl_table_set_double(t, variance_fit, i, yfit_variance)),
3727 "Could not evaluate polynomial");
3728#else
3729 vf[i] = xsh_polynomial_evaluate_2d(variance_local, x1[i], x2[i]);
3730#endif
3731
3732 }
3733 }
3734
3735 check_msg(
3736 ( cpl_table_erase_column(t, "_X1_double"), cpl_table_erase_column(t, "_X2_double"), cpl_table_erase_column(t, "_Y_double")),
3737 "Could not delete temporary columns");
3738
3739 if (sigmaY != NULL) {
3740 check_msg( cpl_table_erase_column(t, "_sY_double"),
3741 "Could not delete temporary column");
3742 }
3743
3744 cleanup: xsh_unwrap_bivector_vectors(&vx);
3745 xsh_unwrap_vector(&vx1);
3746 xsh_unwrap_vector(&vx2);
3747 xsh_unwrap_vector(&vy);
3748 xsh_unwrap_vector(&vsy);
3749 /* Delete 'variance_local', or return through 'variance' parameter */
3750 if (variance != NULL) {
3751 *variance = variance_local;
3752 } else {
3753 xsh_polynomial_delete(&variance_local);
3754 }
3755 if (cpl_error_get_code() != CPL_ERROR_NONE) {
3757 }
3758
3759 return p;
3760}
3761
3762
3763
3764/*----------------------------------------------------------------------------*/
3781/*----------------------------------------------------------------------------*/
3782
3783int
3785 const char *column,
3786 cpl_table_select_operator operator,
3787 double value)
3788{
3789 int result = 0;
3790 cpl_type type;
3791
3792 assure( t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
3793 assure( cpl_table_has_column(t, column), CPL_ERROR_INCOMPATIBLE_INPUT,
3794 "No such column: %s", column);
3795
3796 type = cpl_table_get_column_type(t, column);
3797
3798 assure( type == CPL_TYPE_DOUBLE || type == CPL_TYPE_FLOAT ||
3799 type == CPL_TYPE_INT, CPL_ERROR_INVALID_TYPE,
3800 "Column '%s' must be double or int. %s found", column,
3801 xsh_tostring_cpl_type(type));
3802
3803 check_msg( cpl_table_select_all(t), "Error selecting rows");
3804
3805 if (type == CPL_TYPE_DOUBLE)
3806 {
3807 result = cpl_table_and_selected_double(t, column, operator, value);
3808 }
3809 else if (type == CPL_TYPE_FLOAT)
3810 {
3811 result = cpl_table_and_selected_float(t, column, operator, value);
3812 }
3813 else if (type == CPL_TYPE_INT)
3814 {
3815 result = cpl_table_and_selected_int(t, column, operator,
3816 xsh_round_double(value));
3817 }
3818 else { /*impossible*/ passure(false, ""); }
3819
3820 cleanup:
3821 return result;
3822
3823}
3824
3825
3826
3827
3828/*---------------------------------------------------------------------------*/
3847/*---------------------------------------------------------------------------*/
3848int
3850 const char *column,
3851 cpl_table_select_operator operator,
3852 double value)
3853{
3854 int result = 0;
3855
3856 assure( t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
3857 assure( cpl_table_has_column(t, column), CPL_ERROR_INCOMPATIBLE_INPUT,
3858 "No such column: %s", column);
3859
3860 check_msg( result = xsh_select_table_rows(t, column, operator, value),
3861 "Error selecting rows");
3862
3863 check_msg( cpl_table_erase_selected(t), "Error deleting rows");
3864
3865 cleanup:
3866 return result;
3867}
3868/*---------------------------------------------------------------------------*/
3877/*---------------------------------------------------------------------------*/
3878cpl_frame* xsh_frame_inv( cpl_frame* in, const char *filename,
3879 xsh_instrument* instr)
3880{
3881 xsh_pre *pre = NULL;
3882 cpl_frame *result = NULL;
3883 const char* tag = "INV_PRE";
3884
3886 XSH_ASSURE_NOT_NULL( instr);
3887
3888 check( pre = xsh_pre_load( in, instr));
3889 check( xsh_pre_multiply_scalar( pre, -1.0));
3890 check( result = xsh_pre_save( pre, filename, tag, 1));
3891 check( cpl_frame_set_tag( result, tag));
3892
3893 cleanup:
3894 if (cpl_error_get_code() != CPL_ERROR_NONE){
3895 xsh_free_frame( &result);
3896 }
3897 xsh_pre_free( &pre);
3898 return result;
3899}
3900/*---------------------------------------------------------------------------*/
3901
3902/*---------------------------------------------------------------------------*/
3910/*---------------------------------------------------------------------------*/
3911cpl_frame* xsh_frame_abs( cpl_frame* in, xsh_instrument* instr,
3912 cpl_frame** sign)
3913{
3914 xsh_pre *pre = NULL;
3915 cpl_frame *result = NULL;
3916 cpl_frame *sign_frame = NULL;
3917 char name[256];
3918 const char* tag = "ABS_PRE";
3919 const char* sign_tag = "SIGN_PRE";
3920 const char *filename = NULL;
3921 cpl_image *sign_img = NULL;
3922
3924 XSH_ASSURE_NOT_NULL( sign);
3925
3926 check( filename = cpl_frame_get_filename( in));
3927 check( pre = xsh_pre_load( in, instr));
3928 check( sign_img = xsh_pre_abs( pre));
3929 sprintf( name ,"ABS_%s", filename);
3930 check( result = xsh_pre_save( pre, name, tag, 1));
3931 check( cpl_frame_set_tag( result, tag));
3932 sprintf( name ,"SIGN_%s", filename);
3933 check( cpl_image_save( sign_img, name, CPL_BPP_32_SIGNED,
3934 NULL,CPL_IO_DEFAULT));
3936 check( sign_frame = cpl_frame_new());
3937 check( cpl_frame_set_filename( sign_frame, name));
3938 check( cpl_frame_set_tag( sign_frame, sign_tag));
3939 *sign = sign_frame;
3940
3941 cleanup:
3942 if (cpl_error_get_code() != CPL_ERROR_NONE){
3943 xsh_free_frame( &result);
3944 }
3945 xsh_free_image( &sign_img);
3946 xsh_pre_free( &pre);
3947 return result;
3948}
3949
3950
3951/*---------------------------------------------------------------------------*/
3958void
3959xsh_frame_spectrum_save(cpl_frame* frm,const char* name_o)
3960{
3961 xsh_spectrum* s=NULL;
3962 //const char* name=NULL;
3963 const char* tag=NULL;
3964 cpl_frame* loc_frm=NULL;
3965 //name=cpl_frame_get_filename(frm);
3966 s=xsh_spectrum_load(frm);
3967 loc_frm=xsh_spectrum_save(s,name_o,tag);
3968 cpl_frame_set_filename(frm,name_o);
3969
3971 xsh_free_frame(&loc_frm);
3972 return;
3973}
3974
3975/*---------------------------------------------------------------------------*/
3982void
3983xsh_frame_image_save(cpl_frame* frm,const char* name_o)
3984{
3985 cpl_image* ima=NULL;
3986 const char* name=NULL;
3987 int i=0;
3988 int next=cpl_frame_get_nextensions(frm);
3989 int type=CPL_TYPE_FLOAT;
3990 cpl_propertylist* plist=NULL;
3991 name=cpl_frame_get_filename(frm);
3992
3993 for(i=0;i<=next;i++) {
3994 ima=cpl_image_load(name,CPL_TYPE_UNSPECIFIED,0,i);
3995 type = cpl_image_get_type(ima);
3996 plist=cpl_propertylist_load(name,i);
3997 if(i==0) {
3998 cpl_image_save(ima,name_o,type,plist,CPL_IO_DEFAULT);
3999 } else{
4000 cpl_image_save(ima,name_o,type,plist,CPL_IO_EXTEND);
4001 }
4002 xsh_free_image(&ima);
4003 xsh_free_propertylist(&plist);
4004 }
4005
4006 return;
4007}
4008
4009
4016void
4017xsh_frame_table_save(cpl_frame* frame,const char* name_o)
4018{
4019 const char* fname=NULL;
4020
4021 int nbext=0;
4022 int extension ;
4023 cpl_table *tbl_ext = NULL;
4024 cpl_propertylist *tbl_ext_header = NULL;
4025 cpl_propertylist *primary_header = NULL;
4026 int i=0;
4027
4028 fname=cpl_frame_get_filename(frame);
4029 nbext = cpl_frame_get_nextensions( frame);
4030
4031 for( i = 0 ; i<nbext ; i++ ) {
4032
4033 check( tbl_ext = cpl_table_load( fname, i+1, 0));
4034 check( tbl_ext_header = cpl_propertylist_load( fname, i+1));
4035
4036 if ( i == 0 ) extension = CPL_IO_DEFAULT ;
4037 else extension = CPL_IO_EXTEND ;
4038 check(cpl_table_save( tbl_ext, primary_header, tbl_ext_header,
4039 name_o, extension));
4040 xsh_free_table( &tbl_ext);
4041 xsh_free_propertylist( &tbl_ext_header);
4042
4043 }
4044
4045 cleanup:
4046 xsh_free_table( &tbl_ext);
4047 xsh_free_propertylist( &tbl_ext_header);
4048
4049 return;
4050}
4051/*---------------------------------------------------------------------------*/
4060/*---------------------------------------------------------------------------*/
4061cpl_frame* xsh_frame_mult( cpl_frame* in, xsh_instrument* instr,
4062 cpl_frame* sign)
4063{
4064 xsh_pre *pre = NULL;
4065 cpl_frame *result = NULL;
4066 cpl_image *sign_img = NULL;
4067 const char* name = NULL;
4068 const char* tag = "MULT_IMG_PRE";
4069
4071 XSH_ASSURE_NOT_NULL( sign);
4072
4073 check( name = cpl_frame_get_filename( sign));
4074 check( pre = xsh_pre_load( in, instr));
4075 check( sign_img = cpl_image_load( name, CPL_TYPE_INT, 0, 0));
4076 check( xsh_pre_multiply_image( pre, sign_img));
4077 check( result = xsh_pre_save( pre, "RESTORE_PRE.fits", tag, 1));
4078 check( cpl_frame_set_tag( result, tag));
4079
4080 cleanup:
4081 if (cpl_error_get_code() != CPL_ERROR_NONE){
4082 xsh_free_frame( &result);
4083 }
4084 xsh_free_image( &sign_img);
4085 xsh_pre_free( &pre);
4086 return result;
4087}
4088
4089/*---------------------------------------------------------------------------*/
4103/*---------------------------------------------------------------------------*/
4104
4105
4106cpl_error_code
4107xsh_monitor_flux(cpl_frame* frm_ima,const cpl_frame* frm_tab,
4108 xsh_instrument *instrument, const char* qc_key_prefix)
4109{
4110
4111 int ord_min=0;
4112 int ord_max=0;
4113 int i=0;
4114 const char* name_ima=NULL;
4115 const char* name_tab=NULL;
4116 cpl_table* tab=NULL;
4117 cpl_image* ima=NULL;
4118 cpl_image* qua=NULL;
4119 cpl_table* ext=NULL;
4120 int next=0;
4121 double* cx=NULL;
4122 double* cy=NULL;
4123 int ix=0;
4124 int iy=0;
4125 double flux_min_init=FLT_MAX;
4126 double flux_max_init=-FLT_MAX;
4127
4128 double flux_min_ord=flux_min_init;
4129 double flux_max_ord=flux_max_init;
4130
4131 double flux_min=flux_min_init;
4132 double flux_max=flux_max_init;
4133 double* pima=NULL;
4134 int* pqua=NULL;
4135 double flux=0;
4136 int qual=0;
4137 cpl_propertylist* plist=NULL;
4138 char qc_flux_min[40];
4139 char qc_flux_max[40];
4140 int sx=0;
4141 int sy=0;
4142 int j=0;
4143 int binx=1;
4144 int biny=1;
4145 int decode_bp=instrument->decode_bp;
4146 cpl_ensure_code(frm_ima != NULL, CPL_ERROR_NULL_INPUT);
4147 cpl_ensure_code(frm_tab != NULL, CPL_ERROR_NULL_INPUT);
4148 xsh_msg("monitor flux");
4149 check(name_ima=cpl_frame_get_filename(frm_ima));
4150 check(name_tab=cpl_frame_get_filename(frm_tab));
4151
4152 check(plist=cpl_propertylist_load(name_ima,0));
4153
4155 binx=xsh_pfits_get_binx(plist);
4156 biny=xsh_pfits_get_biny(plist);
4157 }
4158 check(tab=cpl_table_load(name_tab,2,0));
4159 check(ima=cpl_image_load(name_ima,CPL_TYPE_DOUBLE,0,0));
4160 check(qua=cpl_image_load(name_ima,CPL_TYPE_INT,0,2));
4161 check(sx=cpl_image_get_size_x(ima));
4162 check(sy=cpl_image_get_size_y(ima));
4163 //xsh_msg("image=%s",name_ima);
4164 //xsh_msg("sx=%d sy=%d binx=%d biny=%d",sx,sy,binx,biny);
4165 //check(cpl_image_save(ima,"pippo.fits",CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT));
4166
4167 check(pima=cpl_image_get_data_double(ima));
4168 check(pqua=cpl_image_get_data_int(qua));
4169 check(ord_min=cpl_table_get_column_min(tab,"ABSORDER"));
4170 check(ord_max=cpl_table_get_column_max(tab,"ABSORDER"));
4171 //xsh_msg("ord_min=%d ord_max=%d",ord_min,ord_max);
4172
4173 for(i=ord_min;i<=ord_max;i++) {
4174 flux_min_ord=flux_min_init;
4175 flux_max_ord=flux_max_init;
4176
4177 check(next=cpl_table_and_selected_int(tab,"ABSORDER",CPL_EQUAL_TO,i));
4178 ext=cpl_table_extract_selected(tab);
4179 cx=cpl_table_get_data_double(ext,"CENTER_X");
4180 cy=cpl_table_get_data_double(ext,"CENTER_Y");
4181
4182 for(j=0;j<next;j++) {
4183
4184 ix=(int)(cx[j]/binx+0.5);
4185 iy=(int)(cy[j]/biny+0.5);
4186
4187 if( ( (ix>=0) && (ix<sx) ) &&
4188 ( (iy>=0) && (iy<sy) ) ) {
4189 check(flux=pima[ix+sx*iy]);
4190 check(qual=pqua[ix+sx*iy]);
4191 if(!isnan(flux) && ((qual & decode_bp)==0)) {
4192 if(flux<flux_min_ord) {
4193 flux_min_ord=flux;
4194 continue;
4195 }
4196 if(flux>flux_max_ord) {
4197 flux_max_ord=flux;
4198 }
4199
4200 }
4201 }
4202
4203
4204 }
4205 xsh_free_table(&ext);
4206 cpl_table_select_all(tab);
4207
4208 if(next>1) {
4209 flux_min=(flux_min_ord<flux_min)? flux_min_ord:flux_min;
4210 flux_max=(flux_max_ord>flux_max)? flux_max_ord:flux_max;
4211 }
4212
4213 sprintf(qc_flux_min,"%s%d%s",qc_key_prefix,i," MIN");
4214 sprintf(qc_flux_max,"%s%d%s",qc_key_prefix,i," MAX");
4215
4216 //xsh_msg("order=%d next=%d flux_min=%g flux_max=%g",i,next,flux_min_ord,flux_max_ord);
4217 cpl_propertylist_append_double(plist,qc_flux_min,flux_min_ord);
4218 cpl_propertylist_set_comment(plist,qc_flux_min,XSH_QC_FLUX_MIN_C);
4219 cpl_propertylist_append_double(plist,qc_flux_max,flux_max_ord);
4220 cpl_propertylist_set_comment(plist,qc_flux_max,XSH_QC_FLUX_MAX_C);
4221 }
4222
4223 sprintf(qc_flux_min,"%s%s",qc_key_prefix," MIN");
4224 sprintf(qc_flux_max,"%s%s",qc_key_prefix," MAX");
4225 cpl_propertylist_append_double(plist,qc_flux_min,flux_min);
4226 cpl_propertylist_set_comment(plist,qc_flux_min,XSH_QC_FLUX_MIN_C);
4227 cpl_propertylist_append_double(plist,qc_flux_max,flux_max);
4228 cpl_propertylist_set_comment(plist,qc_flux_max,XSH_QC_FLUX_MAX_C);
4230
4231 cleanup:
4232 xsh_free_table(&ext);
4233 xsh_free_image(&ima);
4234 xsh_free_image(&qua);
4235 xsh_free_table(&tab);
4236 xsh_free_propertylist(&plist);
4237
4238
4239 return cpl_error_get_code();
4240
4241}
4242
4243/*---------------------------------------------------------------------------*/
4255/*---------------------------------------------------------------------------*/
4256
4257cpl_error_code
4259 const cpl_propertylist* pheader)
4260{
4261 const char *fname = NULL;
4262 int nbext=0;
4263 int i=0;
4264 cpl_image *image = NULL ;
4265 char cmd[256];
4266 int extension=0 ;
4267 cpl_image* ext_img=NULL;
4268 cpl_propertylist* ext_header=NULL;
4269
4270 XSH_ASSURE_NOT_NULL(frame);
4271 nbext = cpl_frame_get_nextensions( frame);
4272 xsh_msg_dbg_medium("nbext=%d",nbext);
4273 check( fname = cpl_frame_get_filename( frame));
4274 check( image = cpl_image_load( fname, CPL_TYPE_FLOAT, 0, 0));
4275
4276
4277 //xsh_plist_dump(pheader);
4278
4279 cpl_image_save(image, "tmp.fits", CPL_BPP_IEEE_FLOAT, pheader,
4280 CPL_IO_DEFAULT ) ;
4281 xsh_free_image(&image);
4282 xsh_msg_dbg_medium("fname=%s",fname);
4283 for( i = 1 ; i<=nbext ; i++ ) {
4284
4285 check( ext_img = cpl_image_load( fname, CPL_TYPE_FLOAT,0, i));
4286 check( ext_header = cpl_propertylist_load( fname ,i));
4287
4288 if ( i == 0 ) {
4289 extension = CPL_IO_DEFAULT ;
4290 }
4291 else {
4292 extension = CPL_IO_EXTEND ;
4293 check(cpl_image_save( ext_img, "tmp.fits", CPL_BPP_IEEE_FLOAT,ext_header,
4294 extension));
4295 }
4296 xsh_free_image( &ext_img) ;
4297 xsh_free_propertylist( &ext_header) ;
4298 }
4299
4300 sprintf(cmd,"mv tmp.fits %s",fname);
4301 system(cmd);
4302 system("rm -f tmp.fits");
4303
4304
4305 cleanup:
4306 xsh_free_image( &ext_img) ;
4307 xsh_free_propertylist( &ext_header) ;
4308 xsh_free_image(&image);
4309
4310 return cpl_error_get_code();
4311}
4312
4318/*---------------------------------------------------------------------------*/
4319double xsh_vector_get_err_median( cpl_vector *vect)
4320{
4321 double err_median =0.0;
4322 int i, vect_size =0;
4323 double *data = NULL;
4324
4325 XSH_ASSURE_NOT_NULL( vect);
4326
4327 check( vect_size = cpl_vector_get_size( vect));
4328 check( data = cpl_vector_get_data( vect));
4329
4330 if (vect_size > 1){
4331 for( i=0; i< vect_size; i++){
4332 err_median += data[i]*data[i];
4333 }
4334
4335 err_median = sqrt( M_PI / 2.0 *
4336 ((double) vect_size / ((double) vect_size- 1.))) *
4337 (1./(double)vect_size) * sqrt (err_median);
4338 }
4339 else{
4340 err_median = data[0];
4341 }
4342
4343 cleanup:
4344 return err_median;
4345}
4346/*---------------------------------------------------------------------------*/
4353/*---------------------------------------------------------------------------*/
4354double xsh_vector_get_err_mean( cpl_vector *vect)
4355{
4356 double err_mean =0.0;
4357 int i, vect_size =0;
4358 double *data = NULL;
4359
4360 XSH_ASSURE_NOT_NULL( vect);
4361
4362 check( vect_size = cpl_vector_get_size( vect));
4363 check( data = cpl_vector_get_data( vect));
4364
4365 for( i=0; i< vect_size; i++){
4366 err_mean += data[i]*data[i];
4367 }
4368 err_mean = sqrt( err_mean)/(double)vect_size;
4369
4370 cleanup:
4371 return err_mean;
4372}
4373/*---------------------------------------------------------------------------*/
4374
4375
4376/*--------------------------------------------------------------------------*/
4382/*--------------------------------------------------------------------------*/
4384{
4385 return (x >=0) ? (long)(x+0.5) : (long)(x-0.5);
4386}
4387
4388/*---------------------------------------------------------------------------*/
4397/*---------------------------------------------------------------------------*/
4398inline int
4399xsh_min_int(int x, int y)
4400{
4401 return (x <=y) ? x : y;
4402}
4403
4404/*---------------------------------------------------------------------------*/
4413/*---------------------------------------------------------------------------*/
4414inline int
4415xsh_max_int(int x, int y)
4416{
4417 return (x >= y) ? x : y;
4418}
4419
4420
4421/*---------------------------------------------------------------------------*/
4430/*---------------------------------------------------------------------------*/
4431inline double
4432xsh_min_double(double x, double y)
4433{
4434 return (x <=y) ? x : y;
4435}
4436
4437
4438/*---------------------------------------------------------------------------*/
4447/*---------------------------------------------------------------------------*/
4448inline double
4449xsh_max_double(double x, double y)
4450{
4451 return (x >=y) ? x : y;
4452}
4453
4454
4455/*--------------------------------------------------------------------------*/
4462/*--------------------------------------------------------------------------*/
4463double xsh_pow_int(double x, int y)
4464{
4465 double result = 1.0;
4466
4467 /* Invariant is: result * x ^ y */
4468 while(y != 0)
4469 {
4470 if (y % 2 == 0)
4471 {
4472 x *= x;
4473 y /= 2;
4474 }
4475 else
4476 {
4477 if (y > 0)
4478 {
4479 result *= x;
4480 y -= 1;
4481 }
4482 else
4483 {
4484 result /= x;
4485 y += 1;
4486 }
4487 }
4488 }
4489 return result;
4490}
4491
4507const char*
4509{
4510
4511 char *t = s;
4512
4513 assert(s != NULL);
4514
4515 while (*t) {
4516 *t = tolower(*t);
4517 t++;
4518 }
4519
4520 return s;
4521
4522}
4523
4524
4541const char*
4543{
4544
4545 char *t = s;
4546
4547 assert(s != NULL);
4548
4549 while (*t) {
4550 *t = toupper(*t);
4551 t++;
4552 }
4553
4554 return s;
4555
4556}
4557
4558
4559/*----------------------------------------------------------------------------*/
4575/*----------------------------------------------------------------------------*/
4576double
4577xsh_spline_hermite( double xp, const double *x, const double *y, int n, int *istart )
4578{
4579 double yp1, yp2, yp = 0;
4580 double xpi, xpi1, l1, l2, lp1, lp2;
4581 int i;
4582
4583 if ( x[0] <= x[n-1] && (xp < x[0] || xp > x[n-1]) ) return 0.0;
4584 if ( x[0] > x[n-1] && (xp > x[0] || xp < x[n-1]) ) return 0.0;
4585
4586 if ( x[0] <= x[n-1] )
4587 {
4588 for ( i = (*istart)+1; i <= n && xp >= x[i-1]; i++ )
4589 ;
4590 }
4591 else
4592 {
4593 for ( i = (*istart)+1; i <= n && xp <= x[i-1]; i++ )
4594 ;
4595 }
4596
4597 *istart = i;
4598 i--;
4599
4600 lp1 = 1.0 / (x[i-1] - x[i]);
4601 lp2 = -lp1;
4602
4603 if ( i == 1 )
4604 {
4605 yp1 = (y[1] - y[0]) / (x[1] - x[0]);
4606 }
4607 else
4608 {
4609 yp1 = (y[i] - y[i-2]) / (x[i] - x[i-2]);
4610 }
4611
4612 if ( i >= n - 1 )
4613 {
4614 yp2 = (y[n-1] - y[n-2]) / (x[n-1] - x[n-2]);
4615 }
4616 else
4617 {
4618 yp2 = (y[i+1] - y[i-1]) / (x[i+1] - x[i-1]);
4619 }
4620
4621 xpi1 = xp - x[i];
4622 xpi = xp - x[i-1];
4623 l1 = xpi1*lp1;
4624 l2 = xpi*lp2;
4625
4626 yp = y[i-1]*(1 - 2.0*lp1*xpi)*l1*l1 +
4627 y[i]*(1 - 2.0*lp2*xpi1)*l2*l2 +
4628 yp1*xpi*l1*l1 + yp2*xpi1*l2*l2;
4629
4630 return yp;
4631}
4632
4633
4634/*----------------------------------------------------------------------------*/
4645/*----------------------------------------------------------------------------*/
4646
4647double
4648xsh_spline_hermite_table( double xp, const cpl_table *t, const char *column_x,
4649 const char *column_y, int *istart )
4650{
4651 double result = 0;
4652 int n;
4653
4654 const double *x, *y;
4655
4656 check_msg( x = cpl_table_get_data_double_const(t, column_x),
4657 "Error reading column '%s'", column_x);
4658 check_msg( y = cpl_table_get_data_double_const(t, column_y),
4659 "Error reading column '%s'", column_y);
4660
4661 n = cpl_table_get_nrow(t);
4662
4663 result = xsh_spline_hermite(xp, x, y, n, istart);
4664
4665 cleanup:
4666 return result;
4667}
4668
4669
4670
4679cpl_vector *
4680xsh_image_to_vector( cpl_image * spectrum )
4681{
4682 cpl_vector * result =NULL;
4683 cpl_type type=CPL_TYPE_FLOAT;
4684
4685 int i =0;
4686 int ilx=0;
4687 int ily=0;
4688
4689 int* pi=NULL;
4690 float* pf=NULL;
4691 double* pd=NULL;
4692 double* pv=NULL;
4693
4694 int size=0;
4695
4696
4697 XSH_ASSURE_NOT_NULL_MSG(spectrum,"NULL input spectrum (1D) image!Exit.");
4698 ilx=cpl_image_get_size_x(spectrum);
4699 ily=cpl_image_get_size_y(spectrum);
4700 size=ilx*ily;
4701
4702 result=cpl_vector_new(size);
4703 pv=cpl_vector_get_data(result);
4704
4705 switch(type) {
4706
4707 case CPL_TYPE_INT:
4708 pi=cpl_image_get_data_int(spectrum);
4709 for ( i = 0 ; i < size ; i++ ) pv[i] = (double) pi[i] ;
4710 break;
4711
4712 case CPL_TYPE_FLOAT:
4713 pf=cpl_image_get_data_float(spectrum);
4714 for ( i = 0 ; i < size ; i++ ) pv[i] = (double) pf[i] ;
4715 break;
4716
4717 case CPL_TYPE_DOUBLE:
4718 pd=cpl_image_get_data_double(spectrum);
4719 for ( i = 0 ; i < size ; i++ ) pv[i] = (double) pd[i] ;
4720 break;
4721
4722 default:
4723 xsh_msg_error("Wrong input image data type %d",type);
4724 }
4725
4726 cleanup:
4727
4728 return result ;
4729}
4730
4731
4732/*----------------------------------------------------------------------------*/
4742/*----------------------------------------------------------------------------*/
4743
4744cpl_image*
4745xsh_vector_to_image(const cpl_vector* vector,cpl_type type)
4746{
4747 int i=0;
4748 cpl_image* image=NULL;
4749 int size=0;
4750 const double* pv=NULL;
4751 int* pi=NULL;
4752 float* pf=NULL;
4753 double* pd=NULL;
4754
4755
4756 size=cpl_vector_get_size(vector);
4757 image=cpl_image_new(size,1,type);
4758 pv=cpl_vector_get_data_const(vector);
4759 if(type == CPL_TYPE_INT) {
4760 pi=cpl_image_get_data_int(image);
4761 for(i=0;i<size;i++) {
4762 pi[i]=pv[i];
4763 }
4764 } else if (type == CPL_TYPE_FLOAT) {
4765 pf=cpl_image_get_data_float(image);
4766 for(i=0;i<size;i++) {
4767 pf[i]=pv[i];
4768 }
4769 } else if (type == CPL_TYPE_DOUBLE) {
4770 pd=cpl_image_get_data_double(image);
4771 for(i=0;i<size;i++) {
4772 pd[i]=pv[i];
4773 }
4774 } else {
4775 assure( false, CPL_ERROR_INVALID_TYPE,
4776 "No CPL type to represent BITPIX = %d", type);
4777 }
4778
4779 cleanup:
4780 if (cpl_error_get_code() != CPL_ERROR_NONE){
4781 xsh_free_image(&image);
4782 }
4783
4784 return image;
4785
4786}
4787
4788/*--------------------------------------------------------------------------*/
4796/*--------------------------------------------------------------------------*/
4797cpl_frame*
4798xsh_util_multiply_by_response(cpl_frame* merged_sci, cpl_frame* response,
4799 const char* tag_o)
4800{
4801 cpl_frame* result=NULL;
4802 cpl_image* data_sci=NULL;
4803 cpl_image* errs_sci=NULL;
4804 cpl_image* qual_sci=NULL;
4805
4806 cpl_image* data_tmp=NULL;
4807 cpl_image* errs_tmp=NULL;
4808
4809 cpl_vector* data_vec=NULL;
4810 cpl_vector* errs_vec=NULL;
4811 cpl_vector* qual_vec=NULL;
4812
4813 cpl_propertylist* hdat=NULL;
4814 cpl_propertylist* herr=NULL;
4815 cpl_propertylist* hqua=NULL;
4816 cpl_propertylist* plist=NULL;
4817
4818 cpl_table* response_table=NULL;
4819
4820 const char* name_s=NULL;
4821 //const char* tag_s=NULL;
4822 const char* name_r=NULL;
4823
4824 char* name_o=NULL;
4825 double lambda_start=0;
4826 double lambda_step=0;
4827 int bin=0;
4828 int naxis=0;
4829 int nbins = 0;
4830 int ntraces = 0;
4831
4832 double *fluxcal_science_data = NULL;
4833 double *fluxcal_science_noise = NULL;
4834
4835 XSH_ASSURE_NOT_NULL_MSG(merged_sci,"NULL input merged frame!Exit.");
4836 XSH_ASSURE_NOT_NULL_MSG(response,"NULL input response frame!Exit.");
4837
4838 check(name_s=cpl_frame_get_filename(merged_sci));
4839 //check(tag_s=cpl_frame_get_tag(merged_sci));
4840 name_o=cpl_sprintf("%s.fits",tag_o);
4841
4842 check(hdat=cpl_propertylist_load(name_s,0));
4843 check(herr=cpl_propertylist_load(name_s,1));
4844 check(hqua=cpl_propertylist_load(name_s,2));
4845
4846 naxis=xsh_pfits_get_naxis(hdat);
4847
4848 if(naxis == 1) {
4849
4850 check(data_vec=cpl_vector_load(name_s,0));
4851 check(errs_vec=cpl_vector_load(name_s,1));
4852
4853 check(data_sci=xsh_vector_to_image(data_vec,XSH_PRE_DATA_TYPE));
4854 check(errs_sci=xsh_vector_to_image(errs_vec,XSH_PRE_ERRS_TYPE));
4855
4856 xsh_free_vector(&data_vec);
4857 xsh_free_vector(&errs_vec);
4858
4859 } else {
4860
4861 check(data_sci=cpl_image_load(name_s,XSH_PRE_DATA_TYPE,0,0));
4862 check(errs_sci=cpl_image_load(name_s,XSH_PRE_ERRS_TYPE,0,1));
4863 check(qual_sci=cpl_image_load(name_s,XSH_PRE_QUAL_TYPE,0,2));
4864
4865 }
4866
4867 data_tmp=cpl_image_cast(data_sci,CPL_TYPE_DOUBLE);
4868 errs_tmp=cpl_image_cast(errs_sci,CPL_TYPE_DOUBLE);
4869 xsh_free_image(&data_sci);
4870 xsh_free_image(&errs_sci);
4871
4872 check(name_r=cpl_frame_get_filename(response));
4873 check(response_table=cpl_table_load(name_r,1,0));
4874
4875/* in case the input response was obtained on a binned frame we need
4876 to correct it to un-binned data. We get biny that corresponds to
4877 the bin along wave dispersion direction
4878 plist=cpl_propertylist_load(name_r,0);
4879 binx=xsh_pfits_get_biny(plist);
4880 cpl_table_multiply_scalar(response_table,"FLUX",binx);
4881 xsh_free_propertylist(&plist);
4882*/
4883
4884 /*
4885 * Flux calibrate reduced spectrum
4886 * flux := flux * response
4887 */
4888 xsh_msg("Multiply by response function");
4889
4890 check(nbins = cpl_image_get_size_x(data_tmp));
4891 check(ntraces = cpl_image_get_size_y(data_tmp));
4892
4893 check(fluxcal_science_data = cpl_image_get_data_double(data_tmp));
4894 check(fluxcal_science_noise = cpl_image_get_data_double(errs_tmp));
4895
4896 check_msg( lambda_start = xsh_pfits_get_crval1(hdat),
4897 "Error reading start wavelength from reduced science header");
4899 "Error reading bin width from header");
4900
4901 check(cpl_table_cast_column(response_table,"LAMBDA","DLAMBDA",CPL_TYPE_DOUBLE));
4902 check(cpl_table_cast_column(response_table,"FLUX","DFLUX",CPL_TYPE_DOUBLE));
4903
4904 for (bin = 1; bin <= nbins; bin++)
4905 {
4906 double lambda;
4907 double response;
4908 int trace; /* Spatial traces (for 2d extracted spectra) */
4909 int istart = 0;
4910
4911 lambda = lambda_start + (bin-1) * lambda_step;
4912 check_msg( response =
4913 xsh_spline_hermite_table(lambda, response_table,
4914 "DLAMBDA", "DFLUX", &istart),
4915 "Error interpolating response curve at lambda = %f wlu", lambda);
4916
4917 xsh_msg_dbg_medium("response=%g",response);
4918
4919 for (trace = 1; trace <= ntraces; trace++)
4920 {
4921 /* Don't check for bad pixels here, also correct those.
4922 * The fluxcal image has the same bad pixels as the reduced_science
4923 * image */
4924
4925 fluxcal_science_data [(bin-1) + (trace-1)*nbins] *= response;
4926 /* the following gives problems on some XSH data */
4927 fluxcal_science_noise[(bin-1) + (trace-1)*nbins] *= fabs(response);
4928 /* Do not propagate the error of the response
4929 curve which is negligibly small (and unknown at this point!).
4930 */
4931 }
4932 }
4933
4934 data_sci=cpl_image_cast(data_tmp,XSH_PRE_DATA_TYPE);
4935 errs_sci=cpl_image_cast(errs_tmp,XSH_PRE_ERRS_TYPE);
4936 xsh_free_image(&data_tmp);
4937 xsh_free_image(&errs_tmp);
4938
4939 cpl_table_erase_column(response_table,"DLAMBDA");
4940 cpl_table_erase_column(response_table,"DFLUX");
4941 check( xsh_pfits_set_pcatg( hdat, tag_o));
4942 xsh_pfits_set_extname( hdat, "FLUX");
4943
4945 check(xsh_plist_set_extra_keys(hdat,"IMAGE","DATA","RMSE",
4946 "FLUX","ERRS","QUAL",0));
4947
4949 xsh_pfits_set_extname( herr, "ERRS");
4950 check(xsh_plist_set_extra_keys(herr,"IMAGE","DATA","RMSE",
4951 "FLUX","ERRS","QUAL",1));
4952
4953
4954 xsh_pfits_set_extname( hqua, "QUAL");
4955 check(xsh_plist_set_extra_keys(hqua,"IMAGE","DATA","RMSE",
4956 "FLUX","ERRS","QUAL",2));
4957
4958
4959
4960 if(naxis==1) {
4961 check(data_vec=xsh_image_to_vector(data_sci));
4962 check(errs_vec=xsh_image_to_vector(errs_sci));
4963
4965 check(cpl_vector_save(data_vec,name_o,XSH_SPECTRUM_DATA_BPP,hdat,CPL_IO_DEFAULT));
4967 check(cpl_vector_save(errs_vec,name_o,XSH_SPECTRUM_ERRS_BPP,herr,CPL_IO_EXTEND));
4968 check(qual_vec=cpl_vector_load(name_s,2));
4969 check(cpl_vector_save(errs_vec,name_o,XSH_SPECTRUM_ERRS_BPP,hqua,CPL_IO_EXTEND));
4970
4971
4972 } else {
4974 check(cpl_image_save(data_sci,name_o,XSH_PRE_DATA_BPP,hdat,CPL_IO_DEFAULT));
4976 check(cpl_image_save(errs_sci,name_o,XSH_PRE_ERRS_BPP,herr,CPL_IO_EXTEND));
4977 check(cpl_image_save(qual_sci,name_o,XSH_PRE_QUAL_BPP,hqua,CPL_IO_EXTEND));
4978 }
4979 /* the qual ext is treated separately: we duplicate it to product */
4980
4981 result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_IMAGE,CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
4982
4983 cleanup:
4984
4985 cpl_free(name_o);
4986
4987 xsh_free_image(&data_sci);
4988 xsh_free_image(&errs_sci);
4989 xsh_free_image(&qual_sci);
4990 xsh_free_image(&data_sci);
4991 xsh_free_image(&errs_sci);
4992
4993 xsh_free_vector(&data_vec);
4994 xsh_free_vector(&errs_vec);
4995 xsh_free_vector(&qual_vec);
4996
4997 xsh_free_table(&response_table);
4998 xsh_free_propertylist(&hdat);
4999 xsh_free_propertylist(&herr);
5000 xsh_free_propertylist(&hqua);
5001 xsh_free_propertylist(&plist);
5002
5003 return result;
5004}
5005
5006/*--------------------------------------------------------------------------*/
5014/*--------------------------------------------------------------------------*/
5015cpl_frame*
5016xsh_util_multiply_by_response_ord(cpl_frame* extracted_sci, cpl_frame* response,
5017 const char* tag_o)
5018{
5019 cpl_frame* result=NULL;
5020 cpl_image* data_sci=NULL;
5021 cpl_image* errs_sci=NULL;
5022 cpl_image* qual_sci=NULL;
5023
5024 cpl_image* data_tmp=NULL;
5025 cpl_image* errs_tmp=NULL;
5026
5027 cpl_vector* data_vec=NULL;
5028 cpl_vector* errs_vec=NULL;
5029 cpl_vector* qual_vec=NULL;
5030
5031 cpl_propertylist* hdat=NULL;
5032 cpl_propertylist* herr=NULL;
5033 cpl_propertylist* hqua=NULL;
5034 cpl_propertylist* plist=NULL;
5035
5036 cpl_table* response_table=NULL;
5037
5038 const char* name_s=NULL;
5039 //const char* tag_s=NULL;
5040 const char* name_r=NULL;
5041 char* name_o=NULL;
5042 double lambda_start=0;
5043 double lambda_step=0;
5044 int bin=0;
5045 int naxis=0;
5046
5047 int nbins = 0;
5048 int ntraces = 0;
5049
5050 int next_sci = 0;
5051 int next_res = 0;
5052 int ext = 0;
5053 int order=0;
5054
5055 double *fluxcal_science_data = NULL;
5056 double *fluxcal_science_noise = NULL;
5057
5058 XSH_ASSURE_NOT_NULL_MSG(extracted_sci,"NULL input extracted frame!Exit.");
5059 XSH_ASSURE_NOT_NULL_MSG(response,"NULL input response frame!Exit.");
5060
5061 check(name_s=cpl_frame_get_filename(extracted_sci));
5062 //check(tag_s=cpl_frame_get_tag(extracted_sci));
5063
5064 name_o=cpl_sprintf("%s.fits",tag_o);
5065 next_sci=cpl_frame_get_nextensions(extracted_sci);
5066 next_res=cpl_frame_get_nextensions(response);
5067 xsh_msg("Multiply by response function");
5068 check(name_r=cpl_frame_get_filename(response));
5069
5070/* in case the input response was obtained on a binned frame we need
5071 to correct it to un-binned data. We get biny that corresponds to
5072 the bin along wave dispersion direction
5073 plist=cpl_propertylist_load(name_r,0);
5074 cpl_propertylist_dump(plist,stdout);
5075 binx=xsh_pfits_get_biny(plist);
5076 xsh_free_propertylist(&plist);
5077*/
5078 for(ext=0, order=0;ext<next_sci;ext+=3,order++) {
5079 xsh_free_propertylist(&hdat);
5080 xsh_free_propertylist(&herr);
5081 xsh_free_propertylist(&hqua);
5082
5083 check(hdat=cpl_propertylist_load(name_s,ext+0));
5084 check(herr=cpl_propertylist_load(name_s,ext+1));
5085 check(hqua=cpl_propertylist_load(name_s,ext+2));
5086
5087 naxis=xsh_pfits_get_naxis(hdat);
5088
5089 if(naxis == 1) {
5090
5091 check(data_vec=cpl_vector_load(name_s,ext+0));
5092 check(errs_vec=cpl_vector_load(name_s,ext+1));
5093
5094 xsh_free_image(&data_sci);
5095 xsh_free_image(&errs_sci);
5096 check(data_sci=xsh_vector_to_image(data_vec,XSH_PRE_DATA_TYPE));
5097 check(errs_sci=xsh_vector_to_image(errs_vec,XSH_PRE_ERRS_TYPE));
5098
5099 xsh_free_vector(&data_vec);
5100 xsh_free_vector(&errs_vec);
5101
5102 } else {
5103
5104 xsh_free_image(&data_sci);
5105 xsh_free_image(&errs_sci);
5106 xsh_free_image(&qual_sci);
5107 check(data_sci=cpl_image_load(name_s,XSH_PRE_DATA_TYPE,0,ext+0));
5108 check(errs_sci=cpl_image_load(name_s,XSH_PRE_ERRS_TYPE,0,ext+1));
5109 check(qual_sci=cpl_image_load(name_s,XSH_PRE_QUAL_TYPE,0,ext+2));
5110
5111 }
5112
5113 xsh_free_image(&data_tmp);
5114 xsh_free_image(&errs_tmp);
5115 data_tmp=cpl_image_cast(data_sci,CPL_TYPE_DOUBLE);
5116 errs_tmp=cpl_image_cast(errs_sci,CPL_TYPE_DOUBLE);
5117 xsh_free_image(&data_sci);
5118 xsh_free_image(&errs_sci);
5119 xsh_free_table(&response_table);
5120 if(next_res>1) {
5121 check(response_table=cpl_table_load(name_r,order+1,0));
5122 //cpl_table_multiply_scalar(response_table,"FLUX",binx);
5123 } else {
5124 check(response_table=cpl_table_load(name_r,next_res,0));
5125 //cpl_table_multiply_scalar(response_table,"FLUX",binx);
5126 }
5127 /*
5128 * Flux calibrate reduced spectrum
5129 * flux := flux * response
5130 */
5131 check(nbins = cpl_image_get_size_x(data_tmp));
5132 check(ntraces = cpl_image_get_size_y(data_tmp));
5133
5134 check(fluxcal_science_data = cpl_image_get_data_double(data_tmp));
5135 check(fluxcal_science_noise = cpl_image_get_data_double(errs_tmp));
5136
5137 check_msg( lambda_start = xsh_pfits_get_crval1(hdat),
5138 "Error reading start wavelength from reduced science header");
5140 "Error reading bin width from header");
5141
5142 check(cpl_table_cast_column(response_table,"LAMBDA","DLAMBDA",CPL_TYPE_DOUBLE));
5143 check(cpl_table_cast_column(response_table,"RESPONSE","DFLUX",CPL_TYPE_DOUBLE));
5144
5145 for (bin = 1; bin <= nbins; bin++)
5146 {
5147 double lambda;
5148 double response;
5149 int trace; /* Spatial traces (for 2d extracted spectra) */
5150 int istart = 0;
5151
5152 lambda = lambda_start + (bin-1) * lambda_step;
5153 check_msg( response =
5154 xsh_spline_hermite_table(lambda, response_table,
5155 "DLAMBDA", "DFLUX", &istart),
5156 "Error interpolating response curve at lambda = %f wlu", lambda);
5157
5158 xsh_msg_dbg_medium("ext=%d response=%g",ext,response);
5159
5160 for (trace = 1; trace <= ntraces; trace++)
5161 {
5162 /* Don't check for bad pixels here, also correct those.
5163 * The fluxcal image has the same bad pixels as the reduced_science
5164 * image */
5165
5166 fluxcal_science_data [(bin-1) + (trace-1)*nbins] *= response;
5167 /* the following gives problems on some XSH data */
5168 fluxcal_science_noise[(bin-1) + (trace-1)*nbins] *= fabs(response);
5169 /* Do not propagate the error of the response
5170 curve which is negligibly small (and unknown at this point!).
5171 */
5172 }
5173 }
5174
5175 data_sci=cpl_image_cast(data_tmp,XSH_PRE_DATA_TYPE);
5176 errs_sci=cpl_image_cast(errs_tmp,XSH_PRE_ERRS_TYPE);
5177 xsh_free_image(&data_tmp);
5178 xsh_free_image(&errs_tmp);
5179
5180 cpl_table_erase_column(response_table,"DLAMBDA");
5181 cpl_table_erase_column(response_table,"DFLUX");
5182 check( xsh_pfits_set_pcatg( hdat, tag_o));
5183
5184 xsh_pfits_set_extname( hdat, "FLUX");
5186 check(xsh_plist_set_extra_keys(hdat,"IMAGE","DATA","RMSE",
5187 "FLUX","ERRS","QUAL",0));
5188
5190 xsh_pfits_set_extname( herr, "ERRS");
5191 check(xsh_plist_set_extra_keys(herr,"IMAGE","DATA","RMSE",
5192 "FLUX","ERRS","QUAL",1));
5193
5194
5195 xsh_pfits_set_extname( hqua, "QUAL");
5196 check(xsh_plist_set_extra_keys(hqua,"IMAGE","DATA","RMSE",
5197 "FLUX","ERRS","QUAL",2));
5198
5199
5200
5201
5202 if(naxis==1) {
5203 check(data_vec=xsh_image_to_vector(data_sci));
5204 check(errs_vec=xsh_image_to_vector(errs_sci));
5205 if(ext==0) {
5206 check(cpl_vector_save(data_vec,name_o,XSH_SPECTRUM_DATA_BPP,hdat,CPL_IO_DEFAULT));
5207 } else {
5208 check(cpl_vector_save(data_vec,name_o,XSH_SPECTRUM_DATA_BPP,hdat,CPL_IO_EXTEND));
5209 }
5210 check(cpl_vector_save(errs_vec,name_o,XSH_SPECTRUM_ERRS_BPP,herr,CPL_IO_EXTEND));
5211 check(qual_vec=cpl_vector_load(name_s,ext+2));
5212 check(cpl_vector_save(qual_vec,name_o,XSH_SPECTRUM_ERRS_BPP,hqua,CPL_IO_EXTEND));
5213 xsh_free_vector(&data_vec);
5214 xsh_free_vector(&errs_vec);
5215 xsh_free_vector(&qual_vec);
5216 } else {
5217 if(ext==0) {
5218 check(cpl_image_save(data_sci,name_o,XSH_PRE_DATA_BPP,hdat,CPL_IO_DEFAULT));
5219 } else {
5220 check(cpl_image_save(data_sci,name_o,XSH_PRE_DATA_BPP,hdat,CPL_IO_EXTEND));
5221 }
5222 check(cpl_image_save(errs_sci,name_o,XSH_PRE_ERRS_BPP,herr,CPL_IO_EXTEND));
5223 check(cpl_image_save(qual_sci,name_o,XSH_PRE_QUAL_BPP,hqua,CPL_IO_EXTEND));
5224 }
5225
5226 } /* end loop on extensions */
5227
5228 /* the qual ext is treated separately: we duplicate it to product */
5229 result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_IMAGE,CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
5230
5231 cleanup:
5232
5233 cpl_free(name_o);
5234
5235 xsh_free_image(&data_sci);
5236 xsh_free_image(&errs_sci);
5237 xsh_free_image(&qual_sci);
5238 xsh_free_image(&data_sci);
5239 xsh_free_image(&errs_sci);
5240
5241 xsh_free_vector(&data_vec);
5242 xsh_free_vector(&errs_vec);
5243 xsh_free_vector(&qual_vec);
5244
5245 xsh_free_table(&response_table);
5246 xsh_free_propertylist(&hdat);
5247 xsh_free_propertylist(&herr);
5248 xsh_free_propertylist(&hqua);
5249 xsh_free_propertylist(&plist);
5250
5251 return result;
5252}
5253
5254static cpl_error_code
5256 double w,
5257 int i_start,
5258 int i_end,
5259 int* i_inf,
5260 int* i_sup)
5261{
5262
5263 int i=0;
5264 for(i = i_start;i < i_end;i++) {
5265 if (piw[i] < w) {
5266 *i_inf=i;
5267 *i_sup=i+1;
5268 }
5269 }
5270
5271 return cpl_error_get_code();
5272}
5273
5274
5275static double
5277 double* piw,
5278 int i1_inf,
5279 int i1_sup,
5280 int i2_inf,
5281 int i2_sup,
5282 double wave,
5283 double wstep)
5284{
5285
5286 double sum1=0;
5287 double sum2=0;
5288 double sum3=0;
5289 int i=0;
5290
5291 /* The following is to suppress compiler warnings: [-Wunused-parameter] */
5292 (void) i1_inf;
5293 (void) i2_sup;
5294 (void) wave;
5295 (void) wstep;
5296
5297 /* main contribute */
5298 for(i=i1_sup;i<i2_inf;i++) {
5299 /*
5300 simple integration
5301 */
5302 sum2+=pif[i]*(piw[i+1]-piw[i]);
5303 /*
5304 mean 2 point
5305 sum2+=pif[i]*(piw[i+1]-piw[i-1])*0.5;
5306 Simplex 5 points
5307 sum2+=(1/3*pif[i-1]+4/3*pif[i]+1/3*pif[i+1])*(piw[i+1]-piw[i-1])*0.5;
5308 */
5309 /* Bode's 5 points formula
5310 sum2+=(14/45*pif[i-2]+64/45*pif[i-1]+24/45*pif[i]+64/45*pif[i+1]+14/45*pif[i+2])*(piw[i+1]-piw[i-1])*0.5;
5311 */
5312
5313
5314 }
5315 /* extra bit from signal on fractional inf/sup pixel
5316 sum1=(wave-piw[i1_inf])*pif[i1_inf];
5317 sum3=(piw[i2_sup]-wave)*pif[i2_sup];
5318 */
5319 return (sum1+sum2+sum3);
5320}
5321
5322/*---------------------------------------------------------------------------*/
5334/*---------------------------------------------------------------------------*/
5335cpl_frame*
5336xsh_spectrum_resample(cpl_frame* frame_inp,
5337 const double wstep,
5338 const double wmin,
5339 const double wmax,
5340 xsh_instrument* instr)
5341{
5342
5343 cpl_frame* result=NULL;
5344 cpl_table* tab_inp=NULL;
5345 cpl_table* tab_out=NULL;
5346 int nrow_inp=0;
5347 int nrow_out=0;
5348 int i=0;
5349
5350 double wave_min=0;
5351 double wave_max=0;
5352 double wave_start=0;
5353
5354 const char* fname=NULL;
5355 double* pow=NULL;
5356 double* pof=NULL;
5357 double* piw=NULL;
5358 double* pif=NULL;
5359
5360 double wo1=0;
5361 double wo2=0;
5362
5363 int istep=0;
5364
5365 int i1_inf=0;
5366 int i1_sup=0;
5367 int i2_inf=0;
5368 int i2_sup=0;
5369
5370 int i_start=0;
5371 int i_end=0;
5372 double hstep=0;
5373 const char* tag=NULL;
5374 char* name=NULL;
5375 cpl_propertylist* plist=NULL;
5376
5377
5378 check(fname=cpl_frame_get_filename(frame_inp));
5379 tag=cpl_frame_get_tag(frame_inp);
5380 plist=cpl_propertylist_load(fname,0);
5381
5382
5383
5384 tab_inp=cpl_table_load(fname,1,0);
5385 nrow_inp=cpl_table_get_nrow(tab_inp);
5386 wave_min=cpl_table_get_column_min(tab_inp,"LAMBDA");
5387 wave_max=cpl_table_get_column_max(tab_inp,"LAMBDA");
5388
5389 wave_min=(wave_min>wmin) ? wave_min : wmin;
5390 wave_max=(wave_max<wmax) ? wave_max : wmax;
5391
5392 /* for comodity we start from a rounded value in nm */
5393 wave_start=floor(wave_min);
5394 /* make sure that starting wave in UVB is not too small that atm ext
5395 is not defined */
5396 if( xsh_instrument_get_arm(instr) == XSH_ARM_UVB){
5397 wave_start=(wave_start>XSH_ATM_EXT_UVB_WAV_MIN)? wave_start : XSH_ATM_EXT_UVB_WAV_MIN;
5398 }
5399 xsh_msg("Resample ref flux std spectrum to %g [nm] step",wstep);
5400/*
5401 xsh_msg("wave_min %g wave_max %g wave_start %g wstep %g",
5402 wave_min,wave_max,wave_start,wstep);
5403*/
5404 /* prepare table to hold results */
5405 nrow_out=ceil((wave_max-wave_start)/wstep);
5406 tab_out=cpl_table_new(nrow_out);
5407
5408 cpl_table_new_column(tab_out,"LAMBDA",CPL_TYPE_DOUBLE);
5409 cpl_table_new_column(tab_out,"FLUX",CPL_TYPE_DOUBLE);
5410 cpl_table_new_column(tab_out,"BIN_WIDTH",CPL_TYPE_DOUBLE);
5411
5412 cpl_table_fill_column_window_double(tab_out,"LAMBDA",0,nrow_out,0.);
5413 cpl_table_fill_column_window_double(tab_out,"FLUX",0,nrow_out,0.);
5414 cpl_table_fill_column_window_double(tab_out,"BIN_WIDTH",0,nrow_out,wstep);
5415
5416 /* get pointers to data to speed-up computation */
5417 pow=cpl_table_get_data_double(tab_out,"LAMBDA");
5418 pof=cpl_table_get_data_double(tab_out,"FLUX");
5419
5420 piw=cpl_table_get_data_double(tab_inp,"LAMBDA");
5421 pif=cpl_table_get_data_double(tab_inp,"FLUX");
5422
5423 hstep=0.5*wstep;
5424
5425 i_start=0;
5426 i_end=nrow_inp;
5427
5428 /* extra i step to ensure a range large enough to find a sup */
5429 istep=(int) (wstep/(wave_max-wave_min)*nrow_inp+0.5);
5430 istep*=4;
5431/*
5432 xsh_msg("nrow_inp %d nrow_out %d istep %d hstep %g",
5433 nrow_inp,nrow_out,istep,hstep);
5434*/
5435 for(i=0;i<nrow_out;i++) {
5436 pow[i]=wave_start+i*wstep;
5437 wo1=pow[i]-hstep;
5438 wo2=pow[i]+hstep;
5439 i_start=0;
5440 i_end=nrow_inp;
5441
5442 /*
5443 if(wo1>480 && wo1 < 490) {
5444 xsh_msg("wo1 %g wo2 %g",wo1, wo2);
5445 xsh_msg("wt0 piw_start %g piw_end %g",piw[i_start],piw[i_end]);
5446 }
5447 */
5448 /* get indexes corresponding to sup/inf waves */
5449 xsh_util_get_infsup(piw,wo1,i_start,i_end,&i1_inf,&i1_sup);
5450
5451 /*
5452 if(wo1>480 && wo1 < 490) {
5453 xsh_msg("it1 i_start %d i_end %d i1_inf %d i1_sup %d i2_inf %d i2_sup %d",
5454 i_start, i_end, i1_inf, i1_sup, i2_inf, i2_sup);
5455 xsh_msg("wt1 piw_inf %g piw_sup %g",piw[i1_inf],piw[i1_sup]);
5456 }
5457 //reset i_start and i_end to restrict the search to a narrow range
5458 i_start=(i1_sup<nrow_inp)? i1_sup : 0;
5459 i_end=(i1_sup+istep<nrow_inp) ? i1_sup+istep : nrow_inp;
5460
5461
5462 if(wo1>480 && wo1 < 490) {
5463 xsh_msg("wt2 piw_start %g piw_end %g",piw[i_start],piw[i_end]);
5464
5465 xsh_msg("st2 i_start %d i_end %d i1_inf %d i1_sup %d i2_inf %d i2_sup %d",
5466 i_start, i_end, i1_inf, i1_sup, i2_inf, i2_sup);
5467 }
5468 */
5469 xsh_util_get_infsup(piw,wo2,i_start,i_end,&i2_inf,&i2_sup);
5470
5471 /*
5472 if(wo1>480 && wo1 < 490) {
5473 xsh_msg("st3 i_start %d i_end %d i1_inf %d i1_sup %d i2_inf %d i2_sup %d",
5474 i_start, i_end, i1_inf, i1_sup, i2_inf, i2_sup);
5475 xsh_msg("wt3 piw_inf %g piw_sup %g",piw[i2_inf],piw[i2_sup]);
5476 }
5477
5478 i_start=(i2_inf<nrow_inp) ? i2_inf : nrow_inp;
5479 i_end=(i2_sup+istep<nrow_inp) ? i2_sup+istep : nrow_inp;
5480
5481 if(wo1>480 && wo1 < 490) {
5482 xsh_msg("st4 i_start %d i_end %d i1_inf %d i1_sup %d i2_inf %d i2_sup %d",
5483 i_start, i_end, i1_inf, i1_sup, i2_inf, i2_sup);
5484 xsh_msg("wt4 piw_inf %g piw_sup %g",piw[i2_inf],piw[i2_sup]);
5485 }
5486
5487 if(wo1>480 && wo1 < 490) {
5488 xsh_msg("st4 i_start %d i_end %d i1_inf %d i1_sup %d i2_inf %d i2_sup %d",
5489 i_start, i_end, i1_inf, i1_sup, i2_inf, i2_sup);
5490 xsh_msg("i1 piw_inf %g piw_sup %g",piw[i1_inf],piw[i1_sup]);
5491 xsh_msg("i2 piw_inf %g piw_sup %g",piw[i2_inf],piw[i2_sup]);
5492 }
5493 */
5494
5495 /* integrate spectrum on the found range */
5496 pof[i]=xsh_spectrum_integrate(pif,piw,i1_inf,i1_sup,
5497 i2_inf,i2_sup,pow[i],wstep);
5498
5499 /*
5500 if(wo1>480 && wo1 < 490) {
5501 xsh_msg("flux[%g]=%g",pow[i],pof[i]);
5502 }
5503 */
5504 }
5505
5506 cpl_table_and_selected_double(tab_out,"LAMBDA",CPL_LESS_THAN,wmin);
5507 cpl_table_erase_selected(tab_out);
5508 cpl_table_and_selected_double(tab_out,"LAMBDA",CPL_GREATER_THAN,wmax);
5509 cpl_table_erase_selected(tab_out);
5510
5511 name=cpl_sprintf("RESAMPLED_%s_%s.fits",tag,
5513
5514 check(cpl_table_save(tab_out,plist,NULL,name,CPL_IO_DEFAULT));
5516 result=xsh_frame_product(name,tag,CPL_FRAME_TYPE_TABLE,
5517 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
5518
5519
5520 cleanup:
5521 xsh_free_propertylist(&plist);
5522 xsh_free_table(&tab_inp);
5523 xsh_free_table(&tab_out);
5524 cpl_free(name);
5525
5526 return result;
5527}
5528
5529/*--------------------------------------------------------------------------*/
5536/*--------------------------------------------------------------------------*/
5537cpl_frame*
5540{
5541 cpl_frame* result=NULL;
5542 cpl_frame* frm=NULL;
5543
5544 cpl_image* ima=NULL;
5545 cpl_image* err=NULL;
5546
5547 cpl_image* ima_sum=NULL;
5548 cpl_image* err_sum=NULL;
5549 cpl_image* qua_sum=NULL;
5550 cpl_propertylist* hdat=NULL;
5551 cpl_propertylist* herr=NULL;
5552 cpl_propertylist* hqua=NULL;
5553 char* name=NULL;
5554 char* tag=NULL;
5555 const char* fname=NULL;
5556 int size=0;
5557 int i=0;
5558
5559 /* we first sum */
5560 size=cpl_frameset_get_size(set);
5561 for(i=0;i<size;i++) {
5562
5563 frm=cpl_frameset_get_frame(set,i);
5564 fname=cpl_frame_get_filename(frm);
5565
5566 ima=cpl_image_load(fname,XSH_PRE_DATA_TYPE,0,0);
5567 err=cpl_image_load(fname,XSH_PRE_ERRS_TYPE,0,1);
5568 /* errors are summed in quadrature */
5569 cpl_image_multiply(err,err);
5570 if(i==0) {
5571 ima_sum=cpl_image_duplicate(ima);
5572 err_sum=cpl_image_duplicate(err);
5573 } else {
5574 cpl_image_add(ima_sum,ima);
5575 cpl_image_add(err_sum,err);
5576 }
5577
5578 xsh_free_image(&ima);
5579 xsh_free_image(&err);
5580
5581 }
5582
5583 /* when we average */
5584 cpl_image_divide_scalar(ima_sum,size);
5585 cpl_image_divide_scalar(err_sum,size);
5586
5587 /* as was the quadratic error we need to get the square root */
5588 check(cpl_image_power(err_sum,0.5));
5589
5590 /* for the qual image we assume is ok the one of 1st frame */
5591 qua_sum=cpl_image_load(fname,XSH_PRE_QUAL_TYPE,0,2);
5592
5593 frm=cpl_frameset_get_frame(set,0);
5594 fname=cpl_frame_get_filename(frm);
5595 hdat=cpl_propertylist_load(fname,0);
5596 herr=cpl_propertylist_load(fname,1);
5597 hqua=cpl_propertylist_load(fname,2);
5598
5599 name=cpl_sprintf("SKY_AVG_%s.fits",xsh_instrument_arm_tostring( instrument));
5600 tag=cpl_sprintf("SKY_AVG_%s",xsh_instrument_arm_tostring( instrument));
5601
5602 check(cpl_image_save(ima_sum,name,XSH_PRE_DATA_BPP,hdat,CPL_IO_DEFAULT));
5603 check(cpl_image_save(err_sum,name,XSH_PRE_ERRS_BPP,herr,CPL_IO_EXTEND));
5604 check(cpl_image_save(qua_sum,name,XSH_PRE_QUAL_BPP,hqua,CPL_IO_EXTEND));
5605 result=xsh_frame_product(name,tag,CPL_FRAME_TYPE_IMAGE,
5606 CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
5608
5609 cleanup:
5610
5611 xsh_free_image(&ima);
5612 xsh_free_image(&err);
5613
5614 xsh_free_image(&ima_sum);
5615 xsh_free_image(&err_sum);
5616 xsh_free_image(&qua_sum);
5617
5618 xsh_free_propertylist(&hdat);
5619 xsh_free_propertylist(&herr);
5620 xsh_free_propertylist(&hqua);
5621
5622 cpl_free(name);
5623 cpl_free(tag);
5624
5625 return result;
5626}
5627
5628
5629
5630/*---------------------------------------------------------------------------*/
5649cpl_error_code
5651 const char* tag_o,
5652 const int ext,
5653 const int bin_size,
5654 const double gain,
5655 const double exptime,
5656 const double airmass,
5657 const cpl_table* tbl_atm_ext)
5658{
5659
5660
5661 cpl_image* data_ima=NULL;
5662 cpl_image* errs_ima=NULL;
5663 cpl_image* qual_ima=NULL;
5664 cpl_image* data_nrm=NULL;
5665 cpl_image* errs_nrm=NULL;
5666
5667 cpl_image* data_tmp=NULL;
5668 cpl_image* errs_tmp=NULL;
5669
5670 cpl_image* data_nrm_tmp=NULL;
5671 cpl_image* errs_nrm_tmp=NULL;
5672
5673 cpl_vector* data_vec=NULL;
5674 cpl_vector* errs_vec=NULL;
5675 cpl_vector* qual_vec=NULL;
5676
5677 cpl_propertylist* hdat=NULL;
5678 cpl_propertylist* herr=NULL;
5679 cpl_propertylist* hqua=NULL;
5680 int naxis=0;
5681 char name_o[256];
5682
5683 sprintf(name_o,"%s.fits",tag_o);
5684
5685 xsh_free_propertylist(&hdat);
5686 xsh_free_propertylist(&herr);
5687 xsh_free_propertylist(&hqua);
5688
5689 hdat=cpl_propertylist_load(name_s,ext+0);
5690 herr=cpl_propertylist_load(name_s,ext+1);
5691 hqua=cpl_propertylist_load(name_s,ext+2);
5692
5693
5694 naxis=xsh_pfits_get_naxis(hdat);
5695 xsh_pfits_set_pcatg(hdat,tag_o);
5696 if(naxis == 1) {
5697
5698 check(data_vec=cpl_vector_load(name_s,ext+0));
5699 check(errs_vec=cpl_vector_load(name_s,ext+1));
5700 xsh_free_image(&data_ima);
5701 xsh_free_image(&errs_ima);
5702 check(data_ima=xsh_vector_to_image(data_vec,XSH_PRE_DATA_TYPE));
5703 check(errs_ima=xsh_vector_to_image(errs_vec,XSH_PRE_ERRS_TYPE));
5704 xsh_free_vector(&data_vec);
5705 xsh_free_vector(&errs_vec);
5706
5707 } else {
5708
5709 xsh_free_image(&data_ima);
5710 xsh_free_image(&errs_ima);
5711 xsh_free_image(&qual_ima);
5712 check(data_ima=cpl_image_load(name_s,XSH_PRE_DATA_TYPE,0,ext+0));
5713 check(errs_ima=cpl_image_load(name_s,XSH_PRE_ERRS_TYPE,0,ext+1));
5714 check(qual_ima=cpl_image_load(name_s,XSH_PRE_QUAL_TYPE,0,ext+2));
5715
5716 }
5717 xsh_free_image(&data_tmp);
5718 xsh_free_image(&errs_tmp);
5719 data_tmp=cpl_image_cast(data_ima,CPL_TYPE_DOUBLE);
5720 errs_tmp=cpl_image_cast(errs_ima,CPL_TYPE_DOUBLE);
5721
5722 xsh_free_image(&data_nrm_tmp);
5723 xsh_free_image(&errs_nrm_tmp);
5724
5725 check(data_nrm_tmp=xsh_normalize_spectrum_image(data_tmp,errs_tmp,hdat,
5726 bin_size,gain,exptime,airmass,1,
5727 tbl_atm_ext,&errs_nrm_tmp));
5728
5729 xsh_free_image(&data_nrm);
5730 xsh_free_image(&errs_nrm);
5731 check(data_nrm=cpl_image_cast(data_nrm_tmp,CPL_TYPE_FLOAT));
5732 check(errs_nrm=cpl_image_cast(errs_nrm_tmp,CPL_TYPE_FLOAT));
5733
5734 if(naxis==1) {
5735 xsh_free_vector(&data_vec);
5736 xsh_free_vector(&errs_vec);
5737
5738 check(data_vec=xsh_image_to_vector(data_nrm));
5739 check(errs_vec=xsh_image_to_vector(errs_nrm));
5740
5741 if(ext==0) {
5742 check(cpl_vector_save(data_vec,name_o,XSH_SPECTRUM_DATA_BPP,hdat,CPL_IO_DEFAULT));
5743 } else {
5744 check(cpl_vector_save(data_vec,name_o,XSH_SPECTRUM_DATA_BPP,hdat,CPL_IO_EXTEND));
5745 }
5746 check(cpl_vector_save(errs_vec,name_o,XSH_SPECTRUM_ERRS_BPP,herr,CPL_IO_EXTEND));
5747 xsh_free_vector(&qual_vec);
5748 check(qual_vec=cpl_vector_load(name_s,ext+2));
5749 check(cpl_vector_save(qual_vec,name_o,XSH_SPECTRUM_ERRS_BPP,hqua,CPL_IO_EXTEND));
5750
5751
5752 } else {
5753 if(ext==0) {
5754 check(cpl_image_save(data_nrm,name_o,XSH_PRE_DATA_BPP,hdat,CPL_IO_DEFAULT));
5755 } else {
5756 check(cpl_image_save(data_nrm,name_o,XSH_PRE_DATA_BPP,hdat,CPL_IO_EXTEND));
5757 }
5758 check(cpl_image_save(errs_nrm,name_o,XSH_PRE_ERRS_BPP,herr,CPL_IO_EXTEND));
5759 check(cpl_image_save(qual_ima,name_o,XSH_PRE_QUAL_BPP,hqua,CPL_IO_EXTEND));
5760
5761 }
5762 /* the qual ext is treated separately: we duplicate it to product */
5763
5764
5765 cleanup:
5766 xsh_free_image(&data_ima);
5767 xsh_free_image(&errs_ima);
5768 xsh_free_image(&qual_ima);
5769 xsh_free_image(&data_nrm);
5770 xsh_free_image(&errs_nrm);
5771 xsh_free_image(&data_tmp);
5772 xsh_free_image(&errs_tmp);
5773 xsh_free_image(&data_nrm_tmp);
5774 xsh_free_image(&errs_nrm_tmp);
5775
5776 xsh_free_propertylist(&hdat);
5777 xsh_free_propertylist(&herr);
5778 xsh_free_propertylist(&hqua);
5779
5780 xsh_free_vector(&data_vec);
5781 xsh_free_vector(&errs_vec);
5782 xsh_free_vector(&qual_vec);
5783
5784 return cpl_error_get_code();
5785}
5786
5787
5788/*---------------------------------------------------------------------------*/
5805/* Needs to be updated for multi extension (ORDER-BY-ORDER) */
5806cpl_frame *
5807xsh_normalize_spectrum(const cpl_frame *obj_frame,
5808 const cpl_frame *atm_ext_frame,
5809 cpl_boolean correct_binning,
5811 const char* tag_o)
5812{
5813
5814 cpl_frame* result=NULL;
5815 const char* name_s=NULL;
5816 const char* aname=NULL;
5817
5818 cpl_table* tbl_atm_ext=NULL;
5819 cpl_propertylist* hdat=NULL;
5820
5821 char* name_o=NULL;
5822 int binx=1;
5823 double gain=0;
5824 double exptime=0;
5825 double airmass=0;
5826
5827 XSH_ASSURE_NOT_NULL_MSG(obj_frame,"Null input object frame");
5828 XSH_ASSURE_NOT_NULL_MSG(atm_ext_frame,"Null input atm ext frame");
5829
5830 name_s=cpl_frame_get_filename(obj_frame);
5831 aname=cpl_frame_get_filename(atm_ext_frame);
5832 tbl_atm_ext=cpl_table_load(aname,1,0);
5833
5834 cpl_table_cast_column( tbl_atm_ext,"LAMBDA","D_LAMBDA",CPL_TYPE_DOUBLE);
5835 cpl_table_cast_column( tbl_atm_ext,XSH_ATMOS_EXT_LIST_COLNAME_K,"D_EXTINCTION",CPL_TYPE_DOUBLE);
5836
5837 /* observed frame scaling factors */
5838 hdat=cpl_propertylist_load(name_s,0);
5841 /* we assume gain in units of ADU/e- as ESO standard */
5842 gain=1./2.12;
5843 } else {
5844 gain = xsh_pfits_get_gain(hdat);
5845 }
5846
5847 if (correct_binning) {
5848 /* x-binning of rotated image is y-binning of raw image */
5849 //binx = xsh_pfits_get_biny(hdat);
5850 } else {
5851 xsh_msg_dbg_medium("Spectrum will not be normalized to unit binning");
5852 binx = 1;
5853 }
5854 airmass=xsh_pfits_get_airm_mean(hdat);
5855 name_o=cpl_sprintf("%s.fits",tag_o);
5856
5857 check(xsh_normalize_spectrum_image_slice(name_s,tag_o,0,binx,gain,
5858 exptime,airmass,tbl_atm_ext));
5859
5860 result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_IMAGE,CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
5861
5862 cleanup:
5863
5864 xsh_free_table(&tbl_atm_ext);
5865 xsh_free_propertylist(&hdat);
5866 cpl_free(name_o);
5867
5868 return result;
5869
5870}
5871
5872
5873
5874
5875/*---------------------------------------------------------------------------*/
5891/* Needs to be updated for multi extension (ORDER-BY-ORDER) */
5892cpl_frame *
5893xsh_normalize_spectrum_ord(const cpl_frame *obj_frame,
5894 const cpl_frame *atm_ext_frame,
5895 cpl_boolean correct_binning,
5897 const char* tag_o)
5898{
5899
5900 cpl_frame* result=NULL;
5901 const char* name_s=NULL;
5902 const char* aname=NULL;
5903
5904 cpl_table* tbl_atm_ext=NULL;
5905 cpl_propertylist* hdat=NULL;
5906 char* name_o=NULL;
5907
5908 int next=0;
5909 int ext=0;
5910 int binx=1;
5911 int biny=1;
5912 int bin_size=1;
5913 double gain=0;
5914 double exptime=0;
5915 double airmass=0;
5916
5917 XSH_ASSURE_NOT_NULL_MSG(obj_frame,"Null input object frame");
5918 XSH_ASSURE_NOT_NULL_MSG(atm_ext_frame,"Null input atm ext frame");
5919
5920 next=cpl_frame_get_nextensions( obj_frame);
5921 name_s=cpl_frame_get_filename(obj_frame);
5922
5923 aname=cpl_frame_get_filename(atm_ext_frame);
5924 tbl_atm_ext=cpl_table_load(aname,1,0);
5925 check(cpl_table_cast_column( tbl_atm_ext,"LAMBDA","D_LAMBDA",CPL_TYPE_DOUBLE));
5926 if(!cpl_table_has_column(tbl_atm_ext,XSH_ATMOS_EXT_LIST_COLNAME_K)){
5927 xsh_msg_warning("You are using an obsolete atm extinction line table");
5928 cpl_table_duplicate_column(tbl_atm_ext,XSH_ATMOS_EXT_LIST_COLNAME_K,
5929 tbl_atm_ext,XSH_ATMOS_EXT_LIST_COLNAME_OLD);
5930 }
5931 check(cpl_table_cast_column( tbl_atm_ext,XSH_ATMOS_EXT_LIST_COLNAME_K,"D_EXTINCTION",CPL_TYPE_DOUBLE));
5932 name_o=cpl_sprintf("%s.fits",tag_o);
5933
5934 hdat=cpl_propertylist_load(name_s,0);
5935 /* observed frame scaling factors */
5938 /* we assume gain in units of ADU/e- as ESO standard */
5939 gain=1./2.12;
5940 } else {
5941 check(gain = xsh_pfits_get_gain(hdat));
5942 }
5943
5944 if (correct_binning && (xsh_instrument_get_arm(instrument) != XSH_ARM_NIR)) {
5945 /* x-binning of rotated image is y-binning of raw image */
5946 check(binx = xsh_pfits_get_binx(hdat));
5947 check(biny = xsh_pfits_get_biny(hdat));
5948 bin_size=binx*biny;
5949 } else {
5950 xsh_msg_dbg_medium("Spectrum will not be normalized to unit binning");
5951 }
5952 check(airmass=xsh_pfits_get_airm_mean(hdat));
5953
5954 for(ext=0;ext<next;ext+=3) {
5955 check(xsh_normalize_spectrum_image_slice(name_s,tag_o,ext,bin_size,gain,
5956 exptime,airmass,tbl_atm_ext));
5957 }/* end loop over extention */
5958
5959 result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_IMAGE,CPL_FRAME_GROUP_PRODUCT,CPL_FRAME_LEVEL_FINAL);
5960
5961 cleanup:
5962
5963 xsh_free_table(&tbl_atm_ext);
5964 xsh_free_propertylist(&hdat);
5965 cpl_free(name_o);
5966
5967 return result;
5968
5969}
5970
5971/*---------------------------------------------------------------------------*/
5993/* Needs to be updated for multi extension (ORDER-BY-ORDER) */
5994/*----------------------------------------------------------------------------*/
5995cpl_image *
5996xsh_normalize_spectrum_image(const cpl_image *spectrum,
5997 const cpl_image *spectrum_error,
5998 const cpl_propertylist *spectrum_header,
5999 const int bin_size,
6000 const double gain,
6001 const double exptime,
6002 const double airmass,
6003 const int n_traces,
6004 const cpl_table *atm_extinction,
6005 cpl_image **scaled_error)
6006{
6007 cpl_image *scaled = NULL;
6008 int norders, ny, nx;
6009 double cor_fct=gain*exptime*bin_size;
6010 XSH_ASSURE_NOT_NULL_MSG(spectrum,"Null input spectrum");
6011 XSH_ASSURE_NOT_NULL_MSG(scaled_error,"Null input scaled error");
6012 XSH_ASSURE_NOT_NULL_MSG(spectrum_error, "Null input spectrum error");
6013 XSH_ASSURE_NOT_NULL_MSG(spectrum_header,"Null input spectrum header");
6014 XSH_ASSURE_NOT_NULL_MSG(atm_extinction,"Null input atmospheric extinction table");
6015
6016 nx = cpl_image_get_size_x(spectrum);
6017 ny = cpl_image_get_size_y(spectrum);
6018
6019
6020 if (spectrum_error != NULL)
6021 {
6022 assure( nx == cpl_image_get_size_x(spectrum_error) &&
6023 ny == cpl_image_get_size_y(spectrum_error), CPL_ERROR_INCOMPATIBLE_INPUT,
6024 "Error spectrum geometry differs from spectrum: %" CPL_SIZE_FORMAT "x%" CPL_SIZE_FORMAT " vs. %dx%d",
6025 cpl_image_get_size_x(spectrum_error),
6026 cpl_image_get_size_y(spectrum_error),
6027 nx, ny);
6028 }
6029
6030 assure( ny % n_traces == 0, CPL_ERROR_INCOMPATIBLE_INPUT,
6031 "Spectrum image height (%d) is not a multiple of "
6032 "the number of traces (%d). Confused, bailing out",
6033 ny, n_traces);
6034
6035 norders = ny / n_traces;
6036
6037 /*
6038 * Correct for exposure time, gain, bin
6039 */
6040 assure( exptime > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive exposure time: %f s", exptime);
6041 assure( gain > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive gain: %f", gain);
6042 assure( bin_size > 0, CPL_ERROR_ILLEGAL_INPUT, "Illegal binning: %d", bin_size);
6043
6044 xsh_msg_dbg_medium("Correcting for exposure time = %f s, gain = %f, bin_size = %d", exptime, gain, bin_size);
6045
6046 check_msg(scaled=cpl_image_divide_scalar_create(spectrum,cor_fct),
6047 "Error correcting spectrum for gain, exposure time, binning");
6048
6049 if (scaled_error != NULL)
6050 {
6051 check_msg( *scaled_error=cpl_image_divide_scalar_create(spectrum_error,
6052 cor_fct),
6053 "Error correcting rebinned spectrum for gain, exposure time, binning");
6054 }
6055
6056 /*
6057 * Correct for atmospheric extinction
6058 */
6059 {
6060 double dlambda, lambda_start;
6061 int order;
6062
6063 xsh_msg_dbg_medium("Correcting for extinction through airmass %f", airmass);
6064 check_msg( dlambda = xsh_pfits_get_cdelt1(spectrum_header),
6065 "Error reading bin width from header");
6066
6067 for (order = 1; order <= norders; order++)
6068 {
6069 int trace;
6070
6071 /* If spectrum was already merged, then read crval1,
6072 * otherwise read wstart for each order
6073 */
6074
6075 if (norders == 1)
6076 {
6077 check_msg( lambda_start = xsh_pfits_get_crval1(spectrum_header),
6078 "Error reading start wavelength from header");
6079 }
6080 else
6081 {
6082 /* Here need to be updated for multi extension (ORDER-BY-ORDER) */
6083 check_msg( lambda_start = xsh_pfits_get_crval1(spectrum_header),
6084 "Error reading start wavelength from header");
6085 }
6086
6087 for (trace = 1; trace <= n_traces; trace++)
6088 {
6089 int spectrum_row = (order - 1)*n_traces + trace;
6090 int x;
6091
6092 for (x = 1; x <= nx; x++)
6093 {
6094 int pis_rejected1;
6095 int pis_rejected2;
6096 double flux;
6097 double dflux = 0;
6098 double extinction;
6099 double lambda;
6100
6101 lambda = lambda_start + (x-1) * dlambda;
6102
6103 flux = cpl_image_get(scaled, x, spectrum_row, &pis_rejected1);
6104 if (scaled_error != NULL)
6105 {
6106 dflux = cpl_image_get(*scaled_error, x,
6107 spectrum_row, &pis_rejected2);
6108 }
6109
6110 if (!pis_rejected1 && (scaled_error == NULL || !pis_rejected2))
6111 {
6112 int istart = 0;
6113
6114 /* Read extinction (units: magnitude per airmass) */
6115 check_msg( extinction =
6117 lambda, atm_extinction,
6118 "D_LAMBDA", "D_EXTINCTION", &istart),
6119 "Error interpolating extinction coefficient");
6120
6121 /* Correct for extinction using
6122 * the magnitude/flux relation
6123 * m = -2.5 log_10 F
6124 * =>
6125 * F = 10^(-m*0.4)
6126 *
6127 * m_top-of-atmosphere = m - ext.coeff*airmass
6128 * F_top-of-atmosphere = F * 10^(0.4 * ext.coeff*airmass)
6129 */
6130
6131 cpl_image_set(
6132 scaled, x, spectrum_row,
6133 flux * pow(10, 0.4 * extinction * airmass));
6134 if (scaled_error != NULL)
6135 {
6136 cpl_image_set(
6137 *scaled_error, x, spectrum_row,
6138 dflux * pow(10, 0.4 * extinction * airmass));
6139 }
6140 }
6141 else
6142 {
6143 cpl_image_reject(scaled, x, spectrum_row);
6144 if (scaled_error != NULL)
6145 {
6146 cpl_image_reject(*scaled_error, x, spectrum_row);
6147 }
6148 }
6149 } /* for each x */
6150
6151 } /* for each (possibly only 1) trace */
6152
6153 } /* for each (possibly only 1) order */
6154 }
6155
6156 cleanup:
6157 if (cpl_error_get_code() != CPL_ERROR_NONE)
6158 {
6159 xsh_free_image(&scaled);
6160 if (scaled_error != NULL)
6161 {
6162 xsh_free_image(scaled_error);
6163 }
6164 }
6165
6166 return scaled;
6167}
6168
6169static double
6170xsh_iterpol_linear(double* data_x,double* data_y,int ndata,double x,
6171int* i_inf,int* i_sup)
6172{
6173 int i=0;
6174 double y=0;
6175 //int i_min=0;
6176 //int i_max=0;
6177 double x1=data_x[*i_inf];
6178 double x2=data_x[*i_sup];
6179 double y1=data_y[*i_inf];
6180 double y2=data_y[*i_sup];
6181 //x1=x2=y1=y2=0;
6182 //i_min=((*i_inf)>0) ? (*i_inf):0;
6183 //i_max=((*i_sup)<ndata) ? (*i_sup):ndata;
6184 //xsh_msg("i_min=%d i_max=%d",i_min,i_max);
6185 //for(i=i_min;i<i_max;i++) {
6186 for(i=1;i<ndata-1;i++) {
6187 //xsh_msg("data_x[%d]=%g,data_y[%d]=%g,x=%g",i,data_x[i],i,data_y[i],x);
6188 if(data_x[i]>x) {
6189 y1=data_y[i-1];
6190 y2=data_y[i];
6191 x1=data_x[i-1];
6192 x2=data_x[i];
6193 *i_inf=i-1;
6194 *i_sup=i+1;
6195 break;
6196 }
6197 }
6198 //xsh_msg("i_inf=%d i_sup=%d",*i_inf,*i_sup);
6199 y=(y2-y1)/(x2-x1)*(x-x1)+y1;
6200 //xsh_msg("x1=%g x2=%g y1=%g y2=%g x=%g y=%g",x1,x2,y1,y2,x,y);
6201
6202 return y;
6203}
6204
6212cpl_frame*
6213xsh_spectrum_interpolate_linear(cpl_frame* table_frame,
6214 const double wstep,
6215 const double wmin,
6216 const double wmax)
6217{
6218
6219 cpl_frame* result=NULL;
6220 cpl_table* table_i=NULL;
6221 cpl_table* table_o=NULL;
6222 const char* name_i=NULL;
6223 const char* tag_i=NULL;
6224
6225 char* name_o=NULL;
6226 char* tag_o=NULL;
6227
6228 cpl_propertylist* plist=NULL;
6229 int nrows_i=0;
6230 int nrows_o=0;
6231 int row=0;
6232
6233 double* pwave_i=NULL;
6234 double* pflux_i=NULL;
6235 double* pwave_o=NULL;
6236 double* pflux_o=NULL;
6237 int i_inf=0;
6238 int i_sup=0;
6239
6240 //int istart = 0;
6241
6242 XSH_ASSURE_NOT_NULL_MSG(table_frame,"Null input table frame");
6243 XSH_ASSURE_NOT_ILLEGAL_MSG(wmax>wmin,"wmax < wmin");
6244 XSH_ASSURE_NOT_ILLEGAL_MSG(wstep>0,"wstep <= 0");
6245
6246 name_i=cpl_frame_get_filename(table_frame);
6247 tag_i=cpl_frame_get_tag(table_frame);
6248 //xsh_msg("name_i=%s",name_i);
6249 check(table_i=cpl_table_load(name_i,1,0));
6250 nrows_i=cpl_table_get_nrow(table_i);
6251 plist=cpl_propertylist_load(name_i,0);
6252 nrows_o=(int)((wmax-wmin)/wstep+0.5);
6253 table_o=cpl_table_new(nrows_o);
6254 cpl_table_new_column(table_o,"LAMBDA",CPL_TYPE_DOUBLE);
6255 cpl_table_new_column(table_o,"FLUX",CPL_TYPE_DOUBLE);
6256 check(cpl_table_fill_column_window_double(table_o,"LAMBDA",0,nrows_o,0.));
6257 check(cpl_table_fill_column_window_double(table_o,"FLUX",0,nrows_o,0.));
6258 check(pwave_i=cpl_table_get_data_double(table_i,"LAMBDA"));
6259 check(pflux_i=cpl_table_get_data_double(table_i,"FLUX"));
6260 check(pwave_o=cpl_table_get_data_double(table_o,"LAMBDA"));
6261 check(pflux_o=cpl_table_get_data_double(table_o,"FLUX"));
6262 i_inf=0;
6263 i_sup=nrows_o;
6264
6265 for (row = 0; row < nrows_o; row++)
6266 {
6267
6268 pwave_o[row]= wmin + row * wstep;
6269 pflux_o[row]= xsh_iterpol_linear(pwave_i,pflux_i,nrows_i,pwave_o[row],
6270 &i_inf,&i_sup);
6271
6272 //xsh_msg("interpolated flux[%g]=%g",pwave_o[row],pflux_o[row]);
6273 }
6274 tag_o=cpl_sprintf("INTERPOL_%s",tag_i);
6275 name_o=cpl_sprintf("INTERPOL_%s.fits",tag_i);
6276 xsh_pfits_set_pcatg(plist,tag_o);
6277 check(cpl_table_save(table_o,plist,NULL,name_o,CPL_IO_DEFAULT));
6278 check(result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_TABLE,
6279 CPL_FRAME_GROUP_PRODUCT,
6280 CPL_FRAME_LEVEL_FINAL));
6281 xsh_add_temporary_file(name_o);
6282 cleanup:
6283
6284
6285 xsh_free_table(&table_i);
6286 xsh_free_table(&table_o);
6287 xsh_free_propertylist(&plist);
6288 cpl_free(name_o);
6289 cpl_free(tag_o);
6290
6291 return result;
6292
6293}
6294
6295
6296
6297
6305cpl_frame*
6306xsh_spectrum_interpolate(cpl_frame* table_frame,
6307 const double wstep,
6308 const double wmin,
6309 const double wmax)
6310{
6311
6312 cpl_frame* result=NULL;
6313 cpl_table* table_i=NULL;
6314 cpl_table* table_o=NULL;
6315 const char* name_i=NULL;
6316 const char* tag_i=NULL;
6317
6318 char* name_o=NULL;
6319 char* tag_o=NULL;
6320
6321 cpl_propertylist* plist=NULL;
6322 int nrows=0;
6323 int row=0;
6324 double wave=0;
6325 double flux_o=0;
6326 double* pwave=NULL;
6327 double* pflux=NULL;
6328
6329 int istart = 0;
6330 double flux_med =0;
6331 XSH_ASSURE_NOT_NULL_MSG(table_frame,"Null input table frame");
6332 XSH_ASSURE_NOT_ILLEGAL_MSG(wmax>wmin,"wmax < wmin");
6333 XSH_ASSURE_NOT_ILLEGAL_MSG(wstep>0,"wstep <= 0");
6334
6335 name_i=cpl_frame_get_filename(table_frame);
6336
6337 tag_i=cpl_frame_get_tag(table_frame);
6338 check(table_i=cpl_table_load(name_i,1,0));
6339 flux_med=cpl_table_get_column_median(table_i,"FLUX");
6340 cpl_table_divide_scalar(table_i,"FLUX",flux_med);
6341
6342 plist=cpl_propertylist_load(name_i,0);
6343 nrows=(int)((wmax-wmin)/wstep+0.5);
6344 table_o=cpl_table_new(nrows);
6345
6346 cpl_table_new_column(table_o,"LAMBDA",CPL_TYPE_DOUBLE);
6347
6348 cpl_table_new_column(table_o,"FLUX",CPL_TYPE_DOUBLE);
6349
6350 check(pwave=cpl_table_get_data_double(table_o,"LAMBDA"));
6351
6352 check(pflux=cpl_table_get_data_double(table_o,"FLUX"));
6353
6354
6355 check(cpl_table_fill_column_window_double(table_o,"LAMBDA",0,nrows,0.));
6356 check(cpl_table_fill_column_window_double(table_o,"FLUX",0,nrows,0.));
6357
6358 check(pwave=cpl_table_get_data_double(table_o,"LAMBDA"));
6359 check(pflux=cpl_table_get_data_double(table_o,"FLUX"));
6360
6361
6362 for (row = 0; row < nrows; row++)
6363 {
6364
6365 wave = wmin + row * wstep;
6366
6367 check_msg( flux_o = xsh_spline_hermite_table(wave, table_i,
6368 "LAMBDA", "FLUX", &istart),
6369 "Error interpolating curve at lambda = %f wlu", wave);
6370 pwave[row]=wave;
6371 pflux[row]=flux_o;
6372
6373 xsh_msg_dbg_medium("interpolated flux[%g]=%g",wave,flux_o);
6374 }
6375
6376 cpl_table_multiply_scalar(table_i,"FLUX",flux_med);
6377 cpl_table_multiply_scalar(table_o,"FLUX",flux_med);
6378
6379 tag_o=cpl_sprintf("INTERPOL_%s",tag_i);
6380 name_o=cpl_sprintf("INTERPOL_%s.fits",tag_i);
6381 xsh_pfits_set_pcatg(plist,tag_o);
6382 check(cpl_table_save(table_o,plist,NULL,name_o,CPL_IO_DEFAULT));
6383 check(result=xsh_frame_product(name_o,tag_o,CPL_FRAME_TYPE_TABLE,
6384 CPL_FRAME_GROUP_PRODUCT,
6385 CPL_FRAME_LEVEL_FINAL));
6386
6387 xsh_add_temporary_file(name_o);
6388
6389 cleanup:
6390
6391
6392 xsh_free_table(&table_i);
6393 xsh_free_table(&table_o);
6394 xsh_free_propertylist(&plist);
6395 cpl_free(name_o);
6396 cpl_free(tag_o);
6397
6398
6399 return result;
6400
6401}
6402
6403/******************************************************************************/
6404/******************************************************************************/
6414void
6415xsh_array_clip_mean( cpl_array *array,
6416 double kappa,
6417 int niter,
6418 double frac_min,
6419 double *mean,
6420 double *stdev)
6421{
6422 int i, j, size;
6423 double mean_val;
6424 double sigma, frac;
6425 int *flags = NULL;
6426 int nb_rejected = 0, total_rejected=0;
6427 double* pval=NULL;
6428
6429 XSH_ASSURE_NOT_NULL( array);
6430 XSH_ASSURE_NOT_NULL( mean);
6431 XSH_ASSURE_NOT_NULL( stdev);
6432
6433 check( mean_val = cpl_array_get_mean( array));
6434 check( sigma = cpl_array_get_stdev( array));
6435 check( size = cpl_array_get_size( array));
6436
6437 XSH_CALLOC( flags, int, size);
6438
6439 xsh_msg_dbg_medium("Iteration %d/%d", 0, niter);
6440 xsh_msg_dbg_medium("Accepted fraction %f Mean %f sigma %f", 1.0, mean_val, sigma);
6441
6442
6443 check(pval=cpl_array_get_data_double(array));
6444 for( i=1; i<= niter; i++) {
6445 xsh_msg_dbg_medium("Iteration %d/%d", i, niter);
6446 nb_rejected = 0;
6447 for( j=0; j< size; j++){
6448
6449 if ( flags[j] == 0 && fabs( pval[j]-mean_val) > kappa*sigma){
6450 nb_rejected++;
6451 flags[j]=1;
6452 check( cpl_array_set_invalid( array, j));
6453 }
6454 }
6455 if ( nb_rejected == 0){
6456 xsh_msg("No more points are rejected. Iterations are stopped.");
6457 break;
6458 }
6459 total_rejected += nb_rejected;
6460 frac = 1-(double)total_rejected/(double)size;
6461 if (frac < frac_min){
6462 xsh_msg("Minimal fraction of accepted points %f is reached (%f). Iterations are stopped",
6463 frac_min, frac);
6464 break;
6465 }
6466
6467 check( mean_val = cpl_array_get_mean( array));
6468 check( sigma = cpl_array_get_stdev( array));
6469 xsh_msg("Accepted fraction %f Mean %f sigma %f", frac, mean_val, sigma);
6470 }
6471
6472 xsh_msg("End of clipping : Mean %f sigma %f", mean_val, sigma);
6473 *mean = mean_val;
6474 *stdev = sigma;
6475
6476 cleanup:
6477 XSH_FREE( flags);
6478 return;
6479}
6480/******************************************************************************/
6492void
6493xsh_array_clip_median( cpl_array *array,
6494 double kappa,
6495 int niter,
6496 double frac_min,
6497 double *median,
6498 double *stdev)
6499{
6500 int i, j, size;
6501 double median_val;
6502 double sigma, frac;
6503 int *flags = NULL;
6504 int nb_rejected = 0, total_rejected=0;
6505 double* pval=NULL;
6506
6507 XSH_ASSURE_NOT_NULL( array);
6508 XSH_ASSURE_NOT_NULL( median);
6509 XSH_ASSURE_NOT_NULL( stdev);
6510
6511 check( median_val = cpl_array_get_median( array));
6512 check( sigma = cpl_array_get_stdev( array));
6513 check( size = cpl_array_get_size( array));
6514
6515 XSH_CALLOC( flags, int, size);
6516
6517 xsh_msg("Iteration %d/%d", 0, niter);
6518 xsh_msg("Accepted fraction %f Median %f sigma %f", 1.0, median_val, sigma);
6519 check(pval=cpl_array_get_data_double(array));
6520 for( i=1; i<= niter; i++) {
6521 xsh_msg("Iteration %d/%d", i, niter);
6522 nb_rejected = 0;
6523 for( j=0; j< size; j++){
6524
6525 if ( flags[j] == 0 && fabs( pval[j]-median_val) > kappa*sigma){
6526 nb_rejected++;
6527 flags[j]=1;
6528 check( cpl_array_set_invalid( array, j));
6529 }
6530 }
6531 if ( nb_rejected == 0){
6532 xsh_msg("No more points are rejected. Iterations are stopped.");
6533 break;
6534 }
6535 total_rejected += nb_rejected;
6536 frac = 1-(double)total_rejected/(double)size;
6537 if (frac < frac_min){
6538 xsh_msg("Minimal fraction of accepted points %f is reached (%f). Iterations are stopped",
6539 frac_min, frac);
6540 break;
6541 }
6542 check( median_val = cpl_array_get_median( array));
6543 check( sigma = cpl_array_get_stdev( array));
6544 xsh_msg("Accepted fraction %f Median %f sigma %f", frac, median_val, sigma);
6545 }
6546 xsh_msg("End of clipping : Median %f sigma %f", median_val, sigma);
6547 *median = median_val;
6548 *stdev = sigma;
6549
6550 cleanup:
6551 XSH_FREE( flags);
6552 return;
6553}
6554
6567void
6568xsh_array_clip_poly1d( cpl_vector *pos_vect,
6569 cpl_vector *val_vect,
6570 double kappa,
6571 int niter,
6572 double frac_min,
6573 int deg,
6574 cpl_polynomial **polyp,
6575 double *chisq,
6576 int **flagsp)
6577{
6578 int i, j, size;
6579 double frac, sigma;
6580 int *flags = NULL;
6581 int nb_rejected = 0, total_rejected=0;
6582 cpl_polynomial *poly = NULL;
6583 cpl_vector *temp_pos = NULL, *temp_val = NULL;
6584 double *positions = NULL;
6585 double *values = NULL;
6586 int ngood=0;
6587
6588 XSH_ASSURE_NOT_NULL( pos_vect);
6589 XSH_ASSURE_NOT_NULL( val_vect);
6590
6591 XSH_ASSURE_NOT_NULL( polyp);
6592 XSH_ASSURE_NOT_NULL( flagsp);
6593
6594 check( poly = xsh_polynomial_fit_1d_create( pos_vect, val_vect, deg,
6595 chisq));
6596 check( size = cpl_vector_get_size( pos_vect));
6597
6598 XSH_CALLOC( flags, int, size);
6599 XSH_CALLOC( positions, double, size);
6600 XSH_CALLOC( values, double, size);
6601
6602 ngood = size;
6603 sigma = sqrt(*chisq);
6604
6605 xsh_msg_dbg_medium("Iteration %d/%d", 0, niter);
6606 xsh_msg_dbg_medium("Accepted fraction %f Polynomial deg %d sigma %f",
6607 1.0, deg, sigma);
6608
6609 for( i=1; i<= niter; i++) {
6610 xsh_msg_dbg_medium("Iteration %d/%d", i, niter);
6611 nb_rejected = 0;
6612
6613 for( j=0; j< size; j++){
6614 double pos=0.0, val=0.0, pol_val=0.0;
6615
6616 check( pos = cpl_vector_get( pos_vect, j));
6617 check( val = cpl_vector_get( val_vect, j));
6618 check( pol_val = cpl_polynomial_eval_1d( poly, pos, NULL));
6619
6620 if ( flags[j] == 0 && fabs( pol_val-val) > kappa*sigma){
6621 nb_rejected++;
6622 flags[j]=2;
6623 }
6624 }
6625 if ( nb_rejected == 0){
6626 xsh_msg_dbg_medium("No more points are rejected. Iterations are stopped.");
6627 break;
6628 }
6629 total_rejected += nb_rejected;
6630 frac = 1-(double)total_rejected/(double)size;
6631 if (frac < frac_min){
6632 xsh_msg("Minimal fraction of accepted points %f is reached (%f). Iterations are stopped",
6633 frac_min, frac);
6634 break;
6635 }
6636
6637 ngood = 0;
6638 for( j=0; j< size; j++){
6639 if( flags[j] == 0){
6640 positions[ngood] = cpl_vector_get( pos_vect, j);
6641 values[ngood] = cpl_vector_get( val_vect, j);
6642 ngood++;
6643 }
6644 else{
6645 flags[j] = 1;
6646 }
6647 }
6648 check( temp_pos = cpl_vector_wrap( ngood, positions));
6649 check( temp_val = cpl_vector_wrap( ngood, values));
6650
6651 xsh_free_polynomial( &poly);
6652
6653 check( poly = xsh_polynomial_fit_1d_create( temp_pos, temp_val, deg,
6654 chisq));
6655
6656 sigma = sqrt(*chisq);
6657
6658 xsh_msg_dbg_medium("Accepted fraction %f Polynomial deg %d sigma %f",
6659 frac, deg, sigma);
6660 xsh_unwrap_vector( &temp_pos);
6661 xsh_unwrap_vector( &temp_val);
6662 }
6663
6664 for( j=0; j< size; j++){
6665 if( flags[j] == 2){
6666 flags[j] = 0;
6667 }
6668 }
6669 *polyp = poly;
6670 *flagsp = flags;
6671
6672 cleanup:
6673 XSH_FREE( positions);
6674 XSH_FREE( values);
6675 xsh_unwrap_vector( &temp_pos);
6676 xsh_unwrap_vector( &temp_val);
6677 return;
6678}
6679
6680cpl_error_code
6681xsh_rectify_params_set_defaults(cpl_parameterlist* pars,
6682 const char* rec_id,
6683 xsh_instrument* inst,
6684 xsh_rectify_param * rectify_par)
6685{
6686 cpl_parameter* p=NULL;
6687
6688 check(p=xsh_parameters_find(pars,rec_id,"rectify-bin-slit"));
6689 if(cpl_parameter_get_double(p) <= 0) {
6690 if (xsh_instrument_get_arm(inst) == XSH_ARM_UVB){
6692 cpl_parameter_set_double(p,XSH_SLIT_BIN_SIZE_PIPE_UVB);
6693 } else if (xsh_instrument_get_arm(inst) == XSH_ARM_VIS){
6695 cpl_parameter_set_double(p,XSH_SLIT_BIN_SIZE_PIPE_VIS);
6696 } else if (xsh_instrument_get_arm(inst) == XSH_ARM_NIR){
6698 cpl_parameter_set_double(p,XSH_SLIT_BIN_SIZE_PIPE_NIR);
6699 }
6700 }
6701 check(p=xsh_parameters_find(pars,rec_id,"rectify-bin-lambda"));
6702 if(cpl_parameter_get_double(p) <= 0) {
6703 if (xsh_instrument_get_arm(inst) == XSH_ARM_UVB){
6705 cpl_parameter_set_double(p,XSH_WAVE_BIN_SIZE_PIPE_UVB);
6706 } else if (xsh_instrument_get_arm(inst) == XSH_ARM_VIS){
6708 cpl_parameter_set_double(p,XSH_WAVE_BIN_SIZE_PIPE_VIS);
6709 } else if (xsh_instrument_get_arm(inst) == XSH_ARM_NIR){
6711 cpl_parameter_set_double(p,XSH_WAVE_BIN_SIZE_PIPE_NIR);
6712 }
6713 }
6714
6715 cleanup:
6716
6717 return cpl_error_get_code();
6718
6719}
6720
6721
6722cpl_error_code
6724 const char* rec_id,
6725 xsh_instrument* inst,
6726 xsh_remove_crh_single_param * crh_single_par)
6727 {
6728 cpl_parameter* p=NULL;
6729
6730 check(p=xsh_parameters_find(pars,rec_id,"removecrhsingle-niter"));
6731 if (cpl_parameter_get_int(p) < 0) {
6732 if (xsh_instrument_get_arm(inst) == XSH_ARM_NIR){
6733 crh_single_par->nb_iter=XSH_REMOVE_CRH_SINGLE_NIR;
6734 cpl_parameter_set_int(p,XSH_REMOVE_CRH_SINGLE_NIR);
6735 } else if (xsh_instrument_get_arm(inst) == XSH_ARM_UVB ||
6737 crh_single_par->nb_iter=XSH_REMOVE_CRH_SINGLE_UVB_VIS;
6738 cpl_parameter_set_int(p,XSH_REMOVE_CRH_SINGLE_UVB_VIS);
6739 }
6740 }
6741
6742 cleanup:
6743
6744 return cpl_error_get_code();
6745
6746 }
6747
6748/******************************************************************************/
6749struct data {
6750 size_t n;
6751 double * y;
6752 double * x;
6753 int deg;
6754};
6755
6756static int
6757expb_f (const gsl_vector * x, void *data,
6758 gsl_vector * f)
6759{
6760 int i;
6761 int n = ((struct data *)data)->n;
6762 double *y = ((struct data *)data)->y;
6763 double *xtab = ((struct data *) data)->x;
6764
6765 double area = gsl_vector_get (x, 0);
6766 double a = gsl_vector_get (x, 1);
6767 double b = gsl_vector_get( x,2);
6768 double c = gsl_vector_get( x,3);
6769 double x0 = gsl_vector_get( x,4);
6770 double sigma = gsl_vector_get( x,5);
6771
6772 for (i = 0; i < n; i++)
6773 {
6774 /* Model Yi = area/sqrt(2PI*sigma^2)* exp(-(x-x0)^2/(2sigma^2) + a + bx +cx^2 */
6775 double t = xtab[i];
6776 double height = area/sqrt(2*M_PI*sigma*sigma);
6777 double W = ((t-x0)*(t-x0))/(2*sigma*sigma);
6778
6779 double Yi = height*exp(-W)+a+b*t+c*t*t;
6780
6781 gsl_vector_set (f, i, Yi - y[i]);
6782 }
6783
6784 return GSL_SUCCESS;
6785}
6786
6787static int
6788expb_df (const gsl_vector * x, void *data,
6789 gsl_matrix * J)
6790{
6791 int i;
6792 int n = ((struct data *)data)->n;
6793 double *xtab = ((struct data *) data)->x;
6794
6795 double area = gsl_vector_get (x, 0);
6796 double x0 = gsl_vector_get (x, 4);
6797 double sigma = gsl_vector_get( x,5);
6798 int deg = ((struct data *)data)->deg;
6799 for (i = 0; i < n; i++)
6800 {
6801 /* Jacobian matrix J(i,j) = dfi / dxj, */
6802 /* where fi = (Yi - yi)/sigma[i], */
6803 /* Yi = A * exp(-lambda * i) + b */
6804 /* and the xj are the parameters (A,lambda,b) */
6805 double t = xtab[i];
6806
6807 double W = ((t-x0)*(t-x0))/(2*sigma*sigma);
6808 double e = 0.0;
6809
6810
6811 /* df /area */
6812 e = exp(-W)/sqrt(2*M_PI*sigma*sigma);
6813 gsl_matrix_set (J, i, 0, e);
6814
6815 /* df / da */
6816 e = 1;
6817 gsl_matrix_set (J, i, 1, e);
6818
6819 /* df /db */
6820 if (deg >= 1){
6821 e = t;
6822 }
6823 else {
6824 e = 0;
6825 }
6826 gsl_matrix_set (J, i, 2, e);
6827
6828 /* df/dc */
6829 if (deg == 2) {
6830 e = t*t;
6831 }
6832 else {
6833 e = 0;
6834 }
6835 gsl_matrix_set (J, i, 3, e);
6836
6837 /* df / x0 */
6838 e = area/(2*M_PI*sigma)*(t-x0)/sigma*exp(-0.5*pow((t-x0)/sigma,2));
6839 gsl_matrix_set (J, i, 4, e);
6840
6841 /* df /sigma */
6842 e = (sqrt(2)*area*x0*x0-pow(2,1.5)*area*t*x0+sqrt(2)*area*t*t-sqrt(2)*area*sigma*sigma)*exp(-W)/(2*sqrt(M_PI)*sigma*sigma*sigma*sigma);
6843 gsl_matrix_set (J, i, 5, e);
6844
6845 }
6846 return GSL_SUCCESS;
6847}
6848
6849static int
6850expb_fdf (const gsl_vector * x, void *data,
6851 gsl_vector * f, gsl_matrix * J)
6852{
6853 expb_f (x, data, f);
6854 expb_df (x, data, J);
6855
6856 return GSL_SUCCESS;
6857}
6858/******************************************************************************/
6859
6860/******************************************************************************/
6861/******************************************************************************/
6862void xsh_gsl_init_gaussian_fit( cpl_vector *xpos_vect, cpl_vector *ypos_vect,
6863 double *init_par)
6864{
6865 double flux_max, flux_min, intensity;
6866 int i, size;
6867 double init_area, init_sigma, init_x0=0, init_offset;
6868 double flux_sum =0.0;
6869 double hflux, flux25, flux75;
6870 double init25=0, init75=0;
6871
6872 XSH_ASSURE_NOT_NULL( xpos_vect);
6873 XSH_ASSURE_NOT_NULL( ypos_vect);
6874
6875 size = cpl_vector_get_size( xpos_vect);
6876 flux_min = cpl_vector_get_min( ypos_vect);
6877 flux_max = cpl_vector_get_max( ypos_vect);
6878 intensity = flux_max-flux_min;
6879
6880 init_offset = flux_min;
6881
6882 for (i = 0; i < size; i++){
6883 double yval;
6884
6885 yval = cpl_vector_get( ypos_vect, i);
6886 flux_sum += yval-init_offset;
6887 }
6888
6889 hflux = flux_sum/2.0;
6890 flux25 = flux_sum*0.25;
6891 flux75 = flux_sum*0.75;
6892 flux_sum =0.0;
6893
6894 for (i = 0; i < size; i++){
6895 double yval;
6896
6897 yval = cpl_vector_get( ypos_vect, i);
6898
6899 flux_sum += yval-init_offset;
6900
6901 if ( (init25 == 0) && flux_sum > flux25){
6902 init25 = (i+i-1)/2.0;
6903 }
6904
6905 if ( (init_x0 == 0) && flux_sum > hflux){
6906 init_x0 = (i+i-1)/2.0;
6907 }
6908
6909 if ( (init75 == 0) && flux_sum > flux75){
6910 init75 = (i+i-1)/2.0;
6911 break;
6912 }
6913
6914 }
6915 //could replace 0.6744 with HDRL/CPL function for FWHM to SIGMA conversion
6916 init_sigma = (init75-init25)/(2*0.6744);
6917 init_area = intensity*sqrt(2*M_PI*init_sigma*init_sigma);
6918
6919 xsh_msg_dbg_high("DV FIT area %f x0 %f sigma %f offset %f",
6920 init_area, init_x0, init_sigma, init_offset);
6921
6922 init_par[0] = init_area;
6923 init_par[1] = init_offset;
6924 init_par[2] = 0;
6925 init_par[3] = 0;
6926 init_par[4] = init_x0;
6927 init_par[5] = init_sigma;
6928
6929 cleanup:
6930 return;
6931}
6932/******************************************************************************/
6933
6934/******************************************************************************/
6935/******************************************************************************/
6936void xsh_gsl_fit_gaussian( cpl_vector *xpos_vect, cpl_vector *ypos_vect,
6937 int deg,
6938 double *params, double *errs, int *status)
6939{
6940 const gsl_multifit_fdfsolver_type *T;
6941 gsl_multifit_fdfsolver *s=NULL;
6942 int iter = 0;
6943 const size_t p = 6;
6944 gsl_matrix *covar = gsl_matrix_alloc (p, p);
6945
6946
6947#if defined GSL_MAJOR_VERSION && GSL_MAJOR_VERSION >= 2
6948 gsl_matrix *J;
6949#endif
6950 int n=0;
6951 struct data d = { n, NULL, NULL,deg};
6952 gsl_multifit_function_fdf f;
6953 gsl_vector* x = NULL;
6954 double area, offset, b, c, x0, sigma;
6955 double chi, dof, cte;
6956 int size;
6957 double *xpos = NULL;
6958 double *ypos = NULL;
6959
6960 /* gsl fit */
6961 XSH_ASSURE_NOT_NULL( xpos_vect);
6962 XSH_ASSURE_NOT_NULL( ypos_vect);
6963 XSH_ASSURE_NOT_NULL( params);
6964 XSH_ASSURE_NOT_NULL( errs);
6965 XSH_ASSURE_NOT_NULL( status);
6966
6967
6968 size = cpl_vector_get_size( xpos_vect);
6969 xpos = cpl_vector_get_data( xpos_vect);
6970 ypos = cpl_vector_get_data( ypos_vect);
6971
6972 x = gsl_vector_calloc (p);
6973
6974 area = params[0];
6975 offset = params[1];
6976 b = params[2];
6977 c = params[3];
6978 x0 = params[4];
6979 sigma = params[5];
6980
6981 gsl_vector_set( x, 0, area);
6982 gsl_vector_set( x, 1, offset);
6983 gsl_vector_set( x, 2, b);
6984 gsl_vector_set( x, 3, c);
6985 gsl_vector_set( x, 4, x0);
6986 gsl_vector_set( x, 5, sigma);
6987
6988 n = size;
6989 d.n = size;
6990 d.y = ypos;
6991 d.x = xpos;
6992 d.deg = deg;
6993
6994 f.f = &expb_f;
6995 f.df = &expb_df;
6996 f.fdf = &expb_fdf;
6997 f.n = n;
6998 f.p = p;
6999 f.params = &d;
7000
7001 /* This is the data to be fitted */
7002 T = gsl_multifit_fdfsolver_lmsder;
7003 s = gsl_multifit_fdfsolver_alloc (T, n, p);
7004 gsl_multifit_fdfsolver_set (s, &f, x);
7005
7006 xsh_msg_dbg_high ("iter: %3u area % 15.8f a % 15.8f b % 15.8f c % 15.8f x0 % 15.8f sigma % 15.8f |f(x)| = %g\n",
7007 iter,
7008 gsl_vector_get (s->x, 0),
7009 gsl_vector_get (s->x, 1),
7010 gsl_vector_get (s->x, 2),
7011 gsl_vector_get (s->x, 3),
7012 gsl_vector_get (s->x, 4),
7013 gsl_vector_get (s->x, 5),
7014 gsl_blas_dnrm2 (s->f));
7015 do
7016 {
7017 iter++;
7018 *status = gsl_multifit_fdfsolver_iterate (s);
7019
7020 xsh_msg_dbg_high ("iter: %3u area % 15.8f a % 15.8f b % 15.8f c % 15.8f x0 % 15.8f sigma % 15.8f |f(x)| = %g\n",
7021 iter,
7022 gsl_vector_get (s->x, 0),
7023 gsl_vector_get (s->x, 1),
7024 gsl_vector_get (s->x, 2),
7025 gsl_vector_get (s->x, 3),
7026 gsl_vector_get (s->x, 4),
7027 gsl_vector_get (s->x, 5),
7028 gsl_blas_dnrm2 (s->f));
7029
7030 if (*status)
7031 break;
7032
7033 *status = gsl_multifit_test_delta (s->dx, s->x,
7034 1e-2, 1e-2);
7035
7036 }
7037 while ( *status == GSL_CONTINUE && iter < 500);
7038
7039#if defined GSL_MAJOR_VERSION && GSL_MAJOR_VERSION >= 2
7040 J = gsl_matrix_alloc(n, p);
7041 gsl_multifit_fdfsolver_jac(s, J);
7042 gsl_multifit_covar (J, 0.0, covar);
7043 gsl_matrix_free (J);
7044#else
7045 gsl_multifit_covar (s->J, 0.0, covar);
7046#endif
7047
7048
7049 params[0] = gsl_vector_get( s->x, 0);
7050 params[1] = gsl_vector_get( s->x, 1);
7051 params[2] = gsl_vector_get( s->x, 2);
7052 params[3] = gsl_vector_get( s->x, 3);
7053 params[4] = gsl_vector_get( s->x, 4);
7054 params[5] = gsl_vector_get( s->x, 5);
7055
7056 chi = gsl_blas_dnrm2(s->f);
7057 dof = n-p;
7058 cte = GSL_MAX_DBL(1, chi / sqrt(dof));
7059
7060 errs[0] = cte * sqrt(gsl_matrix_get(covar,0,0));
7061 errs[1] = cte * sqrt(gsl_matrix_get(covar,1,1));
7062 errs[2] = cte * sqrt(gsl_matrix_get(covar,2,2));
7063 errs[3] = cte * sqrt(gsl_matrix_get(covar,3,3));
7064 errs[4] = cte * sqrt(gsl_matrix_get(covar,4,4));
7065 errs[5] = cte * sqrt(gsl_matrix_get(covar,5,5));
7066
7067
7068 cleanup:
7069
7070 gsl_multifit_fdfsolver_free (s);
7071 gsl_matrix_free (covar);
7072 gsl_vector_free( x);
7073 return;
7074}
7075
7100double*
7102 double * line_i,
7103 int width_i,
7104 double * line_t,
7105 int width_t,
7106 int half_search,
7107 int normalise,
7108 double * xcorr_max,
7109 double * delta
7110)
7111{
7112 double * xcorr ;
7113 double mean_i, mean_t ;
7114 double rms_i, rms_t ;
7115 double sum, sqsum ;
7116 double norm ;
7117 int maxpos ;
7118 int nsteps ;
7119 int i ;
7120 int step ;
7121 int nval ;
7122 int STEP_MIN=-half_search;
7123 int STEP_MAX=half_search;
7124
7125 /* Compute normalization factors */
7126 sum = sqsum = 0.00 ;
7127 for (i=0 ; i<width_i ; i++) {
7128 sum += line_i[i] ;
7129 sqsum += line_i[i] * line_i[i];
7130 }
7131
7132 mean_i = sum / (double) width_i ;
7133 sqsum /= (double)width_i ;
7134 rms_i = sqsum - mean_i*mean_i ;
7135
7136 sum = sqsum = 0.00 ;
7137 for (i=0 ; i<width_t ; i++) {
7138 sum += line_t[i] ;
7139 sqsum += line_t[i] * line_t[i];
7140 }
7141 mean_t = sum / (double)width_t ;
7142 sqsum /= (double)width_t ;
7143 rms_t = sqsum - mean_t*mean_t ;
7144
7145 norm = 1.00 / sqrt(rms_i * rms_t);
7146
7147 nsteps = (STEP_MAX - STEP_MIN) +1 ;
7148 xcorr = cpl_malloc(nsteps * sizeof(double));
7149 if(normalise==0) {
7150 mean_t=0;
7151 norm=1;
7152 }
7153 for (step=STEP_MIN ; step<=STEP_MAX ; step++) {
7154 xcorr[step-STEP_MIN] = 0.00 ;
7155 nval = 0 ;
7156 for (i=0 ; i<width_t ; i++) {
7157 if ((i+step > 0) &&
7158 (i+step < width_i)) {
7159 xcorr[step-STEP_MIN] += (line_t[i] - mean_t) *
7160 (line_i[i+step] - mean_i) *
7161 norm ;
7162 nval++ ;
7163 }
7164 }
7165 xcorr[step-STEP_MIN] /= (double) nval ;
7166 }
7167
7168 *xcorr_max = xcorr[0] ;
7169 maxpos = 0 ;
7170 for (i=0 ; i<nsteps ; i++) {
7171 if (xcorr[i]>(*xcorr_max)) {
7172 maxpos = i ;
7173 *xcorr_max = xcorr[i];
7174 }
7175 }
7176
7177 cpl_vector* vcor=cpl_vector_wrap(nsteps,xcorr);
7178 double a=xcorr[maxpos-1];
7179 double b=xcorr[maxpos+1];
7180 double c=xcorr[maxpos];
7181 double fraction=(a-b)/(2.*a+2.*b-4.*c);
7182 //cpl_vector_save(vcor,"vcor_correlate.fits",CPL_BPP_IEEE_FLOAT,NULL,CPL_IO_DEFAULT);
7183 cpl_vector_unwrap(vcor);
7184
7185 //xsh_msg("STEP_MIN=%d maxpos=%d",STEP_MIN,maxpos);
7186 //xsh_msg("fraction=%g a=%g b=%g c=%g delta=%g",fraction,a,b,c,0.5*(b-a));
7187 (*delta) = (double)STEP_MIN + (double)maxpos;
7188 *delta-=fraction;
7189 //xsh_msg("fraction=%g a=%g b=%g c=%g diff=%g delta=%g",fraction,a,b,c,0.5*(b-a),*delta);
7190 return xcorr;
7191}
7192
7193/* Helper function to sort frameset by MJD.
7194 Used by cpl_frameset_sort in get_average_airm_iwv_from_raws().
7195*/
7196int raw_mjd_frame_compare(const cpl_frame* f1,const cpl_frame* f2){
7197 int result = 0;
7198 cpl_propertylist* p1 = cpl_propertylist_load(cpl_frame_get_filename(f1),0);
7199 cpl_propertylist* p2 = cpl_propertylist_load(cpl_frame_get_filename(f2),0);
7200 if(p1 != NULL && p2 != NULL && cpl_propertylist_has(p1,"MJD-OBS") && cpl_propertylist_has(p2,"MJD-OBS")){
7201 double mjd1 = cpl_propertylist_get_double(p1,"MJD-OBS");
7202 double mjd2 = cpl_propertylist_get_double(p2,"MJD-OBS");
7203 if(mjd1 < mjd2) {
7204 result = -1;
7205 } else if (mjd1 > mjd2){
7206 result = 1;
7207 }
7208 }
7209 //otherwise they are equal (0)
7210 cpl_propertylist_delete(p1);
7211 cpl_propertylist_delete(p2);
7212 return result;
7213}
7214
7215
7216cpl_error_code get_average_qc_from_raws(cpl_frameset* fset,xsh_instrument* instrument,cpl_propertylist* qclist){
7217 /* Create a duplicate of the frameset sorted by MJD */
7218 cpl_frameset* fraws = cpl_frameset_duplicate(fset);
7219 cpl_frameset_sort(fraws,raw_mjd_frame_compare);
7220
7221 int nraws = cpl_frameset_get_size(fraws);
7222 if(nraws > 0){
7223 //calculate QC NUM SAT
7224 int nsat_max = 0;
7225
7226 for (int f = 0; f < nraws; f++) {
7227 cpl_frame* frm = cpl_frameset_get_frame(fset, f);
7228 const char* fname = cpl_frame_get_filename(frm);
7229 cpl_image* img = cpl_image_load(fname,CPL_TYPE_DOUBLE,0,0);
7230 cpl_propertylist* hdr = cpl_propertylist_load(fname,0);
7231 if(img){
7232 double thresh = 60000.0;
7234 thresh = 42000;
7235 }
7236
7237 double* idata = cpl_image_get_data_double(img);
7238 int nsat = 0;
7239 int nx = cpl_image_get_size_x(img);
7240 int ny = cpl_image_get_size_y(img);
7241 for(int i=0;i<nx*ny;i++){
7242 if(idata[i] > thresh){
7243 nsat++;
7244 }
7245 }
7246 if(nsat > nsat_max){
7247 nsat_max = nsat;
7248 }
7249 }
7250 cpl_image_delete(img);
7251 cpl_propertylist_delete(hdr);
7252 }
7253
7254 cpl_propertylist_update_int(qclist,"ESO QC NUM SAT",nsat_max);
7255
7256 //get first and last raw frames
7257 cpl_frame* raw1 = cpl_frameset_get_frame(fraws,0);
7258 cpl_frame* raw2 = cpl_frameset_get_frame(fraws,nraws-1);
7259 cpl_propertylist* rhdr1 = cpl_propertylist_load(cpl_frame_get_filename(raw1),0);
7260 cpl_propertylist* rhdr2 = cpl_propertylist_load(cpl_frame_get_filename(raw2),0);
7261 if (rhdr1 != NULL && rhdr2 != NULL){
7262 if(cpl_propertylist_has(rhdr1,"ESO TEL AIRM START") && cpl_propertylist_has(rhdr2,"ESO TEL AIRM END")){
7263 cpl_propertylist_update_double(qclist,"ESO QC AIRM AVG",
7264 0.5*(cpl_propertylist_get_double(rhdr1,"ESO TEL AIRM START") + cpl_propertylist_get_double(rhdr2,"ESO TEL AIRM END")));
7265 }
7266 if(cpl_propertylist_has(rhdr1,"ESO TEL AIRM START") && !cpl_propertylist_has(rhdr2,"ESO TEL AIRM END")){
7267 cpl_propertylist_update_double(qclist,"ESO QC AIRM AVG",cpl_propertylist_get_double(rhdr1,"ESO TEL AIRM START"));
7268 }
7269 if(!cpl_propertylist_has(rhdr1,"ESO TEL AIRM START") && cpl_propertylist_has(rhdr2,"ESO TEL AIRM END")){
7270 cpl_propertylist_update_double(qclist,"ESO QC AIRM AVG",cpl_propertylist_get_double(rhdr2,"ESO TEL AIRM END"));
7271 }
7272
7273 if(cpl_propertylist_has(rhdr1,"ESO TEL AMBI IWV START") && cpl_propertylist_has(rhdr2,"ESO TEL AMBI IWV END")){
7274 cpl_propertylist_update_double(qclist,"ESO QC IWV AVG",
7275 0.5*(cpl_propertylist_get_double(rhdr1,"ESO TEL AMBI IWV START") + cpl_propertylist_get_double(rhdr2,"ESO TEL AMBI IWV END")));
7276 }
7277 if(cpl_propertylist_has(rhdr1,"ESO TEL AMBI IWV START") && !cpl_propertylist_has(rhdr2,"ESO TEL AMBI IWV END")){
7278 cpl_propertylist_update_double(qclist,"ESO QC IWV AVG",cpl_propertylist_get_double(rhdr1,"ESO TEL AMBI IWV START"));
7279 }
7280 if(!cpl_propertylist_has(rhdr1,"ESO TEL AMBI IWV START") && cpl_propertylist_has(rhdr2,"ESO TEL AMBI IWV END")){
7281 cpl_propertylist_update_double(qclist,"ESO QC IWV AVG",cpl_propertylist_get_double(rhdr2,"ESO TEL AMBI IWV END"));
7282 }
7283
7284
7285 if(cpl_propertylist_has(rhdr1,"ESO TEL AMBI FWHM START") && cpl_propertylist_has(rhdr2,"ESO TEL AMBI FWHM END")){
7286 cpl_propertylist_update_double(qclist,"ESO QC FWHM AVG",
7287 0.5*(cpl_propertylist_get_double(rhdr1,"ESO TEL AMBI FWHM START") + cpl_propertylist_get_double(rhdr2,"ESO TEL AMBI FWHM END")));
7288 }
7289 if(cpl_propertylist_has(rhdr1,"ESO TEL AMBI FWHM START") && !cpl_propertylist_has(rhdr2,"ESO TEL AMBI FWHM END")){
7290 cpl_propertylist_update_double(qclist,"ESO QC FWHM AVG",cpl_propertylist_get_double(rhdr1,"ESO TEL AMBI FWHM START"));
7291 }
7292 if(!cpl_propertylist_has(rhdr1,"ESO TEL AMBI FWHM START") && cpl_propertylist_has(rhdr2,"ESO TEL AMBI FWHM END")){
7293 cpl_propertylist_update_double(qclist,"ESO QC FWHM AVG",cpl_propertylist_get_double(rhdr2,"ESO TEL AMBI FWHM END"));
7294 }
7295 }
7296
7297
7298 cpl_propertylist_delete(rhdr1);
7299 cpl_propertylist_delete(rhdr2);
7300 }
7301 cpl_frameset_delete(fraws);
7302
7303 return cpl_error_get_code();
7304}
7305
7306cpl_error_code get_chromatic_eff(cpl_frame* eff,cpl_propertylist* qclist){
7307 if(eff != NULL){
7308 cpl_propertylist* ehdr = cpl_propertylist_load(cpl_frame_get_filename(eff),0);
7309 if(ehdr != NULL && cpl_propertylist_has(ehdr,"ESO QC EFF MED ORD 1") && cpl_propertylist_has(ehdr,"ESO QC EFF MED ORD 9")){
7310 double ord1 = cpl_propertylist_get_double(ehdr,"ESO QC EFF MED ORD 1");
7311 double ord9 = cpl_propertylist_get_double(ehdr,"ESO QC EFF MED ORD 9");
7312 if(ord1 != 0.0){
7313 cpl_propertylist_update_double(qclist,"ESO QC CHROMATIC EFF",ord9/ord1);
7314 }
7315 }
7316 cpl_propertylist_delete(ehdr);
7317 }
7318 return cpl_error_get_code();
7319}
7320
7321cpl_error_code
7322calc_curve_qc(cpl_image* im,xsh_instrument* instrument,cpl_propertylist* qclist)
7323{
7324 cpl_error_reset();
7325 //Check that the image loaded but don't quit if missing
7326 if(im != NULL){
7327 //x positions at which to fit gaussians across the spatial direction
7328 //default values are for UVB
7329 int xpos[2] = {2000,12000};
7330 double ypos[2];
7331 //consider 100 pix wide window
7332 int wx =100;
7333 int dw = cpl_image_get_size_x(im);
7334 int dy = cpl_image_get_size_y(im);
7335
7336 //using half the image width here is robust against any binning issues we may encounter
7337 double xcen = dw*0.5;
7338 //xcen = 6427
7339
7341 xpos[0] = 1000;
7342 xpos[1] = 22000;
7343 //xcen = 12159;
7344 }
7346 xpos[0] = 3500;
7347 xpos[1] = 19000;
7348 //xcen = 12375;
7349 }
7350 /* populate ypos containing centroid positions of spatial dir trace */
7351 int llx, lly, urx, ury;
7352 cpl_error_code err = CPL_ERROR_NONE;
7353 for (int idx=0;idx < 2;idx++){
7354 llx = xpos[idx]-wx*0.5;
7355 urx = xpos[idx]+wx*0.5;
7356
7357 //need to restrict these to the central trace; but need to account for restricted y range later...
7358 lly = (int)(dy*0.5-15);
7359 ury = (int)(dy*0.5+15);
7360
7361 //ensure the median deals with cosmics and other bad pixels
7362 cpl_image* windowed = cpl_image_extract(im,llx,lly,urx,ury);
7363 cpl_image* wim = cpl_image_collapse_median_create(windowed,1,0,0);
7364 cpl_image_delete(windowed);
7365
7366 double* wdata = cpl_image_get_data_double(wim);
7367 if(wdata == NULL){
7368 cpl_msg_info(cpl_func,"failed to load data from image window");
7369 }
7370
7371 //make sure we work using the new image dimensions, rather than the full dy
7372 int wdata_dy = cpl_image_get_size_y(wim);
7373 //vectors containing the slit data
7374 cpl_vector* sx = cpl_vector_new(wdata_dy);
7375 cpl_vector* sy = cpl_vector_wrap(wdata_dy,wdata);
7376
7377 for (int i=0;i<wdata_dy;i++){
7378 cpl_vector_set(sx,i,i);
7379 }
7380 double cenpos=0.5*wdata_dy;
7381 double sigma=0.0;
7382 double area=0.0;
7383 double offset=0.0;
7384 //cpl_msg_info(cpl_func,"sy[0] %e sy[1]: %e\n",cpl_vector_get(sy,0),cpl_vector_get(sy,1));
7385 err = cpl_vector_fit_gaussian(sx,NULL,sy,NULL,CPL_FIT_ALL,&cenpos,&sigma,&area,&offset,NULL,NULL,NULL);
7386 //cpl_msg_info(cpl_func,"fit %d: cenpos: %e err: %s\n",idx,cenpos+lly,cpl_error_get_message());
7387 //adding lly puts the cenpos back in the absolute y coord sys
7388 ypos[idx] = cenpos+lly;
7389 cpl_vector_delete(sx);
7390 cpl_vector_unwrap(sy);
7391 cpl_image_delete(wim);
7392 //cpl_free(wdata);
7393 }
7394 if(err == CPL_ERROR_NONE) {
7395 //since we have only two points, we can exactly calculate the straight line
7396 double b = (ypos[1]-ypos[0])/(xpos[1]-xpos[0]);
7397 double a = ypos[0]-b*(xpos[0]-xcen);
7398 cpl_propertylist_update_double(qclist,"ESO QC CURVE 0",a);
7399 cpl_propertylist_update_double(qclist,"ESO QC CURVE 1",b);
7400 cpl_propertylist_update_double(qclist,"ESO QC CURVE X",xcen);
7401 }
7402 }
7403 cpl_error_reset();
7404 return cpl_error_get_code();
7405}
7406
7407/* Functions needed by cpl_fit_lvmq */
7408static int qc_linfunc(const double x[], const double p[], double *f)
7409{
7410 //a + b*(x-x0)
7411 //p[0] == a
7412 //p[1] == b
7413 //p[2] == x0 (constant, not fit)
7414 *f = p[0] + p[1]*(x[0]-p[2]);
7415 return 0;
7416}
7417static int qc_dlinfunc(const double x[], const double p[], double f[])
7418{
7419 // d/da(qc_linfunc)
7420 f[0] = 1;
7421 // d/db(qc_linfunc)
7422 f[1] = x[0]-p[2];
7423 // d/dx0(qc_linfunc)
7424 f[2] = -p[1];
7425 return 0;
7426}
7427
7428cpl_error_code
7429calc_flat_slit_qc(cpl_image* im,int xa1, int xa2, cpl_propertylist* qclist)
7430{
7431 int dy = cpl_image_get_size_y(im);
7432 double chi_sq;
7433 int drop_ll = (dy*0.5)-10;
7434 int drop_ur = dy-((dy*0.5)+10);
7435 cpl_image* dup = cpl_image_duplicate(im);
7436 cpl_image* slit = cpl_image_collapse_median_create(dup,0,drop_ll,drop_ur);
7437
7438 float * sdata = cpl_image_get_data_float(slit);
7439 int coord0 = (xa2-xa1)/2;
7440 int nvals = xa2-xa1;
7441 cpl_vector* sy = cpl_vector_new(nvals);
7442 cpl_vector* sye = cpl_vector_new(nvals);
7443 cpl_vector* sx = cpl_vector_new(nvals);
7444
7445 int count = 0;
7446 for (int i=xa1;i<xa2;i++){
7447 cpl_vector_set(sx,count,i);
7448 cpl_vector_set(sy,count,sdata[i]);
7449 //sye contains errors needed to compute covariance matrix
7450 cpl_vector_set(sye,count,1.0);
7451 count = count + 1;
7452 }
7453 //Calculate the RMS using a copy of the slit y values
7454 cpl_vector* sycalc = cpl_vector_duplicate(sy);
7455 double mean = cpl_vector_get_mean(sycalc);
7456 cpl_vector_subtract_scalar(sycalc,mean);
7457 cpl_vector_multiply(sycalc,sycalc);
7458 double rms = sqrt(cpl_vector_get_mean(sycalc));
7459
7460 cpl_propertylist_append_double(qclist,"ESO QC FLAT SLIT RMS",rms);
7461
7462 cpl_matrix* coeff = cpl_matrix_new(nvals,1);
7463 for (int i=0;i<nvals;i++){
7464 cpl_matrix_set(coeff,i,0,cpl_vector_get(sx,i));
7465 }
7466
7467 cpl_matrix* covar = cpl_matrix_new(3,3);
7468
7469 //Variables for the fitting function. Initial guess for each.
7470 cpl_vector* guess = cpl_vector_new(3);
7471 cpl_vector_set(guess,0,0);
7472 cpl_vector_set(guess,1,0);
7473 cpl_vector_set(guess,2,coord0);
7474 //Only fit the first two and not coord0 (constant)
7475 int ia[3] = {1,1,0};
7476 cpl_error_code err= cpl_fit_lvmq(coeff,NULL,sy,sye,guess,ia,qc_linfunc,qc_dlinfunc,CPL_FIT_LVMQ_TOLERANCE,CPL_FIT_LVMQ_COUNT,CPL_FIT_LVMQ_MAXITER,NULL,&chi_sq,&covar);
7477 /*if(err == CPL_ERROR_NULL_INPUT){ cpl_msg_info(cpl_func,"CPL_ERROR_NULL_INPUT"); }
7478 if(err == CPL_ERROR_ILLEGAL_INPUT){ cpl_msg_info(cpl_func,"CPL_ERROR_ILLEGAL_INPUT"); }
7479 if(err == CPL_ERROR_INCOMPATIBLE_INPUT){ cpl_msg_info(cpl_func,"CPL_ERROR_INCOMPATIBLE_INPUT"); }
7480 if(err == CPL_ERROR_ILLEGAL_OUTPUT){ cpl_msg_info(cpl_func,"CPL_ERROR_ILLEGAL_OUTPUT"); }
7481 if(err == CPL_ERROR_CONTINUE){ cpl_msg_info(cpl_func,"CPL_ERROR_CONTINUE"); }
7482 if(err == CPL_ERROR_SINGULAR_MATRIX){ cpl_msg_info(cpl_func,"CPL_ERROR_SINGULAR_MATRIX"); }
7483 */
7484
7485 /*convert the gradient error to that matching the output of scipy.optimization.curve_fit(absolute_sigma=False)
7486 N.B. the default covariance matrix returned from cpl_fit_lvmq gives results
7487 corresponding to scipy.optimization.curve_fit(absolute_sigma=True)
7488 The previous QC scripts were run with default absolute_sigma=False, so we use grad_err_other here
7489 */
7490 //double grad_err=sqrt(cpl_matrix_get(covar,1,1));
7491 double grad_err_other = sqrt(cpl_matrix_get(covar,1,1)* (chi_sq));
7492 double grad = cpl_vector_get(guess,1);
7493 //cpl_msg_info(cpl_func,"grad %e grad_err %e grad_err_other %e chi_sq %e\n",cpl_vector_get(guess,1),grad_err,grad_err_other,chi_sq);
7494 cpl_propertylist_append_double(qclist,"ESO QC FLAT SLIT B",grad);
7495 cpl_propertylist_append_double(qclist,"ESO QC FLAT SLIT DB",grad_err_other);
7496
7497 cpl_image_delete(slit);
7498
7499 cpl_error_reset();
7500 return cpl_error_get_code();
7501}
7502
7503cpl_error_code
7504calc_resp_qc(cpl_table* mtab, cpl_table* rtab,xsh_instrument* instrument, int lower,int upper,const char* label, cpl_propertylist* qclist)
7505{
7506 //cpl_msg_info(cpl_func,"Calling calc_resp_qc");
7507 //mtab = master = response generated by the recipe
7508 cpl_table* mtab2 = cpl_table_duplicate(mtab);
7509 cpl_table_new_column(mtab2,"SIGMA",CPL_TYPE_DOUBLE);
7510 cpl_size mrows = cpl_table_get_nrow(mtab2);
7511 //cpl_size mrows = cpl_table_get_nrow(mtab);
7512 //rtab = ref = response that we are comparing against (optional in the SOF)
7513 cpl_size rrows = cpl_table_get_nrow(rtab);
7514
7515
7516 if(mrows != rrows){
7517 return CPL_ERROR_NONE;
7518 }
7519 //a vector to note which data not to fit (i.e. set to very large values)
7520 //cpl_vector* sigma = cpl_vector_new(mrows);
7521
7522 float* tmplam = cpl_table_get_data_float(mtab2,"LAMBDA");
7523
7524 cpl_table_select_all(mtab2);
7525 cpl_table_select_all(rtab);
7526
7527 //need to select the rows that we want to deal with
7528 //once that is done, we can do the fitting
7529 for(int i=0;i<mrows;i++){
7530 cpl_table_set_double(mtab2,"SIGMA",i,1.0);
7531 //cpl_vector_set(sigma,i,1.0);
7533 if(i < lower || i > upper ){
7534 cpl_table_set_double(mtab2,"SIGMA",i,1e20);
7535 cpl_table_unselect_row(mtab2,i);
7536 cpl_table_unselect_row(rtab,i);
7537 }
7538 //D2 CALCS
7539 /*if(i < 408 || i > 4074){
7540 cpl_table_set_double(mtab2,"SIGMA",i,1e20);
7541 cpl_table_unselect_row(mtab2,i);
7542 cpl_table_unselect_row(rtab,i);
7543 }*/
7544 //QTH CALCS
7545 /*if(i < 4741 || i > 13408){
7546 cpl_table_set_double(mtab2,"SIGMA",i,1e20);
7547 cpl_table_unselect_row(mtab2,i);
7548 cpl_table_unselect_row(rtab,i);
7549 }*/
7550 }
7552 if(i < 1765){
7553 cpl_table_set_double(mtab2,"SIGMA",i,1e20);
7554 //cpl_vector_set(sigma,i,1e20);
7555 cpl_table_unselect_row(mtab2,i);
7556 cpl_table_unselect_row(rtab,i);
7557 }
7558 }
7560 if( (tmplam[i] > 1350 && tmplam[i] < 1480) || (tmplam[i] > 1770 && tmplam[i] < 2080)){
7561 //cpl_vector_set(sigma,i,1e20);
7562 cpl_table_set_double(mtab2,"SIGMA",i,1e20);
7563 //since the above ranges fall within the spectrum, no need to remove entirely
7564 //just set sigma to be very high
7565 //cpl_table_unselect_row(mtab2,i);
7566 //cpl_table_unselect_row(rtab,i);
7567 }
7568 }
7569 }
7570 mtab2 = cpl_table_extract_selected(mtab2);
7571 rtab = cpl_table_extract_selected(rtab);
7572 //update mrows
7573 mrows = cpl_table_get_nrow(mtab2);
7574
7575 float* mlam = cpl_table_get_data_float(mtab2,"LAMBDA");
7576 double* msigma = cpl_table_get_data_double(mtab2,"SIGMA");
7577 float* rlam = cpl_table_get_data_float(rtab,"LAMBDA");
7578 float* mresp = cpl_table_get_data_float(mtab2,"RESPONSE");
7579 float* rresp = cpl_table_get_data_float(rtab,"RESPONSE");
7580 /*Now extract the actual values we want to fit from the tables */
7581
7582 cpl_vector* vm_lam = cpl_vector_new(mrows);
7583 cpl_vector* vr_lam = cpl_vector_new(mrows);
7584 cpl_vector* vm_resp= cpl_vector_new(mrows);
7585 cpl_vector* vr_resp= cpl_vector_new(mrows);
7586 cpl_vector* sigma = cpl_vector_new(mrows);
7587
7588 cpl_vector* cr = cpl_vector_new(mrows);
7589 for(int i=0;i<mrows;i++){
7590 cpl_vector_set(vm_lam,i,mlam[i]);
7591 cpl_vector_set(sigma,i,msigma[i]);
7592 cpl_vector_set(vr_lam,i,rlam[i]);
7593 cpl_vector_set(vm_resp,i,mresp[i]);
7594 cpl_vector_set(vr_resp,i,rresp[i]);
7595 cpl_vector_set(cr,i,1.0);
7596 if(cpl_vector_get(cr,i) > 0 && cpl_vector_get(vr_resp,i) > 0){
7597 cpl_vector_set(cr,i,cpl_vector_get(vm_resp,i)/cpl_vector_get(vr_resp,i));
7598 } else {
7599 if(i >= 1){
7600 cpl_vector_set(cr,i,cpl_vector_get(cr,i-1));
7601 }
7602 cpl_vector_set(sigma,i,1e20);
7603 }
7604 }
7605 //value for constant in fit
7606 double lam0 = cpl_vector_get(vm_lam,(int)(mrows*0.5));
7607 cpl_msg_info(cpl_func,"lam0: %e\n",lam0);
7608
7609 //setup the data structures needed for the fitting...
7610 cpl_vector* guess = cpl_vector_new(3);
7611 cpl_vector_set(guess,0,0);
7612 cpl_vector_set(guess,1,0);
7613 cpl_vector_set(guess,2,lam0);
7614
7615 cpl_matrix* covar = cpl_matrix_new(3,3);
7616 double chi_sq;
7617
7618 //only fit first two params; third one (lam0) is constant
7619 int ia[3] = {1,1,0};
7620
7621 cpl_matrix* coeff = cpl_matrix_new(mrows,1);
7622 for(int i=0;i<mrows;i++){
7623 cpl_matrix_set(coeff,i,0,cpl_vector_get(vm_lam,i));
7624 }
7625 //yvals = cr vector
7626 //yvals err = sigma vector
7627
7628 cpl_error_code err= cpl_fit_lvmq(coeff,NULL,cr,sigma,guess,ia,qc_linfunc,qc_dlinfunc,CPL_FIT_LVMQ_TOLERANCE,CPL_FIT_LVMQ_COUNT,CPL_FIT_LVMQ_MAXITER,NULL,&chi_sq,&covar);
7629 double a = cpl_vector_get(guess,0);
7630 double b = cpl_vector_get(guess,1);
7631 double da= sqrt(cpl_matrix_get(covar,0,0)* (chi_sq));
7632 double db= sqrt(cpl_matrix_get(covar,1,1)* (chi_sq));
7633
7635 char* kw = NULL;
7636 kw = cpl_sprintf("ESO QC RESP SPEC A %s",label);
7637 cpl_propertylist_append_double(qclist,kw,a);
7638 kw = cpl_sprintf("ESO QC RESP SPEC B %s",label);
7639 cpl_propertylist_append_double(qclist,kw,b);
7640 kw = cpl_sprintf("ESO QC RESP SPEC DA %s",label);
7641 cpl_propertylist_append_double(qclist,kw,da);
7642 kw = cpl_sprintf("ESO QC RESP SPEC DB %s",label);
7643 cpl_propertylist_append_double(qclist,kw,db);
7644 cpl_free(kw);
7645 } else {
7646 cpl_propertylist_append_double(qclist,"ESO QC RESP SPEC A",a);
7647 cpl_propertylist_append_double(qclist,"ESO QC RESP SPEC B",b);
7648 cpl_propertylist_append_double(qclist,"ESO QC RESP SPEC DA",da);
7649 cpl_propertylist_append_double(qclist,"ESO QC RESP SPEC DB",db);
7650 }
7651 cpl_table_delete(mtab2);
7652 cpl_error_reset();
7653 return cpl_error_get_code();
7654}
7655
#define N
static double exptime
static const double step
static double sigma
static xsh_instrument * instrument
int binx
int biny
static float lambda_step
int xsh_grid_get_index(xsh_grid *grid)
get the number of elements in the grid
xsh_grid_point * xsh_grid_point_get(xsh_grid *grid, int i)
get x points from the grid
cpl_image * xsh_pre_get_data(xsh_pre *pre)
Get data.
xsh_pre * xsh_pre_duplicate(const xsh_pre *pre)
Copy a PRE structure.
Definition: xsh_data_pre.c:953
xsh_pre * xsh_pre_load(cpl_frame *frame, xsh_instrument *instr)
Load a xsh_pre structure from a frame.
Definition: xsh_data_pre.c:849
void xsh_pre_multiply_image(const xsh_pre *pre, cpl_image *img)
multiply a frame in PRE format by an image
cpl_image * xsh_pre_get_qual(xsh_pre *pre)
Get qual.
void xsh_pre_multiply_scalar(const xsh_pre *pre, double x)
multiply a frame in PRE format by a scalar
cpl_image * xsh_pre_abs(const xsh_pre *pre)
computes absolute value of a frame in PRE format
void xsh_pre_free(xsh_pre **pre)
Free a xsh_pre structure.
Definition: xsh_data_pre.c:823
cpl_image * xsh_pre_get_errs(xsh_pre *pre)
Get errs.
cpl_frame * xsh_pre_save(const xsh_pre *pre, const char *filename, const char *tag, int temp)
Save PRE on disk.
xsh_spectrum * xsh_spectrum_load(cpl_frame *s1d_frame)
Load a 1D spectrum structure.
cpl_frame * xsh_spectrum_save(xsh_spectrum *s, const char *filename, const char *tag)
save a spectrum
void xsh_spectrum_free(xsh_spectrum **s)
free memory associated to an 1D spectrum
cpl_error_code xsh_print_cpl_frameset(cpl_frameset *frames)
Print a frame set.
Definition: xsh_dump.c:201
const char * xsh_tostring_cpl_type(cpl_type t)
Convert a CPL type to a string.
Definition: xsh_dump.c:359
cpl_error_code xsh_print_cpl_frame(const cpl_frame *f)
Print a frame.
Definition: xsh_dump.c:243
#define XSH_ASSURE_NOT_NULL_MSG(pointer, msg)
Definition: xsh_error.h:103
#define XSH_ASSURE_NOT_ILLEGAL(cond)
Definition: xsh_error.h:107
#define assure(CONDITION, ERROR_CODE,...)
Definition: xsh_error.h:54
#define check(COMMAND)
Definition: xsh_error.h:71
#define check_msg(COMMAND,...)
Definition: xsh_error.h:62
#define xsh_error_reset()
Definition: xsh_error.h:87
#define XSH_ASSURE_NOT_ILLEGAL_MSG(cond, msg)
Definition: xsh_error.h:111
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
#define passure(CONDITION,...)
Definition: xsh_error.h:82
cpl_error_code xsh_instrument_nir_corr_if_spectral_format_is_JH(cpl_frameset *calib, xsh_instrument *instr)
cpl_error_code xsh_instrument_nir_corr_if_JH(cpl_frameset *raws, xsh_instrument *instr)
const char * xsh_instrument_arm_tostring(xsh_instrument *i)
Get the string associated with an arm.
void xsh_instrument_set_recipe_id(xsh_instrument *instrument, const char *recipe_id)
Set the recipe_id into the instrument structure.
XSH_ARM xsh_instrument_get_arm(xsh_instrument *i)
Get an arm on instrument structure.
void xsh_instrument_set_decode_bp(xsh_instrument *i, const int decode_bp)
Set bad pixel code.
int mm
int size
int * y
int * x
static SimAnneal s
Definition: xsh_model_sa.c:99
void xsh_msg_init(void)
Initialize messaging.
Definition: xsh_msg.c:80
#define xsh_msg_warning(...)
Print an warning message.
Definition: xsh_msg.h:88
#define xsh_msg_dbg_medium(...)
Definition: xsh_msg.h:44
#define xsh_msg_debug(...)
Print a debug message.
Definition: xsh_msg.h:99
#define xsh_msg_error(...)
Print an error message.
Definition: xsh_msg.h:62
#define xsh_msg(...)
Print a message on info level.
Definition: xsh_msg.h:121
int xsh_msg_get_warnings(void)
Get number of warnings printed so far.
Definition: xsh_msg.c:116
#define xsh_msg_dbg_high(...)
Definition: xsh_msg.h:40
void xsh_pfits_set_cd1(cpl_propertylist *plist, double value)
Write the CD1 value.
Definition: xsh_pfits.c:2308
void xsh_pfits_set_cd13(cpl_propertylist *plist, double value)
Write the CD1_3 value.
Definition: xsh_pfits.c:2384
cpl_error_code xsh_plist_set_extra_keys(cpl_propertylist *plist, const char *hduclas1, const char *hduclas2, const char *hduclas3, const char *scidata, const char *errdata, const char *qualdata, const int type)
set hdu keys
Definition: xsh_pfits.c:4250
const char * xsh_pfits_get_dpr_type(const cpl_propertylist *plist)
find out the DPR TECH
Definition: xsh_pfits.c:1667
void xsh_pfits_set_cd22(cpl_propertylist *plist, double value)
Write the CD2_2 value.
Definition: xsh_pfits.c:2369
void xsh_pfits_set_pcatg(cpl_propertylist *plist, const char *value)
Write the PCATG value.
Definition: xsh_pfits.c:1008
void xsh_pfits_set_cd21(cpl_propertylist *plist, double value)
Write the CD2_1 value.
Definition: xsh_pfits.c:2354
double xsh_pfits_get_cdelt2(const cpl_propertylist *plist)
find out the cdelt2
Definition: xsh_pfits.c:2216
double xsh_pfits_get_nod_jitterwidth(const cpl_propertylist *plist)
Get the Jitter Box size.
Definition: xsh_pfits.c:4178
double xsh_pfits_get_cdelt3(const cpl_propertylist *plist)
find out the cdelt3
Definition: xsh_pfits.c:2235
int xsh_pfits_get_binx(const cpl_propertylist *plist)
find out the BINX value
Definition: xsh_pfits.c:289
void xsh_pfits_set_extname(cpl_propertylist *plist, const char *value)
Write the EXTNAME value.
Definition: xsh_pfits.c:979
double xsh_pfits_get_nodthrow(const cpl_propertylist *plist)
Get the Nod Throw value.
Definition: xsh_pfits.c:4199
void xsh_pfits_set_cd31(cpl_propertylist *plist, double value)
Write the CD3_2 value.
Definition: xsh_pfits.c:2446
void xsh_pfits_set_cd32(cpl_propertylist *plist, double value)
Write the CD3_2 value.
Definition: xsh_pfits.c:2430
void xsh_pfits_set_cd23(cpl_propertylist *plist, double value)
Write the CD2_3 value.
Definition: xsh_pfits.c:2399
const char * xsh_pfits_get_dpr_catg(const cpl_propertylist *plist)
find out the DPR CATG
Definition: xsh_pfits.c:1688
const char * xsh_pfits_get_date_obs(const cpl_propertylist *plist)
find out the DATE
Definition: xsh_pfits.c:1746
double xsh_pfits_get_gain(const cpl_propertylist *plist)
find out the GAIN value
Definition: xsh_pfits.c:675
double xsh_pfits_get_cdelt1(const cpl_propertylist *plist)
find out the cdelt1
Definition: xsh_pfits.c:2196
int xsh_pfits_get_biny(const cpl_propertylist *plist)
find out the BINY value
Definition: xsh_pfits.c:306
void xsh_pfits_set_bunit(cpl_propertylist *plist, const char *value)
Write the BUNIT value.
Definition: xsh_pfits.c:2606
void xsh_pfits_set_cd33(cpl_propertylist *plist, double value)
Write the CD3_3 value.
Definition: xsh_pfits.c:2415
double xsh_pfits_get_exptime(const cpl_propertylist *plist)
find out the exposure time
Definition: xsh_pfits.c:2254
double xsh_pfits_get_airm_mean(const cpl_propertylist *plist)
find out the mean airmass value
Definition: xsh_pfits.c:511
double xsh_pfits_get_crval1(const cpl_propertylist *plist)
find out the crval1
Definition: xsh_pfits.c:1907
void xsh_pfits_set_cd12(cpl_propertylist *plist, double value)
Write the CD1_2 value.
Definition: xsh_pfits.c:2339
void xsh_pfits_set_cd11(cpl_propertylist *plist, double value)
Write the CD1_1 value.
Definition: xsh_pfits.c:2324
int xsh_pfits_get_naxis(const cpl_propertylist *plist)
find out the NAXIS value
Definition: xsh_pfits.c:209
double xsh_pfits_get_cumoffsety(const cpl_propertylist *plist)
Definition: xsh_pfits.c:3571
polynomial * xsh_polynomial_fit_2d(const cpl_bivector *xy_pos, const cpl_vector *values, const cpl_vector *sigmas, int poly_deg1, int poly_deg2, double *mse, double *red_chisq, polynomial **variance)
Fit a 2d surface with a polynomial in x and y.
void xsh_polynomial_delete(polynomial **p)
Delete a polynomial.
double xsh_polynomial_evaluate_2d(const polynomial *p, double x1, double x2)
Evaluate a 2d polynomial.
polynomial * xsh_polynomial_regression_2d(cpl_table *t, const char *X1, const char *X2, const char *Y, const char *sigmaY, int degree1, int degree2, const char *polynomial_fit, const char *residual_square, const char *variance_fit, double *mse, double *red_chisq, polynomial **variance, double kappa, double min_reject)
Fit a 2d polynomial to three table columns.
Definition: xsh_utils.c:3423
cpl_frame * xsh_normalize_spectrum(const cpl_frame *obj_frame, const cpl_frame *atm_ext_frame, cpl_boolean correct_binning, xsh_instrument *instrument, const char *tag_o)
Normalize a spectrum.
Definition: xsh_utils.c:5807
int xsh_max_int(int x, int y)
Maximum of two numbers.
Definition: xsh_utils.c:4415
#define XSH_FLOAT_SWAP(a, b)
Definition: xsh_utils.c:2404
void xsh_unwrap_vector(cpl_vector **v)
Unwrap a vector and set the pointer to NULL.
Definition: xsh_utils.c:2345
cpl_frame * xsh_frameset_average(cpl_frameset *set, const char *tag)
Dump propertylist.
Definition: xsh_utils.c:875
void xsh_vector_fit_gaussian(cpl_vector *x, cpl_vector *y, XSH_GAUSSIAN_FIT *result)
set debug level
Definition: xsh_utils.c:3101
void xsh_image_fit_spline(cpl_image *img, xsh_grid *grid)
perform spline fit
Definition: xsh_utils.c:2980
static void xsh_property_dump(cpl_property *property)
Dump property.
Definition: xsh_utils.c:797
void xsh_free_polynomial(cpl_polynomial **p)
Deallocate a polynomial and set the pointer to NULL.
Definition: xsh_utils.c:2194
void xsh_free_vector(cpl_vector **v)
Deallocate a vector and set the pointer to NULL.
Definition: xsh_utils.c:2284
void xsh_free_parameterlist(cpl_parameterlist **p)
Deallocate a parameter list and set the pointer to NULL.
Definition: xsh_utils.c:2224
#define XSH_INT_SWAP(a, b)
Definition: xsh_utils.c:2405
#define CPL_TYPE_T
Definition: xsh_utils.c:100
static int qc_dlinfunc(const double x[], const double p[], double f[])
Definition: xsh_utils.c:7417
const char * xsh_set_recipe_sky_file_prefix(char *rec_prefix)
Set recipe sky frames prefix.
Definition: xsh_utils.c:576
static int expb_df(const gsl_vector *x, void *data, gsl_matrix *J)
Definition: xsh_utils.c:6788
static int expb_f(const gsl_vector *x, void *data, gsl_vector *f)
Definition: xsh_utils.c:6757
cpl_error_code xsh_check_input_is_unbinned(cpl_frame *in)
Check if an input frame is not binned.
Definition: xsh_utils.c:375
cpl_image * xsh_normalize_spectrum_image(const cpl_image *spectrum, const cpl_image *spectrum_error, const cpl_propertylist *spectrum_header, const int bin_size, const double gain, const double exptime, const double airmass, const int n_traces, const cpl_table *atm_extinction, cpl_image **scaled_error)
Normalize a spectrum.
Definition: xsh_utils.c:5996
int xsh_time_stamp_set(int ts)
set timestamp
Definition: xsh_utils.c:3179
cpl_error_code get_average_qc_from_raws(cpl_frameset *fset, xsh_instrument *instrument, cpl_propertylist *qclist)
Definition: xsh_utils.c:7216
int xsh_fileutils_copy(const char *srcpath, const char *dstpath)
Definition: xsh_utils.c:429
char * xsh_stringcat_4(const char *s1, const char *s2, const char *s3, const char *s4)
String concatenation.
Definition: xsh_utils.c:1791
const char * xsh_string_tolower(char *s)
Convert all uppercase characters in a string into lowercase characters.
Definition: xsh_utils.c:4508
int xsh_select_table_rows(cpl_table *t, const char *column, cpl_table_select_operator operator, double value)
Select table rows.
Definition: xsh_utils.c:3784
char * xsh_stringcat_5(const char *s1, const char *s2, const char *s3, const char *s4, const char *s5)
String concatenation.
Definition: xsh_utils.c:1831
void xsh_tools_min_max(int size, double *tab, double *min, double *max)
computes min & max in ab array
Definition: xsh_utils.c:2799
static int expb_fdf(const gsl_vector *x, void *data, gsl_vector *f, gsl_matrix *J)
Definition: xsh_utils.c:6850
cpl_error_code xsh_frameset_dump_nod_info(cpl_frameset *set)
Dump frameset nod info.
Definition: xsh_utils.c:1088
const char * xsh_string_toupper(char *s)
Convert all lowercase characters in a string into uppercase characters.
Definition: xsh_utils.c:4542
void xsh_free_image(cpl_image **i)
Deallocate an image and set the pointer to NULL.
Definition: xsh_utils.c:2116
int xsh_debug_level_get(void)
get debug level
Definition: xsh_utils.c:3142
int xsh_fileutils_move(const char *srcpath, const char *dstpath)
Definition: xsh_utils.c:534
cpl_error_code xsh_update_pheader_in_image_multi(cpl_frame *frame, const cpl_propertylist *pheader)
Update FITS header.
Definition: xsh_utils.c:4258
double xsh_spline_hermite(double xp, const double *x, const double *y, int n, int *istart)
Spline interpolation based on Hermite polynomials.
Definition: xsh_utils.c:4577
void xsh_unwrap_bivector_vectors(cpl_bivector **b)
Unwrap a bi-vector and set the pointer to NULL.
Definition: xsh_utils.c:2376
#define CPL_IMAGE_GET_DATA_CONST
Definition: xsh_utils.c:102
double convert_data_to_bin(double data, int binning)
Definition: xsh_utils.c:3246
cpl_error_code xsh_get_property_value(const cpl_propertylist *plist, const char *keyword, cpl_type keywordtype, void *result)
Read a property value from a property list.
Definition: xsh_utils.c:1600
int xsh_min_int(int x, int y)
Minimum of two numbers.
Definition: xsh_utils.c:4399
static cpl_error_code xsh_util_get_infsup(double *piw, double w, int i_start, int i_end, int *i_inf, int *i_sup)
Definition: xsh_utils.c:5255
cpl_frame * xsh_spectrum_interpolate_linear(cpl_frame *table_frame, const double wstep, const double wmin, const double wmax)
spectra interpolation
Definition: xsh_utils.c:6213
static char ** TempFiles
Definition: xsh_utils.c:1419
double * y
Definition: xsh_ngaussfdf.h:14
void xsh_free_frame(cpl_frame **f)
Deallocate a frame and set the pointer to NULL.
Definition: xsh_utils.c:2269
double xsh_vector_get_err_median(cpl_vector *vect)
Computes median error on a data set.
Definition: xsh_utils.c:4319
void xsh_free_frameset(cpl_frameset **f)
Deallocate a frame set and set the pointer to NULL.
Definition: xsh_utils.c:2254
int xsh_debug_level_set(int level)
set debug level
Definition: xsh_utils.c:3125
char * xsh_stringcat_6(const char *s1, const char *s2, const char *s3, const char *s4, const char *s5, const char *s6)
String concatenation.
Definition: xsh_utils.c:1875
char * xsh_set_recipe_file_prefix(cpl_frameset *raw, const char *recipe)
Set recipe frames prefix.
Definition: xsh_utils.c:601
char * xsh_stringcat_3(const char *s1, const char *s2, const char *s3)
String concatenation.
Definition: xsh_utils.c:1753
void xsh_free_temporary_files(void)
Free temprary files list.
Definition: xsh_utils.c:1451
cpl_frame * xsh_normalize_spectrum_ord(const cpl_frame *obj_frame, const cpl_frame *atm_ext_frame, cpl_boolean correct_binning, xsh_instrument *instrument, const char *tag_o)
Normalize a spectrum.
Definition: xsh_utils.c:5893
void xsh_free_array(cpl_array **m)
Deallocate an array and set the pointer to NULL.
Definition: xsh_utils.c:2299
double * xsh_function1d_xcorrelate(double *line_i, int width_i, double *line_t, int width_t, int half_search, int normalise, double *xcorr_max, double *delta)
Definition: xsh_utils.c:7101
double xsh_tools_tchebitchev_transform(double pos, double min, double max)
computes Tchebitchev transformation
Definition: xsh_utils.c:2917
static int NbTemp
Definition: xsh_utils.c:1420
cpl_frame * xsh_util_multiply_by_response_ord(cpl_frame *extracted_sci, cpl_frame *response, const char *tag_o)
Multiply input frame by response frame.
Definition: xsh_utils.c:5016
double xsh_min_double(double x, double y)
Minimum of two numbers.
Definition: xsh_utils.c:4432
double xsh_vector_get_err_mean(cpl_vector *vect)
Computes mean error on a data set.
Definition: xsh_utils.c:4354
const char * xsh_debug_level_tostring(void)
set debug level
Definition: xsh_utils.c:3155
void xsh_tools_get_statistics(double *tab, int size, double *median, double *mean, double *stdev)
Compute median, stdev and mean for the tab.
Definition: xsh_utils.c:2421
void xsh_mem_dump(const char *prompt)
Definition: xsh_utils.c:3208
void xsh_free_stats(cpl_stats **s)
Deallocate a stats object and set the pointer to NULL.
Definition: xsh_utils.c:2314
double frame_date
Definition: xsh_utils.c:3277
static int qc_linfunc(const double x[], const double p[], double *f)
Definition: xsh_utils.c:7408
static int NbProducts
Definition: xsh_utils.c:1422
void xsh_reindex_float(float *data, int *idx, int size)
TO BE DESCRIBED.
Definition: xsh_utils.c:2038
void xsh_frame_table_save(cpl_frame *frame, const char *name_o)
Save a table frame.
Definition: xsh_utils.c:4017
cpl_error_code xsh_monitor_flux(cpl_frame *frm_ima, const cpl_frame *frm_tab, xsh_instrument *instrument, const char *qc_key_prefix)
Monitor Flux level along the orders traces given by an input table
Definition: xsh_utils.c:4107
cpl_frame * xsh_frame_mult(cpl_frame *in, xsh_instrument *instr, cpl_frame *sign)
Computes product of two input frames.
Definition: xsh_utils.c:4061
void xsh_random_init(void)
Definition: xsh_utils.c:109
cpl_error_code calc_flat_slit_qc(cpl_image *im, int xa1, int xa2, cpl_propertylist *qclist)
Definition: xsh_utils.c:7429
#define CPL_IMAGE_GET_DATA
Definition: xsh_utils.c:101
cpl_vector * xsh_tools_tchebitchev_poly_eval(int n, double X)
Compute tchebitchev Tn(X) first coefficient for tchebitchev polynomial.
Definition: xsh_utils.c:2836
void xsh_plist_dump(cpl_propertylist *plist)
Dump propertylist.
Definition: xsh_utils.c:1026
int xsh_get_random_int_window(const int v1, const int v2)
generates random integer values in range [v1,v2]
Definition: xsh_utils.c:128
#define CPL_TYPE
Definition: xsh_utils.c:99
double xsh_tools_tchebitchev_reverse_transform(double pos, double min, double max)
computes reverse Tchebitchev transformation
Definition: xsh_utils.c:2954
void xsh_gsl_init_gaussian_fit(cpl_vector *xpos_vect, cpl_vector *ypos_vect, double *init_par)
Definition: xsh_utils.c:6862
cpl_error_code xsh_set_cd_matrix3d(cpl_propertylist *plist)
Set CD matrix.
Definition: xsh_utils.c:744
cpl_frame * xsh_frame_abs(cpl_frame *in, xsh_instrument *instr, cpl_frame **sign)
Computes absolute value of a frame.
Definition: xsh_utils.c:3911
void xsh_free_mask(cpl_mask **m)
Deallocate an image mask and set the pointer to NULL.
Definition: xsh_utils.c:2149
char * xsh_get_basename(const char *filename)
Return base filename.
Definition: xsh_utils.c:1175
int deg
Definition: xsh_utils.c:6753
const char * frame_name
Definition: xsh_utils.c:3280
int xsh_tools_running_median_1d_get_max(double *tab, int size, int wsize)
get max of a list of doubles after running median
Definition: xsh_utils.c:2748
cpl_error_code calc_curve_qc(cpl_image *im, xsh_instrument *instrument, cpl_propertylist *qclist)
Definition: xsh_utils.c:7322
void xsh_free_product_files(void)
Free temprary files list.
Definition: xsh_utils.c:1491
static int compare_frame_date(const void *one, const void *two)
Definition: xsh_utils.c:3284
int raw_mjd_frame_compare(const cpl_frame *f1, const cpl_frame *f2)
Definition: xsh_utils.c:7196
size_t n
Definition: xsh_ngaussfdf.h:11
const char * xsh_get_license(void)
Get the pipeline copyright and license.
Definition: xsh_utils.c:1193
char * xsh_stringcat_any(const char *s,...)
Concatenate an arbitrary number of strings.
Definition: xsh_utils.c:1925
void xsh_reindex_int(int *data, int *idx, int size)
TO BE DESCRIBED.
Definition: xsh_utils.c:2070
cpl_error_code xsh_tools_sort_double(double *pix_arr, int n)
Sort a double array.
Definition: xsh_utils.c:2461
cpl_error_code xsh_frameset_dump(cpl_frameset *set)
Dump frameset.
Definition: xsh_utils.c:1054
cpl_error_code xsh_set_cd_matrix2d(cpl_propertylist *plist)
Set CD matrix.
Definition: xsh_utils.c:718
#define XSH_PIX_STACK_SIZE
Definition: xsh_utils.c:2407
double xsh_hms2deg(const double hms)
Convert a double from hours minute seconds to deg:
Definition: xsh_utils.c:312
int xsh_time_stamp_get(void)
get timestamp
Definition: xsh_utils.c:3196
double xsh_get_random_double_window(const double v1, const double v2)
generates random integer values in range [v1,v2]
Definition: xsh_utils.c:150
cpl_frame * xsh_spectrum_resample(cpl_frame *frame_inp, const double wstep, const double wmin, const double wmax, xsh_instrument *instr)
resample a spectrum
Definition: xsh_utils.c:5336
void xsh_array_clip_poly1d(cpl_vector *pos_vect, cpl_vector *val_vect, double kappa, int niter, double frac_min, int deg, cpl_polynomial **polyp, double *chisq, int **flagsp)
clip outliers from a 1D poly fit
Definition: xsh_utils.c:6568
char * xsh_stringdup(const char *s)
String duplication.
Definition: xsh_utils.c:1658
int xsh_erase_table_rows(cpl_table *t, const char *column, cpl_table_select_operator operator, double value)
Erase table rows.
Definition: xsh_utils.c:3849
cpl_error_code xsh_tools_sort_int(int *pix_arr, int n)
Sort an integer array.
Definition: xsh_utils.c:2633
cpl_error_code get_chromatic_eff(cpl_frame *eff, cpl_propertylist *qclist)
Definition: xsh_utils.c:7306
void xsh_frame_image_save(cpl_frame *frm, const char *name_o)
save an image frame
Definition: xsh_utils.c:3983
cpl_frame * xsh_util_frameset_collapse_mean(cpl_frameset *set, xsh_instrument *instrument)
Compute mean frame from a list of (IMAGE) framesets.
Definition: xsh_utils.c:5538
cpl_vector * xsh_image_to_vector(cpl_image *spectrum)
Definition: xsh_utils.c:4680
cpl_frame * xsh_frame_inv(cpl_frame *in, const char *filename, xsh_instrument *instr)
Inverse the flux of a PRE frame.
Definition: xsh_utils.c:3878
void xsh_free_parameter(cpl_parameter **p)
Deallocate a parameter and set the pointer to NULL.
Definition: xsh_utils.c:2239
long xsh_round_double(double x)
Computes round(x)
Definition: xsh_utils.c:4383
cpl_error_code xsh_set_cd_matrix(cpl_propertylist *plist)
Set CD matrix.
Definition: xsh_utils.c:676
cpl_frame * xsh_util_multiply_by_response(cpl_frame *merged_sci, cpl_frame *response, const char *tag_o)
Multiply input frame by response frame.
Definition: xsh_utils.c:4798
int * xsh_sort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *))
Sort an array and give is index table.
Definition: xsh_utils.c:1966
void xsh_reindex(double *data, int *idx, int size)
TO BE DESCRIBED.
Definition: xsh_utils.c:2008
void xsh_array_clip_median(cpl_array *array, double kappa, int niter, double frac_min, double *median, double *stdev)
median clip of an array
Definition: xsh_utils.c:6493
void xsh_init(void)
Reset library state.
Definition: xsh_utils.c:1160
double xsh_tools_get_median_double(double *array, int size)
Calculates the median value of an array of double.
Definition: xsh_utils.c:2721
cpl_frameset * xsh_order_frameset_by_date(cpl_frameset *frameset)
Order frameset by date.
Definition: xsh_utils.c:3306
char * xsh_sdate_utc(time_t *now)
Definition: xsh_utils.c:1691
void xsh_unwrap_image(cpl_image **i)
Unwrap an image and set the pointer to NULL.
Definition: xsh_utils.c:2330
cpl_image * xsh_imagelist_collapse_sigclip_iter_create(const cpl_imagelist *imlist, double sigma_low, double sigma_upp, const int niter)
Average with sigma-clipping rejection an imagelist to a single image.
Definition: xsh_utils.c:193
static double date_to_double(const char *the_date)
Definition: xsh_utils.c:3255
void xsh_array_clip_mean(cpl_array *array, double kappa, int niter, double frac_min, double *mean, double *stdev)
mean clip of an array
Definition: xsh_utils.c:6415
cpl_error_code xsh_tools_sort_float(float *pix_arr, int n)
Sort a float array.
Definition: xsh_utils.c:2548
double xsh_sess2deg(const double sess)
Convert a double from ssessagesimal to deg: 203049.197= 20:30:49.197 = 20.5136658333.
Definition: xsh_utils.c:345
void xsh_free_matrix(cpl_matrix **m)
Deallocate a matrix and set the pointer to NULL.
Definition: xsh_utils.c:2209
char * xsh_stringcat(const char *s1, const char *s2)
String concatenation.
Definition: xsh_utils.c:1719
void xsh_gsl_fit_gaussian(cpl_vector *xpos_vect, cpl_vector *ypos_vect, int deg, double *params, double *errs, int *status)
Definition: xsh_utils.c:6936
cpl_error_code xsh_remove_crh_single_params_set_defaults(cpl_parameterlist *pars, const char *rec_id, xsh_instrument *inst, xsh_remove_crh_single_param *crh_single_par)
Definition: xsh_utils.c:6723
cpl_error_code xsh_begin(cpl_frameset *frames, const cpl_parameterlist *parameters, xsh_instrument **instrument, cpl_frameset **raws, cpl_frameset **calib, const char *tag_list[], int tag_list_size, const char *recipe_id, unsigned int binary_version, const char *short_descr)
Recipe initialization.
Definition: xsh_utils.c:1244
cpl_error_code xsh_rectify_params_set_defaults(cpl_parameterlist *pars, const char *rec_id, xsh_instrument *inst, xsh_rectify_param *rectify_par)
Definition: xsh_utils.c:6681
double convert_bin_to_data(double bin_data, int binning)
Definition: xsh_utils.c:3228
void xsh_free_table(cpl_table **t)
Deallocate a table and set the pointer to NULL.
Definition: xsh_utils.c:2133
cpl_error_code calc_resp_qc(cpl_table *mtab, cpl_table *rtab, xsh_instrument *instrument, int lower, int upper, const char *label, cpl_propertylist *qclist)
Definition: xsh_utils.c:7504
void xsh_free_propertylist(cpl_propertylist **p)
Deallocate a property list and set the pointer to NULL.
Definition: xsh_utils.c:2179
cpl_error_code xsh_end(const char *recipe_id, cpl_frameset *frames, cpl_parameterlist *parameters)
Recipe termination.
Definition: xsh_utils.c:1519
cpl_image * xsh_vector_to_image(const cpl_vector *vector, cpl_type type)
Convert a vector to a 1d image.
Definition: xsh_utils.c:4745
double * x
Definition: xsh_utils.c:6752
void xsh_add_product_file(const char *name)
Add temporary file to temprary files list.
Definition: xsh_utils.c:1472
static double xsh_spectrum_integrate(double *pif, double *piw, int i1_inf, int i1_sup, int i2_inf, int i2_sup, double wave, double wstep)
Definition: xsh_utils.c:5276
cpl_frame * xsh_spectrum_interpolate(cpl_frame *table_frame, const double wstep, const double wmin, const double wmax)
spectra interpolation
Definition: xsh_utils.c:6306
void xsh_frame_spectrum_save(cpl_frame *frm, const char *name_o)
save an spectrum frame
Definition: xsh_utils.c:3959
cpl_error_code xsh_normalize_spectrum_image_slice(const char *name_s, const char *tag_o, const int ext, const int bin_size, const double gain, const double exptime, const double airmass, const cpl_table *tbl_atm_ext)
Normalize spectrum slice.
Definition: xsh_utils.c:5650
cpl_frame * xsh_frameset_add(cpl_frameset *set, xsh_instrument *instr, const int decode_bp)
coadd frames in a frameset
Definition: xsh_utils.c:921
double xsh_spline_hermite_table(double xp, const cpl_table *t, const char *column_x, const char *column_y, int *istart)
Spline interpolation based on Hermite polynomials.
Definition: xsh_utils.c:4648
static double xsh_iterpol_linear(double *data_x, double *data_y, int ndata, double x, int *i_inf, int *i_sup)
Definition: xsh_utils.c:6170
void xsh_tools_tchebitchev_transform_tab(int size, double *pos, double min, double max, double *tcheb_pos)
computes Tchebitchev transformation
Definition: xsh_utils.c:2881
void xsh_free_imagelist(cpl_imagelist **i)
Deallocate an image list and set the pointer to NULL.
Definition: xsh_utils.c:2164
double xsh_pow_int(double x, int y)
Computes x^y.
Definition: xsh_utils.c:4463
static char ** ProdFiles
Definition: xsh_utils.c:1421
double xsh_max_double(double x, double y)
Maximum of two numbers.
Definition: xsh_utils.c:4449
void xsh_free(const void *mem)
Deallocate memory.
Definition: xsh_utils.c:2102
void xsh_unwrap_array(cpl_array **a)
Unwrap an array and set the pointer to NULL.
Definition: xsh_utils.c:2361
cpl_parameterlist * xsh_parameterlist_duplicate(const cpl_parameterlist *pin)
Extract frames with given tag from frameset.
Definition: xsh_utils.c:771
cpl_frame * frame
Definition: xsh_utils.c:3279
#define XSH_DOUBLE_SWAP(a, b)
Definition: xsh_utils.c:2403
void xsh_add_temporary_file(const char *name)
Add temporary file to temprary files list.
Definition: xsh_utils.c:1432
cpl_error_code xsh_set_cd_matrix1d(cpl_propertylist *plist)
Set CD matrix.
Definition: xsh_utils.c:701
void xsh_show_time(const char *comment)
show time
Definition: xsh_utils.c:2389
unsigned int first
Definition: irplib_error.c:88
double * x
Definition: xsh_model_sa.c:94
double * t
Definition: xsh_ngaussfdf.h:13
void * data
Definition: xsh_utils.h:120
#define QFLAG_GOOD_PIXEL
#define XSH_ATMOS_EXT_LIST_COLNAME_OLD
#define XSH_ATMOS_EXT_LIST_COLNAME_K
@ XSH_ARM_UVB
@ XSH_ARM_NIR
@ XSH_ARM_VIS
#define XSH_PRE_DATA_TYPE
Definition: xsh_data_pre.h:42
#define XSH_PRE_QUAL_TYPE
Definition: xsh_data_pre.h:46
#define XSH_PRE_ERRS_BPP
Definition: xsh_data_pre.h:45
#define XSH_PRE_QUAL_BPP
Definition: xsh_data_pre.h:47
#define XSH_PRE_ERRS_TYPE
Definition: xsh_data_pre.h:44
#define XSH_PRE_DATA_BPP
Definition: xsh_data_pre.h:43
#define XSH_SPECTRUM_DATA_BPP
#define XSH_SPECTRUM_ERRS_BPP
int nx
double kappa
Definition: xsh_detmon_lg.c:81
int niter
Definition: xsh_detmon_lg.c:82
int lly
Definition: xsh_detmon_lg.c:86
int llx
Definition: xsh_detmon_lg.c:85
int m
Definition: xsh_detmon_lg.c:91
int n
Definition: xsh_detmon_lg.c:92
int urx
Definition: xsh_detmon_lg.c:87
int ury
Definition: xsh_detmon_lg.c:88
int ny
int order
Definition: xsh_detmon_lg.c:80
double cr
cpl_error_code xsh_calib_nir_corr_if_JH(cpl_frameset *calib, xsh_instrument *instr, const char *recid)
Definition: xsh_dfs.c:5014
void xsh_dfs_split_in_group(cpl_frameset *input, cpl_frameset *raws, cpl_frameset *calib)
split input sof in groups: raw and calib
Definition: xsh_dfs.c:1202
int xsh_dfs_files_dont_exist(cpl_frameset *frameset)
Check if all SOF files exist.
Definition: xsh_dfs.c:245
xsh_instrument * xsh_dfs_set_groups(cpl_frameset *set)
Set the group as RAW or CALIB in a frameset and return the instrument detected.
Definition: xsh_dfs.c:1046
void xsh_dfs_filter(cpl_frameset *set, const char *tags[], int size)
filter the frameset with the given tag list
Definition: xsh_dfs.c:1511
cpl_frame * xsh_frame_product(const char *fname, const char *tag, cpl_frame_type type, cpl_frame_group group, cpl_frame_level level)
Creates a frame with given characteristics.
Definition: xsh_dfs.c:930
#define XSH_SLIT_BIN_SIZE_PIPE_VIS
Definition: xsh_dfs.h:100
#define XSH_WAVE_BIN_SIZE_PIPE_VIS
Definition: xsh_dfs.h:104
#define XSH_SLIT_BIN_SIZE_PIPE_UVB
Definition: xsh_dfs.h:99
#define XSH_SLIT_BIN_SIZE_PIPE_NIR
Definition: xsh_dfs.h:101
#define XSH_REMOVE_CRH_SINGLE_NIR
Definition: xsh_dfs.h:107
#define XSH_REMOVE_CRH_SINGLE_UVB_VIS
Definition: xsh_dfs.h:108
#define XSH_WAVE_BIN_SIZE_PIPE_UVB
Definition: xsh_dfs.h:103
#define XSH_WAVE_BIN_SIZE_PIPE_NIR
Definition: xsh_dfs.h:105
#define max(a, b)
cpl_parameter * xsh_parameters_find(cpl_parameterlist *list, const char *recipe_id, const char *name)
find a parameter
int xsh_parameters_get_temporary(const char *recipe_id, const cpl_parameterlist *list)
int xsh_parameters_debug_level_get(const char *recipe_id, const cpl_parameterlist *list)
#define XSH_NOD_THROW
Definition: xsh_pfits.h:228
#define XSH_NOD_CUMULATIVE_OFFSETY
Definition: xsh_pfits.h:226
#define XSH_NOD_JITTER_BOX
Definition: xsh_pfits.h:229
#define XSH_BUNIT_FLUX_ABS_C
Definition: xsh_pfits.h:114
#define XSH_QC_FLUX_MIN_C
Definition: xsh_pfits_qc.h:114
#define XSH_QC_FLUX_MAX_C
Definition: xsh_pfits_qc.h:116
static int XshDebugLevel
Definition: xsh_utils.c:69
#define DEV_BLOCKSIZE
Definition: xsh_utils.c:78
static int XshTimeStamp
Definition: xsh_utils.c:70
#define XSH_ATM_EXT_UVB_WAV_MIN
Definition: xsh_utils.c:79
#define MAXIMUM(x, y)
Definition: xsh_utils.c:75
#define XSH_FREE(POINTER)
Definition: xsh_utils.h:92
@ XSH_DEBUG_LEVEL_HIGH
Definition: xsh_utils.h:138
@ XSH_DEBUG_LEVEL_NONE
Definition: xsh_utils.h:137
@ XSH_DEBUG_LEVEL_LOW
Definition: xsh_utils.h:137
@ XSH_DEBUG_LEVEL_MEDIUM
Definition: xsh_utils.h:138
#define XSH_MALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:49
#define XSH_CALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:56
#define M_PI
Definition: xsh_utils.h:43
#define XSH_NEW_FRAMESET(POINTER)
Definition: xsh_utils.h:84
cpl_polynomial * xsh_polynomial_fit_1d_create(const cpl_vector *x_pos, const cpl_vector *values, int degree, double *mse)