00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287 #ifdef HAVE_CONFIG_H
00288 # include <config.h>
00289 #endif
00290
00291
00297
00298
00299
00300
00301
00302 #include <assert.h>
00303 #include <uves_utils.h>
00304 #include <uves_utils_cpl.h>
00305
00306 #include <uves_extract_profile.h>
00307 #include <uves_plot.h>
00308 #include <uves_dfs.h>
00309 #include <uves_pfits.h>
00310 #include <uves_utils_wrappers.h>
00311 #include <uves_msg.h>
00312 #include <uves_dump.h>
00313 #include <uves_error.h>
00314
00315 #include <irplib_utils.h>
00316
00317 #include <cpl.h>
00318 #include <qfits.h>
00319
00320 #include <ctype.h>
00321 #include <stdbool.h>
00322 #include <float.h>
00323
00324
00325
00326
00327
00328
00329 #define C_TO_FORTRAN_INDEXING(a) &a[-1]
00330 #define FORTRAN_TO_C_INDEXING(a) &a[1]
00331
00333
00334
00335
00336
00337
00338 static cpl_error_code
00339 uves_cosrout(cpl_image* ima,
00340 cpl_image** msk,
00341 const double ron,
00342 const double gain,
00343 const int ns,
00344 const double sky,
00345 const double rc,
00346 cpl_image** flt,
00347 cpl_image** out);
00348
00349
00350 static cpl_error_code
00351 uves_find_next(cpl_image** msk,
00352 const int first_y,
00353 int* next_x,
00354 int* next_y);
00355
00356 static cpl_error_code
00357 uves_sort(const int kmax,float* inp, int* ord);
00358
00359
00360
00361
00362
00363
00364
00409
00410
00411 cpl_error_code
00412 uves_rcosmic(cpl_image* ima,
00413 cpl_image** flt,
00414 cpl_image** out,
00415 cpl_image** msk,
00416 const double sky,
00417 const double ron,
00418 const double gain,
00419 const int ns,
00420 const double rc)
00421
00422 {
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465 check_nomsg(*flt=cpl_image_duplicate(ima));
00466 check_nomsg(uves_filter_image_median(flt,1,1,false));
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506 check_nomsg(uves_cosrout(ima,msk,ron,gain,ns,sky,rc,flt,out));
00507 cleanup:
00508 return CPL_ERROR_NONE;
00509 }
00510
00511
00512
00513
00537
00538
00539 static cpl_error_code
00540 uves_cosrout(cpl_image* ima,
00541 cpl_image** msk,
00542 const double ron,
00543 const double gain,
00544 const int ns,
00545 const double sky,
00546 const double rc,
00547 cpl_image** flt,
00548 cpl_image** out)
00549 {
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570 int sx=0;
00571 int sy=0;
00572 int i=0;
00573 int j=0;
00574 int k=1;
00575 int pix=0;
00576 int first[2];
00577 int next_x=0;
00578 int next_y=0;
00579 int i_min=0;
00580 int i_max=0;
00581 int j_min=0;
00582 int j_max=0;
00583 int idu_max=0;
00584 int jdu_max=0;
00585 int i1=0;
00586 int i2=0;
00587 int ii=0;
00588 int jj=0;
00589 int j1=0;
00590 int num=0;
00591 int l=0;
00592 int nmax=1e6;
00593 int ord[nmax];
00594
00595
00596 float* pi=NULL;
00597 float* po=NULL;
00598 float* pf=NULL;
00599 int* pm=NULL;
00600 float sigma=0;
00601
00602
00603 float vec[nmax];
00604
00605 double f_max=0;
00606 double s1=0;
00607 double s2=0;
00608 double asum=0;
00609 double a_median=0;
00610
00611 uves_msg_warning("sky=%g gain=%g ron=%g ns=%d rc=%g",sky,gain,ron,ns,rc);
00612 check_nomsg(sx=cpl_image_get_size_x(ima));
00613 check_nomsg(sy=cpl_image_get_size_y(ima));
00614 check_nomsg(pi=cpl_image_get_data_float(ima));
00615 check_nomsg(pf=cpl_image_get_data_float(*flt));
00616 check_nomsg(pm=cpl_image_get_data_int(*msk));
00617
00618 check_nomsg(*out=cpl_image_duplicate(ima));
00619 check_nomsg(po=cpl_image_get_data_float(*out));
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658 uves_msg_warning("Set all pix to = -1 -> candidate for cosmic");
00659 k=1;
00660 for(j=1;j<sy-1;j++) {
00661 for(i=1;i<sx-1;i++) {
00662 pix=j*sx+i;
00663 sigma=sqrt(ron*ron+pf[pix]/gain);
00664 if ( (pi[pix]-pf[pix]) >= (ns*sigma) ) {
00665 pm[pix]=-1;
00666 k++;
00667 }
00668 }
00669 }
00670
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696 first[0]=1;
00697 first[1]=1;
00698
00699 lab100:
00700 check_nomsg(uves_find_next(msk,first[1],&next_x, &next_y));
00701
00702 if(next_x==-1) return CPL_ERROR_NONE;
00703 i=next_x;
00704 j=next_y;
00705
00706 uves_msg_debug("p[%d,%d]= 2 -> member of the group",i,j);
00707 pix=j*sx+i;
00708 pm[pix]=2;
00709
00710 i_min=i;
00711 i_max=i;
00712 j_min=j;
00713 j_max=j;
00714 idu_max=i;
00715 jdu_max=j;
00716 f_max=pi[pix];
00717
00718 lab110:
00719 i1=0;
00720 i2=0;
00721
00722
00723
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743
00744
00745 for(l=0;l<2;l++) {
00746 for(k=0;k<2;k++) {
00747 ii=i+k-l;
00748 jj=j+k+l-3;
00749 pix=jj*sx+ii;
00750 if(pm[pix]==-1) {
00751 i1=ii;
00752 j1=jj;
00753 i_min=(i_min<ii) ? i_min: ii;
00754 i_max=(i_max>ii) ? i_max: ii;
00755 j_min=(j_min<jj) ? j_min: jj;
00756 j_max=(j_max>jj) ? j_max: jj;
00757 uves_msg_debug("p[%d,%d]= 2 -> member of the group",ii,jj);
00758 pm[pix]=2;
00759 if(pi[pix]>f_max) {
00760 f_max=pi[pix];
00761 idu_max=ii;
00762 idu_max=jj;
00763 }
00764 } else if(pm[pix]==0) {
00765 pm[pix]=4;
00766 uves_msg_debug("p[%d,%d]= 4 -> neighbourhood of the group",k,l);
00767 }
00768 }
00769 }
00770
00771
00772
00773
00774
00775
00776
00777
00778
00779
00780
00781
00782
00783
00784
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798
00799 pix=j*sx+i;
00800 pm[pix]=3;
00801 uves_msg_debug("p[%d,%d]= 3 -> member of a group which has been examined",i,j);
00802 if(i1 != 0) {
00803 i=i1;
00804 j=j1;
00805 goto lab110;
00806 }
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818 for(l=j_min;l<=j_max;l++){
00819 for(k=i_min;k<=i_max;k++){
00820 pix=l*sy+k;
00821 if(pm[pix] == 2) {
00822 i=k;
00823 j=l;
00824 goto lab110;
00825 }
00826 }
00827 }
00828 first[0] = next_x+1;
00829 first[1] = next_y;
00830
00831
00832
00833
00834
00835
00836
00837
00838
00839
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852
00853 s1=pi[(jdu_max-1)*sx+idu_max-1]+
00854 pi[(jdu_max-1)*sx+idu_max+1]+
00855 pi[(jdu_max-1)*sx+idu_max]+
00856 pi[(jdu_max+1)*sx+idu_max];
00857
00858 s2=pi[(jdu_max+1)*sy+idu_max-1]+
00859 pi[(jdu_max+1)*sy+idu_max+1]+
00860 pi[(jdu_max)*sy+idu_max-1]+
00861 pi[(jdu_max)*sy+idu_max+1];
00862 asum=(s1+s2)/8.-sky;
00863
00864
00865
00866
00867
00868
00869
00870
00871
00872
00873
00874
00875
00876
00877
00878
00879
00880
00881
00882
00883
00884 if((f_max-sky) > rc*asum) {
00885 num=0;
00886 for( l = j_min-1; l <= j_max+1; l++) {
00887 for( k = i_min-1; k<= i_max+1;k++) {
00888 if(pm[l*sx+k]==4) {
00889 vec[num]=pi[l*sx+k];
00890 num++;
00891 }
00892 }
00893 }
00894
00895
00896
00897
00898
00899
00900
00901
00902
00903
00904
00905
00906
00907
00908
00909
00910
00911 uves_sort(num-1,vec,ord);
00912 a_median=vec[ord[(num-1)/2]];
00913 for(l = j_min-1; l <= j_max+1 ; l++){
00914 for(k = i_min-1 ; k <= i_max+1 ; k++){
00915 if(pm[l*sx+k] == 3) {
00916 pm[l*sx+k]=1;
00917 uves_msg_debug("p[%d,%d]= 1 -> a cosmic (at the end)",k,l);
00918
00919 po[l*sx+k]=a_median;
00920 } else if (pm[l*sx+k] == 4) {
00921 po[l*sx+k]=0;
00922 po[l*sx+k]=a_median;
00923 }
00924 }
00925 }
00926
00927
00928
00929
00930
00931
00932
00933
00934
00935
00936
00937
00938
00939
00940
00941
00942
00943 } else {
00944 for( l = j_min-1 ; l <= j_max+1 ; l++) {
00945 for( k = i_min-1 ; k <= i_max+1 ; k++) {
00946 if(pm[l*sx+k] != -1) {
00947 uves_msg_debug("p[%d,%d]= 0 -> not a cosmic",k,l);
00948 pm[l*sx+k] = 0;
00949 }
00950 }
00951 }
00952 }
00953
00954
00955 if (next_x >0) goto lab100;
00956
00957
00958
00959
00960
00961
00962
00963
00964
00965
00966
00967
00968
00969
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 cleanup:
00981
00982 return CPL_ERROR_NONE;
00983
00984 }
00985
00986
00987
00988
00989
00990 static cpl_error_code
00991 uves_find_next(cpl_image** msk,
00992 const int first_y,
00993 int* next_x,
00994 int* next_y)
00995 {
00996 int sx=cpl_image_get_size_x(*msk);
00997 int sy=cpl_image_get_size_y(*msk);
00998 int i=0;
00999 int j=0;
01000 int* pc=NULL;
01001 int pix=0;
01002
01003
01004
01005 check_nomsg(pc=cpl_image_get_data_int(*msk));
01006 for(j=first_y;j<sy;j++) {
01007 for(i=1;i<sx;i++) {
01008 pix=j*sx+i;
01009 if(pc[pix]==-1) {
01010 *next_x=i;
01011 *next_y=j;
01012 return CPL_ERROR_NONE;
01013 }
01014 }
01015 }
01016
01017 *next_x=-1;
01018 *next_y=-1;
01019 cleanup:
01020 return CPL_ERROR_NONE;
01021
01022 }
01023
01024
01025
01026
01027
01028
01029
01030
01031
01032
01033
01034
01035
01036
01037
01038
01039
01040
01041
01042
01043
01044
01045
01046
01047
01048 static cpl_error_code
01049 uves_sort(const int kmax,float* inp, int* ord)
01050 {
01051 int k=0;
01052 int j=0;
01053 int l=0;
01054 float f=0;
01055 int i_min=0;
01056 int i_max=0;
01057 int i=0;
01058
01059 for(k=0;k<kmax;k++) {
01060 ord[k]=k;
01061 }
01062
01063 if(inp[0]>inp[1]) {
01064 ord[0]=1;
01065 ord[1]=0;
01066 }
01067
01068 for(j=2;j<kmax;j++) {
01069 f=inp[j];
01070 l=inp[j-1];
01071
01072
01073
01074
01075
01076
01077
01078
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088
01089 if(inp[l]<=f) goto lab4400;
01090 l=ord[0];
01091 i_min=0;
01092 if(f<=inp[l]) goto lab4250;
01093 i_max=j-1;
01094 lab4200:
01095 i=(i_min+i_max)/2;
01096 l=ord[i];
01097
01098
01099
01100
01101
01102
01103
01104
01105
01106
01107
01108 if(inp[l]<f) {
01109 i_min=i;
01110 } else {
01111 i_max=i;
01112 }
01113 if(i_max>(i_min+1)) goto lab4200;
01114 i_min=i_max;
01115 lab4250:
01116 for(k=j-2;k>=i_min;k--) {
01117 ord[k+1]=ord[k];
01118 }
01119 ord[i_min]=j;
01120 lab4400:
01121 return CPL_ERROR_NONE;
01122 }
01123 return CPL_ERROR_NONE;
01124 }
01125
01126
01127
01128
01129
01130
01131
01132
01133
01134
01135
01136
01137
01138
01139
01140
01141
01142
01143
01149
01150
01151 cpl_parameterlist*
01152 uves_parameterlist_duplicate(const cpl_parameterlist* pin){
01153
01154 cpl_parameter* p=NULL;
01155 cpl_parameterlist* pout=NULL;
01156
01157 pout=cpl_parameterlist_new();
01158 p=cpl_parameterlist_get_first((cpl_parameterlist*)pin);
01159 while (p != NULL)
01160 {
01161 cpl_parameterlist_append(pout,p);
01162 p=cpl_parameterlist_get_next((cpl_parameterlist*)pin);
01163 }
01164 return pout;
01165
01166 }
01183 const char*
01184 uves_string_toupper(char* s)
01185 {
01186
01187 char *t = s;
01188
01189 assert(s != NULL);
01190
01191 while (*t) {
01192 *t = toupper(*t);
01193 t++;
01194 }
01195
01196 return s;
01197
01198 }
01199
01215 const char*
01216 uves_string_tolower(char* s)
01217 {
01218
01219 char *t = s;
01220
01221 assert(s != NULL);
01222
01223 while (*t) {
01224 *t = tolower(*t);
01225 t++;
01226 }
01227
01228 return s;
01229
01230 }
01231
01232
01233
01234
01235
01242
01243 cpl_frameset *
01244 uves_frameset_extract(const cpl_frameset *frames,
01245 const char *tag)
01246 {
01247 cpl_frameset *subset = NULL;
01248 const cpl_frame *f;
01249
01250
01251
01252 assure( frames != NULL, CPL_ERROR_ILLEGAL_INPUT, "Null frameset" );
01253 assure( tag != NULL, CPL_ERROR_ILLEGAL_INPUT, "Null tag" );
01254
01255 subset = cpl_frameset_new();
01256
01257 for (f = cpl_frameset_find_const(frames, tag);
01258 f != NULL;
01259 f = cpl_frameset_find_const(frames, NULL)) {
01260
01261 cpl_frameset_insert(subset, cpl_frame_duplicate(f));
01262 }
01263
01264 cleanup:
01265 return subset;
01266 }
01267
01268
01278
01279 inline double
01280 uves_pow_int(double x, int y)
01281 {
01282 double result = 1.0;
01283
01284
01285
01286
01287 while(y != 0)
01288 {
01289 if (y % 2 == 0)
01290 {
01291 x *= x;
01292 y /= 2;
01293 }
01294 else
01295 {
01296 if (y > 0)
01297 {
01298 result *= x;
01299 y -= 1;
01300 }
01301 else
01302 {
01303 result /= x;
01304 y += 1;
01305 }
01306 }
01307 }
01308
01309 return result;
01310 }
01311
01312
01313
01314
01315
01324
01325 inline long
01326 uves_round_double(double x)
01327 {
01328 return (x >=0) ? (long)(x+0.5) : (long)(x-0.5);
01329 }
01330
01331
01340
01341 inline double
01342 uves_max_double(double x, double y)
01343 {
01344 return (x >=y) ? x : y;
01345 }
01346
01355
01356 inline int
01357 uves_max_int(int x, int y)
01358 {
01359 return (x >=y) ? x : y;
01360 }
01361
01362
01371
01372 inline double
01373 uves_min_double(double x, double y)
01374 {
01375 return (x <=y) ? x : y;
01376 }
01377
01386
01387 inline int
01388 uves_min_int(int x, int y)
01389 {
01390 return (x <=y) ? x : y;
01391 }
01392
01393
01404
01405 inline double
01406 uves_error_fraction(double x, double y, double dx, double dy)
01407 {
01408
01409
01410
01411 return sqrt( dx*dx/(y*y) + x*x*dy*dy/(y*y*y*y) );
01412 }
01413
01414
01415
01416
01425
01426 cpl_error_code
01427 uves_get_version(int *major, int *minor, int *micro)
01428 {
01429
01430 if (major != NULL) *major = UVES_MAJOR_VERSION;
01431 if (minor != NULL) *minor = UVES_MINOR_VERSION;
01432 if (micro != NULL) *micro = UVES_MICRO_VERSION;
01433
01434 return cpl_error_get_code();
01435 }
01436
01437
01438
01444
01445 int
01446 uves_get_version_binary(void)
01447 {
01448 return UVES_BINARY_VERSION;
01449 }
01450
01451
01452
01460
01461 const char *
01462 uves_get_license(void)
01463 {
01464 return
01465 "This file is part of the ESO UVES Instrument Pipeline\n"
01466 "Copyright (C) 2004,2005,2006 European Southern Observatory\n"
01467 "\n"
01468 "This program is free software; you can redistribute it and/or modify\n"
01469 "it under the terms of the GNU General Public License as published by\n"
01470 "the Free Software Foundation; either version 2 of the License, or\n"
01471 "(at your option) any later version.\n"
01472 "\n"
01473 "This program is distributed in the hope that it will be useful,\n"
01474 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
01475 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
01476 "GNU General Public License for more details.\n"
01477 "\n"
01478 "You should have received a copy of the GNU General Public License\n"
01479 "along with this program; if not, write to the Free Software\n"
01480 "Foundation, 51 Franklin St, Fifth Floor, Boston, \n"
01481 "MA 02111-1307 USA" ;
01482
01483
01484 }
01485
01486
01496
01497
01498 #define REQ_CPL_MAJOR 3
01499 #define REQ_CPL_MINOR 1
01500 #define REQ_CPL_MICRO 0
01501
01502 #define REQ_QF_MAJOR 6
01503 #define REQ_QF_MINOR 2
01504 #define REQ_QF_MICRO 0
01505
01506 void
01507 uves_check_version(void)
01508 {
01509 #ifdef CPL_VERSION_CODE
01510 #if CPL_VERSION_CODE >= CPL_VERSION(REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO)
01511 uves_msg_debug("Compile time CPL version code was %d "
01512 "(version %d-%d-%d, code %d required)",
01513 CPL_VERSION_CODE, REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO,
01514 CPL_VERSION(REQ_CPL_MAJOR, REQ_CPL_MINOR, REQ_CPL_MICRO));
01515 #else
01516 #error CPL version too old
01517 #endif
01518 #else
01519 #error CPL_VERSION_CODE not defined. CPL version too old
01520 #endif
01521
01522 if (cpl_version_get_major() < REQ_CPL_MAJOR ||
01523 (cpl_version_get_major() == REQ_CPL_MAJOR &&
01524 (int) cpl_version_get_minor() < REQ_CPL_MINOR) ||
01525
01526 (cpl_version_get_major() == REQ_CPL_MAJOR &&
01527 cpl_version_get_minor() == REQ_CPL_MINOR &&
01528 (int) cpl_version_get_micro() < REQ_CPL_MICRO)
01529 )
01530 {
01531 uves_msg_warning("CPL version %s (%d.%d.%d) (detected) is not supported. "
01532 "Please update to CPL version %d.%d.%d or later",
01533 cpl_version_get_version(),
01534 cpl_version_get_major(),
01535 cpl_version_get_minor(),
01536 cpl_version_get_micro(),
01537 REQ_CPL_MAJOR,
01538 REQ_CPL_MINOR,
01539 REQ_CPL_MICRO);
01540 }
01541 else
01542 {
01543 uves_msg_debug("Runtime CPL version %s (%d.%d.%d) detected (%d.%d.%d or later required)",
01544 cpl_version_get_version(),
01545 cpl_version_get_major(),
01546 cpl_version_get_minor(),
01547 cpl_version_get_micro(),
01548 REQ_CPL_MAJOR,
01549 REQ_CPL_MINOR,
01550 REQ_CPL_MICRO);
01551 }
01552
01553 {
01554 const char *qfts_v = " ";
01555 char *suffix;
01556
01557 long qfts_major;
01558 long qfts_minor;
01559 long qfts_micro;
01560
01561 qfts_v = qfits_version();
01562
01563 assure( qfts_v != NULL, CPL_ERROR_ILLEGAL_INPUT,
01564 "Error reading qfits version");
01565
01566
01567 qfts_major = strtol(qfts_v, &suffix, 10);
01568 assure( suffix != NULL && suffix[0] == '.' && suffix[1] != '\0',
01569 CPL_ERROR_ILLEGAL_INPUT,
01570 "Error parsing version string '%s'. "
01571 "Format 'X.Y.Z' expected", qfts_v);
01572
01573
01574 qfts_minor = strtol(suffix+1, &suffix, 10);
01575 assure( suffix != NULL && suffix[0] == '.' && suffix[1] != '\0',
01576 CPL_ERROR_ILLEGAL_INPUT,
01577 "Error parsing version string '%s'. "
01578 "Format 'X.Y.Z' expected", qfts_v);
01579
01580
01581 qfts_micro = strtol(suffix+1, &suffix, 10);
01582
01583
01584 if (qfts_major < REQ_QF_MAJOR ||
01585 (qfts_major == REQ_QF_MAJOR && qfts_minor < REQ_QF_MINOR) ||
01586 (qfts_major == REQ_QF_MAJOR && qfts_minor == REQ_QF_MINOR &&
01587 qfts_micro < REQ_QF_MICRO)
01588 )
01589 {
01590 uves_msg_warning("qfits version %s (detected) is not supported. "
01591 "Please update to qfits version %d.%d.%d or later",
01592 qfts_v,
01593 REQ_QF_MAJOR,
01594 REQ_QF_MINOR,
01595 REQ_QF_MICRO);
01596 }
01597 else
01598 {
01599 uves_msg_debug("qfits version %ld.%ld.%ld detected "
01600 "(%d.%d.%d or later required)",
01601 qfts_major, qfts_minor, qfts_micro,
01602 REQ_QF_MAJOR,
01603 REQ_QF_MINOR,
01604 REQ_QF_MICRO);
01605 }
01606 }
01607
01608 cleanup:
01609 return;
01610 }
01611
01612
01624
01625 cpl_error_code
01626 uves_end(const char *recipe_id, const cpl_frameset *frames)
01627 {
01628 cpl_frameset *products = NULL;
01629 const cpl_frame *f;
01630 int warnings = uves_msg_get_warnings();
01631
01632 recipe_id = recipe_id;
01633
01634
01635
01636
01637
01638
01639 products = cpl_frameset_new();
01640 assure_mem( products );
01641
01642 for (f = cpl_frameset_get_first_const(frames);
01643 f != NULL;
01644 f = cpl_frameset_get_next_const(frames))
01645 {
01646 if (cpl_frame_get_group(f) == CPL_FRAME_GROUP_PRODUCT)
01647 {
01648 check_nomsg(
01649 cpl_frameset_insert(products, cpl_frame_duplicate(f)));
01650 }
01651 }
01652
01653
01654
01655
01656
01657
01658
01659
01660 if( warnings > 0)
01661 {
01662 uves_msg_warning("Recipe produced %d warning%s (excluding this one)",
01663 uves_msg_get_warnings(),
01664 (warnings > 1) ? "s" : "");
01665 }
01666
01667 cleanup:
01668 uves_free_frameset(&products);
01669 return cpl_error_get_code();
01670 }
01671
01672
01693
01694 char *
01695 uves_initialize(cpl_frameset *frames, const cpl_parameterlist *parlist,
01696 const char *recipe_id, const char *short_descr)
01697 {
01698 char *recipe_string = NULL;
01699 char *stars = NULL;
01700 char *spaces1 = NULL;
01701 char *spaces2 = NULL;
01702 char *spaces3 = NULL;
01703 char *spaces4 = NULL;
01704 char *start_time = NULL;
01705
01706 start_time = uves_sprintf("%s", qfits_get_datetime_iso8601());
01707
01708 check( uves_check_version(), "Library validation failed");
01709
01710
01711 {
01712 const char *plotter_command;
01713 int msglevel;
01714
01715
01716
01717 if (0)
01718 check( uves_get_parameter(parlist, NULL, "uves", "msginfolevel",
01719 CPL_TYPE_INT, &msglevel),
01720 "Could not read parameter");
01721 else
01722 {
01723 msglevel = -1;
01724 }
01725 uves_msg_set_level(msglevel);
01726 check( uves_get_parameter(parlist, NULL, "uves", "plotter",
01727 CPL_TYPE_STRING, &plotter_command), "Could not read parameter");
01728
01729
01730 check( uves_plot_initialize(plotter_command),
01731 "Could not initialize plotting");
01732 }
01733
01734
01735
01736
01737
01738
01739
01740 recipe_string = uves_sprintf("Recipe: %s", recipe_id);
01741 {
01742 int field = uves_max_int(strlen(PACKAGE_STRING), strlen(recipe_string));
01743 int nstars = 3+1 + field + 1+3;
01744 int nspaces1, nspaces2, nspaces3, nspaces4;
01745 int i;
01746
01747
01748 nspaces1 = (field - strlen(PACKAGE_STRING)) / 2;
01749 nspaces2 = field - strlen(PACKAGE_STRING) - nspaces1;
01750
01751 nspaces3 = (field - strlen(recipe_string)) / 2;
01752 nspaces4 = field - strlen(recipe_string) - nspaces3;
01753
01754 spaces1 = cpl_calloc(nspaces1 + 1, sizeof(char));
01755 spaces2 = cpl_calloc(nspaces2 + 1, sizeof(char));
01756 spaces3 = cpl_calloc(nspaces3 + 1, sizeof(char));
01757 spaces4 = cpl_calloc(nspaces4 + 1, sizeof(char));
01758 for (i = 0; i < nspaces1; i++) spaces1[i] = ' ';
01759 for (i = 0; i < nspaces2; i++) spaces2[i] = ' ';
01760 for (i = 0; i < nspaces3; i++) spaces3[i] = ' ';
01761 for (i = 0; i < nspaces4; i++) spaces4[i] = ' ';
01762
01763 stars = cpl_calloc(nstars + 1, sizeof(char));
01764 for (i = 0; i < nstars; i++) stars[i] = '*';
01765
01766 uves_msg("%s", stars);
01767 uves_msg("*** %s%s%s ***", spaces1, PACKAGE_STRING, spaces2);
01768 uves_msg("*** %s%s%s ***", spaces3, recipe_string, spaces4);
01769 uves_msg("%s", stars);
01770 }
01771
01772 uves_msg("This recipe %c%s", tolower(short_descr[0]), short_descr+1);
01773
01774 if (cpl_frameset_is_empty(frames)) {
01775 uves_msg_debug("Guvf cvcryvar unf ernpurq vgf uvtu dhnyvgl qhr na npgvir "
01776 "hfre pbzzhavgl naq gur erfcbafvoyr naq vqrnyvfgvp jbex bs "
01777 "vaqvivqhny cvcryvar qrirybcref, naq qrfcvgr orvat 'onfrq ba' "
01778 "PCY juvpu vf n cvrpr bs cbyvgvpny penc");
01779 }
01780
01781
01782
01783
01784 check( uves_dfs_set_groups(frames), "Could not classify input frames");
01785
01786
01787 uves_msg_low("Input frames");
01788 check( uves_print_cpl_frameset(frames), "Could not print input frames" );
01789
01790 cleanup:
01791 cpl_free(recipe_string);
01792 cpl_free(stars);
01793 cpl_free(spaces1);
01794 cpl_free(spaces2);
01795 cpl_free(spaces3);
01796 cpl_free(spaces4);
01797 return start_time;
01798 }
01799
01800
01801
01829
01830 cpl_image *
01831 uves_average_images(const cpl_image *image1, const cpl_image *noise1,
01832 const cpl_image *image2, const cpl_image *noise2,
01833 cpl_image **noise)
01834 {
01835 cpl_image *result = NULL;
01836 int nx, ny, x, y;
01837
01838
01839 assure( image1 != NULL, CPL_ERROR_NULL_INPUT, "Null image");
01840 assure( image2 != NULL, CPL_ERROR_NULL_INPUT, "Null image");
01841 assure( noise1 != NULL, CPL_ERROR_NULL_INPUT, "Null image");
01842 assure( noise2 != NULL, CPL_ERROR_NULL_INPUT, "Null image");
01843 assure( noise != NULL, CPL_ERROR_NULL_INPUT, "Null image");
01844
01845 assure( cpl_image_get_min(noise1) > 0, CPL_ERROR_ILLEGAL_INPUT,
01846 "Noise must be everywhere positive, minimum = %e", cpl_image_get_min(noise1));
01847 assure( cpl_image_get_min(noise2) > 0, CPL_ERROR_ILLEGAL_INPUT,
01848 "Noise must be everywhere positive, minimum = %e", cpl_image_get_min(noise2));
01849
01850 nx = cpl_image_get_size_x(image1);
01851 ny = cpl_image_get_size_y(image1);
01852
01853 assure( nx == cpl_image_get_size_x(image2), CPL_ERROR_INCOMPATIBLE_INPUT,
01854 "Size mismatch %d != %d",
01855 nx, cpl_image_get_size_x(image2));
01856 assure( nx == cpl_image_get_size_x(noise1), CPL_ERROR_INCOMPATIBLE_INPUT,
01857 "Size mismatch %d != %d",
01858 nx, cpl_image_get_size_x(noise1));
01859 assure( nx == cpl_image_get_size_x(noise2), CPL_ERROR_INCOMPATIBLE_INPUT,
01860 "Size mismatch %d != %d",
01861 nx, cpl_image_get_size_x(noise2));
01862 assure( ny == cpl_image_get_size_y(image2), CPL_ERROR_INCOMPATIBLE_INPUT,
01863 "Size mismatch %d != %d",
01864 ny, cpl_image_get_size_y(image2));
01865 assure( ny == cpl_image_get_size_y(noise1), CPL_ERROR_INCOMPATIBLE_INPUT,
01866 "Size mismatch %d != %d",
01867 ny, cpl_image_get_size_y(noise1));
01868 assure( ny == cpl_image_get_size_y(noise2), CPL_ERROR_INCOMPATIBLE_INPUT,
01869 "Size mismatch %d != %d",
01870 ny, cpl_image_get_size_y(noise2));
01871
01872 result = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
01873 *noise = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
01874
01875
01876 for (y = 1; y <= ny; y++)
01877 {
01878 for (x = 1; x <= nx; x++)
01879 {
01880 double flux1, flux2;
01881 double sigma1, sigma2;
01882 int pis_rejected1, noise_rejected1;
01883 int pis_rejected2, noise_rejected2;
01884
01885 flux1 = cpl_image_get(image1, x, y, &pis_rejected1);
01886 flux2 = cpl_image_get(image2, x, y, &pis_rejected2);
01887 sigma1 = cpl_image_get(noise1, x, y, &noise_rejected1);
01888 sigma2 = cpl_image_get(noise2, x, y, &noise_rejected2);
01889
01890 pis_rejected1 = pis_rejected1 || noise_rejected1;
01891 pis_rejected2 = pis_rejected2 || noise_rejected2;
01892
01893 if (pis_rejected1 && pis_rejected2)
01894 {
01895 cpl_image_reject(result, x, y);
01896 cpl_image_reject(*noise, x, y);
01897 }
01898 else
01899 {
01900
01901
01902 double flux, sigma;
01903
01904 if (pis_rejected1 && !pis_rejected2)
01905 {
01906 flux = flux2;
01907 sigma = sigma2;
01908 }
01909 else if (!pis_rejected1 && pis_rejected2)
01910 {
01911 flux = flux1;
01912 sigma = sigma1;
01913 }
01914 else
01915 {
01916
01917 sigma =
01918 1 / (sigma1*sigma1) +
01919 1 / (sigma2*sigma2);
01920
01921 flux = flux1/(sigma1*sigma1) + flux2/(sigma2*sigma2);
01922 flux /= sigma;
01923
01924 sigma = sqrt(sigma);
01925 }
01926
01927 cpl_image_set(result, x, y, flux);
01928 cpl_image_set(*noise, x, y, sigma);
01929 }
01930 }
01931 }
01932
01933 cleanup:
01934 if (cpl_error_get_code() != CPL_ERROR_NONE)
01935 {
01936 uves_free_image(&result);
01937 }
01938 return result;
01939 }
01940
01941
01956
01957 uves_propertylist *
01958 uves_initialize_image_header(const char *ctype1, const char *ctype2, const char *bunit,
01959 double crval1, double crval2,
01960 double crpix1, double crpix2,
01961 double cdelt1, double cdelt2)
01962 {
01963 uves_propertylist *header = NULL;
01964
01965 header = uves_propertylist_new();
01966
01967 check( uves_pfits_set_ctype1(header, ctype1), "Error writing keyword");
01968 check( uves_pfits_set_ctype2(header, ctype2), "Error writing keyword");
01969 check( uves_pfits_set_bunit (header, bunit ), "Error writing keyword");
01970 check( uves_pfits_set_crval1(header, crval1), "Error writing keyword");
01971 check( uves_pfits_set_crval2(header, crval2), "Error writing keyword");
01972 check( uves_pfits_set_crpix1(header, crpix1), "Error writing keyword");
01973 check( uves_pfits_set_crpix2(header, crpix2), "Error writing keyword");
01974 check( uves_pfits_set_cdelt1(header, cdelt1), "Error writing keyword");
01975 check( uves_pfits_set_cdelt2(header, cdelt2), "Error writing keyword");
01976
01977 cleanup:
01978 return header;
01979 }
01980
01981
01999
02000 cpl_image *
02001 uves_define_noise(const cpl_image *image, const uves_propertylist *image_header,
02002 int ncom, enum uves_chip chip)
02003 {
02004
02005
02006
02007
02008
02009 cpl_image *noise = NULL;
02010
02011
02012
02013 double ron;
02014 double gain;
02015 int nx, ny, i;
02016 double *noise_data;
02017 const double *image_data;
02018
02019
02020 assure( ncom >= 1, CPL_ERROR_ILLEGAL_INPUT, "Number of combined frames = %d", ncom);
02021
02022 check( ron = uves_pfits_get_ron_adu(image_header, chip),
02023 "Could not read read-out noise");
02024
02025 check( gain = uves_pfits_get_gain(image_header, chip),
02026 "Could not read gain factor");
02027 assure( gain > 0, CPL_ERROR_ILLEGAL_INPUT, "Non-positive gain: %e", gain);
02028
02029 nx = cpl_image_get_size_x(image);
02030 ny = cpl_image_get_size_y(image);
02031
02032
02033 assure(cpl_image_count_rejected(image) == 0,
02034 CPL_ERROR_UNSUPPORTED_MODE, "Input image contains bad pixels");
02035 assure(cpl_image_get_type(image) == CPL_TYPE_DOUBLE,
02036 CPL_ERROR_UNSUPPORTED_MODE,
02037 "Input image is of type %s. double expected",
02038 uves_tostring_cpl_type(cpl_image_get_type(image)));
02039
02040 noise = cpl_image_new(nx, ny, CPL_TYPE_DOUBLE);
02041 assure_mem( noise );
02042
02043 noise_data = cpl_image_get_data_double(noise);
02044
02045 image_data = cpl_image_get_data_double_const(image);
02046
02047
02048
02049
02050
02051
02052
02053
02054
02055
02056
02057
02058
02059
02060
02061
02062
02063
02064
02065 for (i = 0; i < nx*ny; i++)
02066 {
02067 double flux;
02068
02069
02070
02071 flux = image_data[i];
02072 {
02073 double flux_e = uves_max_double(0, flux) / gain;
02074 double sigma_e = sqrt(flux_e);
02075 double sigma_adu = sigma_e * gain;
02076 double quant_var = uves_max_double(0, (gain*gain - 1)/12.0);
02077
02078
02079
02080
02081
02082
02083
02084
02085
02086
02087
02088
02089
02090
02091
02092
02093 double median_factor = (ncom > 1) ? 2.0/M_PI : 1.0;
02094
02095
02096
02097
02098
02099 noise_data[i] = sqrt((ron*ron + quant_var + sigma_adu*sigma_adu)
02100 / (ncom * median_factor));
02101 }
02102 }
02103
02104 cleanup:
02105
02106 if (cpl_error_get_code() != CPL_ERROR_NONE)
02107 {
02108 uves_free_image(&noise);
02109 }
02110
02111 return noise;
02112 }
02113
02114
02115
02125
02126 cpl_error_code
02127 uves_subtract_bias(cpl_image *image, const cpl_image *master_bias)
02128 {
02129 passure ( image != NULL, " ");
02130 passure ( master_bias != NULL, " ");
02131
02132 check( cpl_image_subtract(image, master_bias),
02133 "Error subtracting bias");
02134
02135
02136
02137
02138
02139 #if 0
02140
02141
02142
02143
02144
02145
02146
02147 check( cpl_image_threshold(image,
02148 0, DBL_MAX,
02149 0, DBL_MAX),
02150 "Error thresholding image");
02151 #endif
02152
02153 cleanup:
02154 return cpl_error_get_code();
02155 }
02156
02169
02170 cpl_error_code
02171 uves_subtract_dark(cpl_image *image, const uves_propertylist *image_header,
02172 const cpl_image *master_dark,
02173 const uves_propertylist *mdark_header)
02174 {
02175 cpl_image *normalized_mdark = NULL;
02176 double image_exptime = 0.0;
02177 double mdark_exptime = 0.0;
02178
02179 passure ( image != NULL, " ");
02180 passure ( image_header != NULL, " ");
02181 passure ( master_dark != NULL, " ");
02182 passure ( mdark_header != NULL, " ");
02183
02184
02185 check( image_exptime = uves_pfits_get_exptime(image_header),
02186 "Error reading input image exposure time");
02187 check( mdark_exptime = uves_pfits_get_exptime(mdark_header),
02188 "Error reading master dark exposure time");
02189
02190 uves_msg("Rescaling master dark from %f s to %f s exposure time",
02191 mdark_exptime, image_exptime);
02192
02193 check( normalized_mdark =
02194 cpl_image_multiply_scalar_create(master_dark,
02195 image_exptime / mdark_exptime),
02196 "Error normalizing master dark");
02197
02198 check( cpl_image_subtract(image, normalized_mdark),
02199 "Error subtracting master dark");
02200
02201 cleanup:
02202 uves_free_image(&normalized_mdark);
02203 return cpl_error_get_code();
02204 }
02205
02206
02220
02221 int uves_absolute_order(int first_abs_order, int last_abs_order, int relative_order)
02222 {
02223 return (first_abs_order +
02224 (relative_order-1)*((last_abs_order > first_abs_order) ? 1 : -1));
02225 }
02226
02227
02241
02242 double
02243 uves_average_reject(cpl_table *t,
02244 const char *column,
02245 const char *residual2,
02246 double kappa)
02247 {
02248 double mean = 0, median, sigma2;
02249 int rejected;
02250
02251 do {
02252
02253 median = cpl_table_get_column_median(t, column);
02254
02255
02256
02257 cpl_table_duplicate_column(t, residual2, t, column);
02258 cpl_table_subtract_scalar(t, residual2, median);
02259 cpl_table_multiply_columns(t, residual2, residual2);
02260
02261
02262
02263
02264
02265
02266 sigma2 = cpl_table_get_column_median(t, residual2) / (0.6744 * 0.6744);
02267
02268
02269
02270
02271 check_nomsg( rejected = uves_erase_table_rows(t, residual2,
02272 CPL_GREATER_THAN,
02273 kappa*kappa*sigma2));
02274
02275 cpl_table_erase_column(t, residual2);
02276
02277 } while (rejected > 0);
02278
02279 mean = cpl_table_get_column_mean(t, column);
02280
02281 cleanup:
02282 return mean;
02283 }
02284
02285
02318
02319 polynomial *
02320 uves_polynomial_regression_1d(cpl_table *t,
02321 const char *X, const char *Y, const char *sigmaY,
02322 int degree,
02323 const char *polynomial_fit, const char *residual_square,
02324 double *mean_squared_error, double kappa)
02325 {
02326 int N;
02327 int total_rejected = 0;
02328 int rejected = 0;
02329 double mse;
02330 double *x;
02331 double *y;
02332 double *sy;
02333 polynomial *result = NULL;
02334 cpl_vector *vx = NULL;
02335 cpl_vector *vy = NULL;
02336 cpl_vector *vsy = NULL;
02337 cpl_type type;
02338
02339
02340 assure( t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
02341 assure( X != NULL, CPL_ERROR_NULL_INPUT, "Null column name");
02342 assure( Y != NULL, CPL_ERROR_NULL_INPUT, "Null column name");
02343 assure( cpl_table_has_column(t, X), CPL_ERROR_ILLEGAL_INPUT, "No such column: %s", X);
02344 assure( cpl_table_has_column(t, Y), CPL_ERROR_ILLEGAL_INPUT, "No such column: %s", Y);
02345 assure( sigmaY == NULL || cpl_table_has_column(t, sigmaY) , CPL_ERROR_ILLEGAL_INPUT,
02346 "No such column: %s", sigmaY);
02347
02348 assure( polynomial_fit == NULL || !cpl_table_has_column(t, polynomial_fit),
02349 CPL_ERROR_ILLEGAL_INPUT, "Column '%s' already present", polynomial_fit);
02350
02351 assure( residual_square == NULL || !cpl_table_has_column(t, residual_square),
02352 CPL_ERROR_ILLEGAL_INPUT, "Column '%s' already present", residual_square);
02353
02354
02355 type = cpl_table_get_column_type(t, Y);
02356 assure( type == CPL_TYPE_DOUBLE || type == CPL_TYPE_INT, CPL_ERROR_INVALID_TYPE,
02357 "Input column '%s' has wrong type (%s)", Y, uves_tostring_cpl_type(type));
02358 type = cpl_table_get_column_type(t, X);
02359 assure( type == CPL_TYPE_DOUBLE || type == CPL_TYPE_INT, CPL_ERROR_INVALID_TYPE,
02360 "Input column '%s' has wrong type (%s)", X, uves_tostring_cpl_type(type));
02361 if (sigmaY != NULL)
02362 {
02363 type = cpl_table_get_column_type(t, sigmaY);
02364 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE,
02365 CPL_ERROR_INVALID_TYPE,
02366 "Input column '%s' has wrong type (%s)",
02367 sigmaY, uves_tostring_cpl_type(type));
02368 }
02369
02370 check( cpl_table_cast_column(t, X, "_X_double", CPL_TYPE_DOUBLE),
02371 "Could not cast table column '%s' to double", X);
02372 check( cpl_table_cast_column(t, Y, "_Y_double", CPL_TYPE_DOUBLE),
02373 "Could not cast table column '%s' to double", Y);
02374 if (sigmaY != NULL)
02375 {
02376 check( cpl_table_cast_column(t, sigmaY, "_sY_double", CPL_TYPE_DOUBLE),
02377 "Could not cast table column '%s' to double", sigmaY);
02378 }
02379
02380 total_rejected = 0;
02381 rejected = 0;
02382 check( cpl_table_new_column(t, "_residual_square", CPL_TYPE_DOUBLE),
02383 "Could not create column");
02384 do{
02385 check( (N = cpl_table_get_nrow(t),
02386 x = cpl_table_get_data_double(t, "_X_double"),
02387 y = cpl_table_get_data_double(t, "_Y_double")),
02388 "Could not read table data");
02389
02390 if (sigmaY != NULL)
02391 {
02392 check( sy = cpl_table_get_data_double(t, "_sY_double"),
02393 "Could not read table data");
02394 }
02395 else
02396 {
02397 sy = NULL;
02398 }
02399
02400 assure( N > 0, CPL_ERROR_ILLEGAL_INPUT, "Empty table");
02401
02402
02403 uves_unwrap_vector(&vx);
02404 uves_unwrap_vector(&vy);
02405
02406 vx = cpl_vector_wrap(N, x);
02407 vy = cpl_vector_wrap(N, y);
02408
02409 if (sy != NULL)
02410 {
02411 uves_unwrap_vector(&vsy);
02412 vsy = cpl_vector_wrap(N, sy);
02413 }
02414 else
02415 {
02416 vsy = NULL;
02417 }
02418
02419
02420 uves_polynomial_delete(&result);
02421 check( result = uves_polynomial_fit_1d(vx, vy, vsy, degree, &mse),
02422 "Could not fit polynomial");
02423
02424
02425 if (kappa > 0)
02426 {
02427 double sigma2;
02428 int i;
02429
02430 for (i = 0; i < N; i++)
02431 {
02432 double xval, yval, yfit;
02433
02434 check(( xval = cpl_table_get_double(t, "_X_double", i, NULL),
02435 yval = cpl_table_get_double(t, "_Y_double" ,i, NULL),
02436 yfit = uves_polynomial_evaluate_1d(result, xval),
02437
02438 cpl_table_set_double(t, "_residual_square", i,
02439 (yfit-yval)*(yfit-yval))),
02440 "Could not evaluate polynomial");
02441 }
02442
02443
02444
02445
02446
02447
02448
02449 sigma2 = cpl_table_get_column_median(t, "_residual_square") / (0.6744 * 0.6744);
02450
02451
02452 check( rejected = uves_erase_table_rows(t, "_residual_square",
02453 CPL_GREATER_THAN, kappa*kappa*sigma2),
02454 "Could not remove outlier points");
02455
02456 uves_msg_debug("%d of %d points rejected in kappa-sigma clipping. rms=%f",
02457 rejected, N, sqrt(mse));
02458
02459
02460 total_rejected += rejected;
02461 N = cpl_table_get_nrow(t);
02462 }
02463
02464 } while (rejected > 0);
02465
02466 cpl_table_erase_column(t, "_residual_square");
02467
02468 if (kappa > 0)
02469 {
02470 uves_msg_debug("%d of %d points (%f %%) rejected in kappa-sigma clipping",
02471 total_rejected,
02472 N + total_rejected,
02473 (100.0*total_rejected)/(N + total_rejected)
02474 );
02475 }
02476
02477 if (mean_squared_error != NULL) *mean_squared_error = mse;
02478
02479
02480 if (polynomial_fit != NULL || residual_square != NULL)
02481 {
02482 int i;
02483
02484 check( cpl_table_new_column(t, "_polynomial_fit", CPL_TYPE_DOUBLE),
02485 "Could not create column");
02486 for (i = 0; i < N; i++){
02487 double xval;
02488 double yfit;
02489
02490 check((
02491 xval = cpl_table_get_double(t, "_X_double", i, NULL),
02492 yfit = uves_polynomial_evaluate_1d(result, xval),
02493 cpl_table_set_double(t, "_polynomial_fit", i, yfit)),
02494 "Could not evaluate polynomial");
02495 }
02496
02497
02498 if (residual_square != NULL)
02499 {
02500 check(( cpl_table_duplicate_column(t, residual_square,
02501 t, "_polynomial_fit"),
02502 cpl_table_subtract_columns(t, residual_square, Y),
02503 cpl_table_multiply_columns(t, residual_square, residual_square)),
02504
02505 "Could not calculate Residual of fit");
02506 }
02507
02508
02509 if (polynomial_fit != NULL)
02510 {
02511 cpl_table_name_column(t, "_polynomial_fit", polynomial_fit);
02512 }
02513 else
02514 {
02515 cpl_table_erase_column(t, "_polynomial_fit");
02516 }
02517 }
02518
02519 check(( cpl_table_erase_column(t, "_X_double"),
02520 cpl_table_erase_column(t, "_Y_double")),
02521 "Could not delete temporary columns");
02522
02523 if (sigmaY != NULL)
02524 {
02525 check( cpl_table_erase_column(t, "_sY_double"),
02526 "Could not delete temporary column");
02527 }
02528
02529 cleanup:
02530 uves_unwrap_vector(&vx);
02531 uves_unwrap_vector(&vy);
02532 uves_unwrap_vector(&vsy);
02533 if (cpl_error_get_code() != CPL_ERROR_NONE)
02534 {
02535 uves_polynomial_delete(&result);
02536 }
02537
02538 return result;
02539 }
02540
02541
02542
02590
02591
02592 polynomial *
02593 uves_polynomial_regression_2d(cpl_table *t,
02594 const char *X1, const char *X2, const char *Y,
02595 const char *sigmaY,
02596 int degree1, int degree2,
02597 const char *polynomial_fit, const char *residual_square,
02598 const char *variance_fit,
02599 double *mse, double *red_chisq,
02600 polynomial **variance, double kappa,
02601 double min_reject)
02602 {
02603 int N;
02604 int rejected;
02605 int total_rejected;
02606 double *x1;
02607 double *x2;
02608 double *y;
02609 double *res;
02610 double *sy;
02611 polynomial *p = NULL;
02612 polynomial *variance_local = NULL;
02613 cpl_vector *vx1 = NULL;
02614 cpl_vector *vx2 = NULL;
02615 cpl_bivector *vx = NULL;
02616 cpl_vector *vy = NULL;
02617 cpl_vector *vsy= NULL;
02618 cpl_type type;
02619
02620
02621 assure( t != NULL, CPL_ERROR_NULL_INPUT, "Null table");
02622 assure( cpl_table_has_column(t, X1), CPL_ERROR_ILLEGAL_INPUT, "No such column: %s", X1);
02623 assure( cpl_table_has_column(t, X2), CPL_ERROR_ILLEGAL_INPUT, "No such column: %s", X2);
02624 assure( cpl_table_has_column(t, Y) , CPL_ERROR_ILLEGAL_INPUT, "No such column: %s", Y);
02625 assure( (variance == NULL && variance_fit == NULL) || sigmaY != NULL,
02626 CPL_ERROR_INCOMPATIBLE_INPUT, "Cannot calculate variances without sigmaY");
02627 if (sigmaY != NULL)
02628 {
02629 assure( cpl_table_has_column(t, sigmaY) , CPL_ERROR_ILLEGAL_INPUT,
02630 "No such column: %s", sigmaY);
02631 }
02632 if (polynomial_fit != NULL)
02633 {
02634 assure( !cpl_table_has_column(t, polynomial_fit) , CPL_ERROR_ILLEGAL_INPUT,
02635 "Table already has '%s' column", polynomial_fit);
02636 }
02637 if (residual_square != NULL)
02638 {
02639 assure( !cpl_table_has_column(t, residual_square), CPL_ERROR_ILLEGAL_INPUT,
02640 "Table already has '%s' column", residual_square);
02641 }
02642 if (variance_fit != NULL)
02643 {
02644 assure( !cpl_table_has_column(t, variance_fit) , CPL_ERROR_ILLEGAL_INPUT,
02645 "Table already has '%s' column", variance_fit);
02646 }
02647
02648
02649 type = cpl_table_get_column_type(t, X1);
02650 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE,
02651 "Input column '%s' has wrong type (%s)", X1, uves_tostring_cpl_type(type));
02652 type = cpl_table_get_column_type(t, X2);
02653 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE,
02654 "Input column '%s' has wrong type (%s)", X2, uves_tostring_cpl_type(type));
02655 type = cpl_table_get_column_type(t, Y);
02656 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE,
02657 "Input column '%s' has wrong type (%s)", Y, uves_tostring_cpl_type(type));
02658 if (sigmaY != NULL)
02659 {
02660 type = cpl_table_get_column_type(t, sigmaY);
02661 assure( type == CPL_TYPE_INT || type == CPL_TYPE_DOUBLE, CPL_ERROR_INVALID_TYPE,
02662 "Input column '%s' has wrong type (%s)",
02663 sigmaY, uves_tostring_cpl_type(type));
02664 }
02665
02666
02667 check( cpl_table_cast_column(t, X1 , "_X1_double", CPL_TYPE_DOUBLE),
02668 "Could not cast table column to double");
02669 check( cpl_table_cast_column(t, X2 , "_X2_double", CPL_TYPE_DOUBLE),
02670 "Could not cast table column to double");
02671 check( cpl_table_cast_column(t, Y , "_Y_double", CPL_TYPE_DOUBLE),
02672 "Could not cast table column to double");
02673 if (sigmaY != NULL)
02674 {
02675 check( cpl_table_cast_column(t, sigmaY, "_sY_double", CPL_TYPE_DOUBLE),
02676 "Could not cast table column to double");
02677 }
02678
02679 total_rejected = 0;
02680 rejected = 0;
02681 check( cpl_table_new_column(t, "_residual_square", CPL_TYPE_DOUBLE),
02682 "Could not create column");
02683
02684 do {
02685
02686
02687 check(( N = cpl_table_get_nrow(t),
02688 x1 = cpl_table_get_data_double(t, "_X1_double"),
02689 x2 = cpl_table_get_data_double(t, "_X2_double"),
02690 y = cpl_table_get_data_double(t, "_Y_double"),
02691 res= cpl_table_get_data_double(t, "_residual_square")),
02692 "Could not read table data");
02693
02694 if (sigmaY != NULL)
02695 {
02696 check (sy = cpl_table_get_data_double(t, "_sY_double"),
02697 "Could not read table data");
02698 }
02699 else
02700 {
02701 sy = NULL;
02702 }
02703
02704 assure( N > 0, CPL_ERROR_ILLEGAL_INPUT, "Empty table");
02705
02706
02707 uves_unwrap_vector(&vx1);
02708 uves_unwrap_vector(&vx2);
02709 uves_unwrap_vector(&vy);
02710
02711 vx1 = cpl_vector_wrap(N, x1);
02712 vx2 = cpl_vector_wrap(N, x2);
02713 vy = cpl_vector_wrap(N, y);
02714 if (sy != NULL)
02715 {
02716 uves_unwrap_vector(&vsy);
02717 vsy = cpl_vector_wrap(N, sy);
02718 }
02719 else
02720 {
02721 vsy = NULL;
02722 }
02723
02724
02725 uves_unwrap_bivector_vectors(&vx);
02726 vx = cpl_bivector_wrap_vectors(vx1, vx2);
02727
02728
02729 uves_polynomial_delete(&p);
02730 check( p = uves_polynomial_fit_2d(vx, vy, vsy, degree1, degree2,
02731 NULL, NULL, NULL),
02732 "Could not fit polynomial");
02733
02734
02735 if (kappa > 0)
02736 {
02737 double sigma2;
02738 int i;
02739
02740 cpl_table_fill_column_window_double(t, "_residual_square", 0,
02741 cpl_table_get_nrow(t), 0.0);
02742
02743 for (i = 0; i < N; i++)
02744 {
02745 double yval, yfit;
02746
02747 yval = y[i];
02748 yfit = uves_polynomial_evaluate_2d(p, x1[i], x2[i]);
02749 res[i] = (yfit-y[i])*(yfit-y[i]);
02750 }
02751
02752
02753
02754
02755
02756
02757
02758 sigma2 = cpl_table_get_column_median(t, "_residual_square") / (0.6744 * 0.6744);
02759
02760
02761
02762 check( rejected = uves_erase_table_rows(t, "_residual_square",
02763 CPL_GREATER_THAN, kappa*kappa*sigma2),
02764 "Could not remove outlier points");
02765
02766
02767
02768 uves_msg_debug("%d of %d points rejected in kappa-sigma clipping. rms=%f",
02769 rejected, N, sqrt(sigma2));
02770
02771
02772 total_rejected += rejected;
02773 N = cpl_table_get_nrow(t);
02774 }
02775
02776
02777
02778
02779 } while (rejected > 0 && rejected > min_reject*(N+rejected) &&
02780 N >= (degree1 + 1)*(degree2 + 1) + 1);
02781
02782 if (kappa > 0)
02783 {
02784 uves_msg_debug("%d of %d points (%f %%) rejected in kappa-sigma clipping",
02785 total_rejected,
02786 N + total_rejected,
02787 (100.0*total_rejected)/(N + total_rejected)
02788 );
02789 }
02790
02791
02792 {
02793
02794
02795
02796
02797 check(( N = cpl_table_get_nrow(t),
02798 x1 = cpl_table_get_data_double(t, "_X1_double"),
02799 x2 = cpl_table_get_data_double(t, "_X2_double"),
02800 y = cpl_table_get_data_double(t, "_Y_double"),
02801 res= cpl_table_get_data_double(t, "_residual_square")),
02802 "Could not read table data");
02803
02804 if (sigmaY != NULL)
02805 {
02806 check (sy = cpl_table_get_data_double(t, "_sY_double"),
02807 "Could not read table data");
02808 }
02809 else
02810 {
02811 sy = NULL;
02812 }
02813
02814 assure( N > 0, CPL_ERROR_ILLEGAL_INPUT, "Empty table");
02815
02816
02817 uves_unwrap_vector(&vx1);
02818 uves_unwrap_vector(&vx2);
02819 uves_unwrap_vector(&vy);
02820
02821 vx1 = cpl_vector_wrap(N, x1);
02822 vx2 = cpl_vector_wrap(N, x2);
02823 vy = cpl_vector_wrap(N, y);
02824 if (sy != NULL)
02825 {
02826 uves_unwrap_vector(&vsy);
02827 vsy = cpl_vector_wrap(N, sy);
02828 }
02829 else
02830 {
02831 vsy = NULL;
02832 }
02833
02834
02835 uves_unwrap_bivector_vectors(&vx);
02836 vx = cpl_bivector_wrap_vectors(vx1, vx2);
02837 }
02838
02839 uves_polynomial_delete(&p);
02840 if (variance_fit != NULL || variance != NULL)
02841 {
02842
02843 check( p = uves_polynomial_fit_2d(vx, vy, vsy, degree1, degree2,
02844 mse, red_chisq, &variance_local),
02845 "Could not fit polynomial");
02846 }
02847 else
02848 {
02849 check( p = uves_polynomial_fit_2d(vx, vy, vsy, degree1, degree2,
02850 mse, red_chisq, NULL),
02851 "Could not fit polynomial");
02852 }
02853
02854 cpl_table_erase_column(t, "_residual_square");
02855
02856
02857 if (polynomial_fit != NULL || residual_square != NULL)
02858 {
02859 int i;
02860 double *pf;
02861
02862 check( cpl_table_new_column(t, "_polynomial_fit", CPL_TYPE_DOUBLE),
02863 "Could not create column");
02864
02865 cpl_table_fill_column_window_double(t, "_polynomial_fit", 0,
02866 cpl_table_get_nrow(t), 0.0);
02867
02868 x1 = cpl_table_get_data_double(t, "_X1_double");
02869 x2 = cpl_table_get_data_double(t, "_X2_double");
02870 pf = cpl_table_get_data_double(t, "_polynomial_fit");
02871
02872 for (i = 0; i < N; i++){
02873 #if 0
02874 double x1val, x2val, yfit;
02875
02876 check(( x1val = cpl_table_get_double(t, "_X1_double", i, NULL),
02877 x2val = cpl_table_get_double(t, "_X2_double", i, NULL),
02878 yfit = uves_polynomial_evaluate_2d(p, x1val, x2val),
02879
02880 cpl_table_set_double(t, "_polynomial_fit", i, yfit)),
02881 "Could not evaluate polynomial");
02882
02883 #else
02884 pf[i] = uves_polynomial_evaluate_2d(p, x1[i], x2[i]);
02885 #endif
02886 }
02887
02888
02889 if (residual_square != NULL)
02890 {
02891 check(( cpl_table_duplicate_column(t, residual_square,
02892 t, "_polynomial_fit"),
02893 cpl_table_subtract_columns(t, residual_square, Y),
02894 cpl_table_multiply_columns(t, residual_square, residual_square)),
02895
02896 "Could not calculate Residual of fit");
02897 }
02898
02899
02900 if (polynomial_fit != NULL)
02901 {
02902 cpl_table_name_column(t, "_polynomial_fit", polynomial_fit);
02903 }
02904 else
02905 {
02906 cpl_table_erase_column(t, "_polynomial_fit");
02907 }
02908 }
02909
02910
02911 if (variance_fit != NULL)
02912 {
02913 int i;
02914 double *vf;
02915
02916 check( cpl_table_new_column(t, variance_fit, CPL_TYPE_DOUBLE),
02917 "Could not create column");
02918
02919 cpl_table_fill_column_window_double(t, variance_fit, 0,
02920 cpl_table_get_nrow(t), 0.0);
02921
02922 x1 = cpl_table_get_data_double(t, "_X1_double");
02923 x2 = cpl_table_get_data_double(t, "_X2_double");
02924 vf = cpl_table_get_data_double(t, variance_fit);
02925
02926 for (i = 0; i < N; i++)
02927 {
02928 #if 0
02929 double x1val, x2val, yfit_variance;
02930 check(( x1val = cpl_table_get_double(t, "_X1_double", i, NULL),
02931 x2val = cpl_table_get_double(t, "_X2_double", i, NULL),
02932 yfit_variance = uves_polynomial_evaluate_2d(variance_local,
02933 x1val, x2val),
02934
02935 cpl_table_set_double(t, variance_fit, i, yfit_variance)),
02936 "Could not evaluate polynomial");
02937 #else
02938 vf[i] = uves_polynomial_evaluate_2d(variance_local, x1[i], x2[i]);
02939 #endif
02940
02941 }
02942 }
02943
02944
02945 check(( cpl_table_erase_column(t, "_X1_double"),
02946 cpl_table_erase_column(t, "_X2_double"),
02947 cpl_table_erase_column(t, "_Y_double")),
02948 "Could not delete temporary columns");
02949
02950 if (sigmaY != NULL)
02951 {
02952 check( cpl_table_erase_column(t, "_sY_double"),
02953 "Could not delete temporary column");
02954 }
02955
02956 cleanup:
02957 uves_unwrap_bivector_vectors(&vx);
02958 uves_unwrap_vector(&vx1);
02959 uves_unwrap_vector(&vx2);
02960 uves_unwrap_vector(&vy);
02961 uves_unwrap_vector(&vsy);
02962
02963 if (variance != NULL)
02964 {
02965 *variance = variance_local;
02966 }
02967 else
02968 {
02969 uves_polynomial_delete(&variance_local);
02970 }
02971 if (cpl_error_get_code() != CPL_ERROR_NONE)
02972 {
02973 uves_polynomial_delete(&p);
02974 }
02975
02976 return p;
02977 }
02978
02979
03022
03023
03024 polynomial *
03025 uves_polynomial_regression_2d_autodegree(cpl_table *t,
03026 const char *X1, const char *X2, const char *Y,
03027 const char *sigmaY,
03028 const char *polynomial_fit,
03029 const char *residual_square,
03030 const char *variance_fit,
03031 double *mean_squared_error, double *red_chisq,
03032 polynomial **variance, double kappa,
03033 int maxdeg1, int maxdeg2, double min_rms,
03034 double min_reject,
03035 bool verbose,
03036 const double *min_val,
03037 const double *max_val,
03038 int npos, double positions[][2])
03039 {
03040 int deg1 = 0;
03041 int deg2 = 0;
03042 int i;
03043
03044 double **mse = NULL;
03045 bool adjust1 = true;
03046 bool adjust2 = true;
03047 bool finished = false;
03048
03049 const char *y_unit;
03050 cpl_table *temp = NULL;
03051 polynomial *bivariate_fit = NULL;
03052
03053 assure( (min_val == NULL && max_val == NULL) || positions != NULL,
03054 CPL_ERROR_NULL_INPUT,
03055 "Missing positions array");
03056
03057 check_nomsg( y_unit = cpl_table_get_column_unit(t, Y));
03058 if (y_unit == NULL)
03059 {
03060 y_unit = "";
03061 }
03062
03063 assure(maxdeg1 >= 1 && maxdeg2 >= 1, CPL_ERROR_ILLEGAL_INPUT,
03064 "Illegal max. degrees: (%d, %d)",
03065 maxdeg1, maxdeg2);
03066
03067 mse = cpl_calloc(maxdeg1+1, sizeof(double *));
03068 assure_mem(mse);
03069 for (i = 0; i < maxdeg1+1; i++)
03070 {
03071 int j;
03072 mse[i] = cpl_calloc(maxdeg2+1, sizeof(double));
03073 assure_mem(mse);
03074
03075 for (j = 0; j < maxdeg2+1; j++)
03076 {
03077 mse[i][j] = -1;
03078 }
03079 }
03080
03081 temp = cpl_table_duplicate(t);
03082 assure_mem(temp);
03083
03084 uves_polynomial_delete(&bivariate_fit);
03085 check( bivariate_fit = uves_polynomial_regression_2d(temp,
03086 X1, X2, Y, sigmaY,
03087 deg1,
03088 deg2,
03089 NULL, NULL, NULL,
03090 &mse[deg1][deg2], NULL,
03091 NULL,
03092 kappa, min_reject),
03093 "Error fitting polynomial");
03094 if (verbose)
03095 uves_msg_low("(%d, %d)-degree: RMS = %.3g %s (%d/%d outliers)",
03096 deg1, deg2, sqrt(mse[deg1][deg2]), y_unit,
03097 cpl_table_get_nrow(t) - cpl_table_get_nrow(temp),
03098 cpl_table_get_nrow(t));
03099 else
03100 uves_msg_debug("(%d, %d)-degree: RMS = %.3g %s (%d/%d outliers)",
03101 deg1, deg2, sqrt(mse[deg1][deg2]), y_unit,
03102 cpl_table_get_nrow(t) - cpl_table_get_nrow(temp),
03103 cpl_table_get_nrow(t));
03104
03105
03106 do
03107 {
03108 int new_deg1, new_deg2;
03109 double m;
03110
03111 finished = true;
03112
03113 adjust1 = adjust1 && (deg1 + 2 <= maxdeg1);
03114 adjust2 = adjust2 && (deg2 + 2 <= maxdeg2);
03115
03116
03117
03118
03119
03120
03121
03122
03123
03124
03125
03126
03127
03128
03129
03130 for (new_deg1 = deg1; new_deg1 <= deg1+2; new_deg1++)
03131 for (new_deg2 = deg2; new_deg2 <= deg2+2; new_deg2++)
03132 if ( (
03133 (new_deg1 == deg1+1 && new_deg2 == deg2 && adjust1) ||
03134 (new_deg1 == deg1+2 && new_deg2 == deg2 && adjust1) ||
03135 (new_deg1 == deg1 && new_deg2 == deg2+1 && adjust2) ||
03136 (new_deg1 == deg1 && new_deg2 == deg2+2 && adjust2) ||
03137 (new_deg1 == deg1+1 && new_deg2 == deg2+1 && adjust1 && adjust2)
03138 )
03139 && mse[new_deg1][new_deg2] < 0)
03140 {
03141 int rejected = 0;
03142
03143 uves_free_table(&temp);
03144 temp = cpl_table_duplicate(t);
03145 assure_mem(temp);
03146
03147 uves_polynomial_delete(&bivariate_fit);
03148 bivariate_fit = uves_polynomial_regression_2d(temp,
03149 X1, X2, Y, sigmaY,
03150 new_deg1,
03151 new_deg2,
03152 NULL, NULL, NULL,
03153 &(mse[new_deg1]
03154 [new_deg2]),
03155 NULL,
03156 NULL,
03157 kappa, min_reject);
03158
03159 if (cpl_error_get_code() == CPL_ERROR_SINGULAR_MATRIX)
03160 {
03161 uves_error_reset();
03162
03163 if (verbose)
03164 uves_msg_low("(%d, %d)-degree: Singular matrix",
03165 new_deg1, new_deg2);
03166 else
03167 uves_msg_debug("(%d, %d)-degree: Singular matrix",
03168 new_deg1, new_deg2);
03169
03170 mse[new_deg1][new_deg2] = DBL_MAX/2;
03171 }
03172 else
03173 {
03174 assure( cpl_error_get_code() == CPL_ERROR_NONE,
03175 cpl_error_get_code(),
03176 "Error fitting (%d, %d)-degree polynomial",
03177 new_deg1, new_deg2 );
03178
03179 rejected = cpl_table_get_nrow(t) - cpl_table_get_nrow(temp);
03180
03181 if (verbose)
03182 uves_msg_low("(%d, %d)-degree: RMS = %.3g %s (%d/%d outliers)",
03183 new_deg1, new_deg2, sqrt(mse[new_deg1][new_deg2]), y_unit,
03184 rejected, cpl_table_get_nrow(t));
03185 else
03186 uves_msg_debug("(%d, %d)-degree: RMS = %.3g %s (%d/%d outliers)",
03187 new_deg1, new_deg2, sqrt(mse[new_deg1][new_deg2]), y_unit,
03188 rejected, cpl_table_get_nrow(t));
03189
03190
03191 if (min_val != NULL || max_val != NULL)
03192 {
03193 for (i = 0; i < npos; i++)
03194 {
03195 double val = uves_polynomial_evaluate_2d(
03196 bivariate_fit,
03197 positions[i][0], positions[i][1]);
03198 if (min_val != NULL && val < *min_val)
03199 {
03200 uves_msg_debug("Bad fit: %f < %f",
03201 val,
03202 *min_val);
03203 mse[new_deg1][new_deg2] = DBL_MAX/2;
03204
03205 }
03206 if (max_val != NULL && val > *max_val)
03207 {
03208 uves_msg_debug("Bad fit: %f > %f",
03209 val,
03210 *max_val);
03211 mse[new_deg1][new_deg2] = DBL_MAX/2;
03212 }
03213 }
03214 }
03215
03216
03217
03218
03219 if (rejected >= (4*cpl_table_get_nrow(t))/5)
03220 {
03221 mse[new_deg1][new_deg2] = DBL_MAX/2;
03222 }
03223
03224 }
03225 }
03226
03227
03228
03229
03230
03231
03232
03233
03234
03235 m = mse[deg1][deg2];
03236
03237 if (adjust1
03238 && (m - mse[deg1+1][deg2])/m > 0.1
03239 && (!adjust2 || mse[deg1+1][deg2] <= mse[deg1][deg2+1])
03240
03241
03242
03243
03244
03245 )
03246 {
03247 deg1++;
03248 finished = false;
03249 }
03250 else if (adjust2 &&
03251 (m - mse[deg1][deg2+1])/m > 0.1
03252 && (!adjust1 || mse[deg1+1][deg2] > mse[deg1][deg2+1])
03253 )
03254 {
03255 deg2++;
03256 finished = false;
03257 }
03258 else if (adjust1 && adjust2 && (m - mse[deg1+1][deg2+1])/m > 0.1)
03259 {
03260 deg1++;
03261 deg2++;
03262 finished = false;
03263 }
03264 else if (adjust1
03265 && (m - mse[deg1+2][deg2])/m > 0.1
03266 && (!adjust2 || mse[deg1+2][deg2] <= mse[deg1][deg2+2])
03267 )
03268 {
03269 deg1 += 2;
03270 finished = false;
03271 }
03272 else if (adjust2
03273 && (m - mse[deg1][deg2+2])/m > 0.1
03274 && (!adjust1 || mse[deg1+2][deg2] < mse[deg1][deg2+2]))
03275 {
03276 deg2 += 2;
03277 finished = false;
03278 }
03279
03280
03281 finished = finished || (sqrt(mse[deg1][deg2]) < min_rms);
03282
03283 } while (!finished);
03284
03285 uves_polynomial_delete(&bivariate_fit);
03286 check( bivariate_fit = uves_polynomial_regression_2d(t,
03287 X1, X2, Y, sigmaY,
03288 deg1,
03289 deg2,
03290 polynomial_fit, residual_square,
03291 variance_fit,
03292 mean_squared_error, red_chisq,
03293 variance, kappa, min_reject),
03294 "Error fitting (%d, %d)-degree polynomial", deg1, deg2);
03295
03296 if (verbose)
03297 uves_msg_low("Using degree (%d, %d), RMS = %.3g %s", deg1, deg2,
03298 sqrt(mse[deg1][deg2]), y_unit);
03299 else
03300 uves_msg_debug("Using degree (%d, %d), RMS = %.3g %s", deg1, deg2,
03301 sqrt(mse[deg1][deg2]), y_unit);
03302
03303 cleanup:
03304 if (mse != NULL)
03305 {
03306 for (i = 0; i < maxdeg1+1; i++)
03307 {
03308 if (mse[i] != NULL)
03309 {
03310 cpl_free(mse[i]);
03311 }
03312 }
03313 cpl_free(mse);
03314 }
03315 uves_free_table(&temp);
03316
03317 return bivariate_fit;
03318 }
03319
03320
03330
03331 const char *
03332 uves_remove_string_prefix(const char *s, const char *prefix)
03333 {
03334 const char *result = NULL;
03335 unsigned int prefix_length;
03336
03337 assure( s != NULL, CPL_ERROR_NULL_INPUT, "Null string");
03338 assure( prefix != NULL, CPL_ERROR_NULL_INPUT, "Null string");
03339
03340 prefix_length = strlen(prefix);
03341
03342 assure( strlen(s) >= prefix_length &&
03343 strncmp(s, prefix, prefix_length) == 0,
03344 CPL_ERROR_INCOMPATIBLE_INPUT, "'%s' is not a prefix of '%s'",
03345 prefix, s);
03346
03347 result = s + prefix_length;
03348
03349 cleanup:
03350 return result;
03351 }
03352
03353
03354
03363
03364
03365 double uves_gaussrand(void)
03366 {
03367 static double V1, V2, S;
03368 static int phase = 0;
03369 double X;
03370
03371 if(phase == 0) {
03372 do {
03373 double U1 = (double)rand() / RAND_MAX;
03374 double U2 = (double)rand() / RAND_MAX;
03375
03376 V1 = 2 * U1 - 1;
03377 V2 = 2 * U2 - 1;
03378 S = V1 * V1 + V2 * V2;
03379 } while(S >= 1 || S == 0);
03380
03381 X = V1 * sqrt(-2 * log(S) / S);
03382 } else
03383 X = V2 * sqrt(-2 * log(S) / S);
03384
03385 phase = 1 - phase;
03386
03387 return X;
03388 }
03389
03390
03401
03402
03403 double uves_spline_hermite_table( double xp, const cpl_table *t, const char *column_x,
03404 const char *column_y, int *istart )
03405 {
03406 double result = 0;
03407 int n;
03408
03409 const double *x, *y;
03410
03411 check( x = cpl_table_get_data_double_const(t, column_x),
03412 "Error reading column '%s'", column_x);
03413 check( y = cpl_table_get_data_double_const(t, column_y),
03414 "Error reading column '%s'", column_y);
03415
03416 n = cpl_table_get_nrow(t);
03417
03418 result = uves_spline_hermite(xp, x, y, n, istart);
03419
03420 cleanup:
03421 return result;
03422 }
03423
03424
03440
03441 double uves_spline_hermite( double xp, const double *x, const double *y, int n, int *istart )
03442 {
03443 double yp1, yp2, yp = 0;
03444 double xpi, xpi1, l1, l2, lp1, lp2;
03445 int i;
03446
03447 if ( x[0] <= x[n-1] && (xp < x[0] || xp > x[n-1]) ) return 0.0;
03448 if ( x[0] > x[n-1] && (xp > x[0] || xp < x[n-1]) ) return 0.0;
03449
03450 if ( x[0] <= x[n-1] )
03451 {
03452 for ( i = (*istart)+1; i <= n && xp >= x[i-1]; i++ )
03453 ;
03454 }
03455 else
03456 {
03457 for ( i = (*istart)+1; i <= n && xp <= x[i-1]; i++ )
03458 ;
03459 }
03460
03461 *istart = i;
03462 i--;
03463
03464 lp1 = 1.0 / (x[i-1] - x[i]);
03465 lp2 = -lp1;
03466
03467 if ( i == 1 )
03468 {
03469 yp1 = (y[1] - y[0]) / (x[1] - x[0]);
03470 }
03471 else
03472 {
03473 yp1 = (y[i] - y[i-2]) / (x[i] - x[i-2]);
03474 }
03475
03476 if ( i >= n - 1 )
03477 {
03478 yp2 = (y[n-1] - y[n-2]) / (x[n-1] - x[n-2]);
03479 }
03480 else
03481 {
03482 yp2 = (y[i+1] - y[i-1]) / (x[i+1] - x[i-1]);
03483 }
03484
03485 xpi1 = xp - x[i];
03486 xpi = xp - x[i-1];
03487 l1 = xpi1*lp1;
03488 l2 = xpi*lp2;
03489
03490 yp = y[i-1]*(1 - 2.0*lp1*xpi)*l1*l1 +
03491 y[i]*(1 - 2.0*lp2*xpi1)*l2*l2 +
03492 yp1*xpi*l1*l1 + yp2*xpi1*l2*l2;
03493
03494 return yp;
03495 }
03496
03497
03511
03512
03513 double uves_spline_cubic( double xp, double *x, float *y, float *y2, int n, int *kstart )
03514 {
03515 int klo, khi, k;
03516 double a, b, h, yp = 0;
03517
03518 assure_nomsg( x != NULL, CPL_ERROR_NULL_INPUT);
03519 assure_nomsg( y != NULL, CPL_ERROR_NULL_INPUT);
03520 assure_nomsg( y2 != NULL, CPL_ERROR_NULL_INPUT);
03521 assure_nomsg( kstart != NULL, CPL_ERROR_NULL_INPUT);
03522
03523 klo = *kstart;
03524 khi = n;
03525
03526 if ( xp < x[1] || xp > x[n] )
03527 {
03528 return 0.0;
03529 }
03530 else if ( xp == x[1] )
03531 {
03532 return(y[1]);
03533 }
03534
03535 for ( k = klo; k < n && xp > x[k]; k++ )
03536 ;
03537
03538 klo = *kstart = k-1;
03539 khi = k;
03540
03541 h = x[khi] - x[klo];
03542 assure( h != 0.0, CPL_ERROR_DIVISION_BY_ZERO,
03543 "Empty x-value range: xlo = %e ; xhi = %e", x[khi], x[klo]);
03544
03545 a = (x[khi] - xp) / h;
03546 b = (xp - x[klo]) / h;
03547
03548 yp = a*y[klo] + b*y[khi] + ((a*a*a - a)*y2[klo] + (b*b*b - b)*y2[khi])*
03549 (h*h) / 6.0;
03550
03551 cleanup:
03552 return yp;
03553 }
03554
03555
03565
03566 bool
03567 uves_table_is_sorted_double(const cpl_table *t, const char *column, const bool reverse)
03568 {
03569 bool is_sorted = true;
03570 int i;
03571 int N;
03572 double previous, current;
03573
03574 passure(t != NULL, " ");
03575 passure(cpl_table_has_column(t, column), "No column '%s'", column);
03576 passure(cpl_table_get_column_type(t, column) == CPL_TYPE_DOUBLE, " ");
03577
03578 N = cpl_table_get_nrow(t);
03579
03580 if (N > 1)
03581 {
03582 previous = cpl_table_get_double(t, column, 0, NULL);
03583
03584 for(i = 1; i < N && is_sorted; i++)
03585 {
03586 current = cpl_table_get_double(t, column, i, NULL);
03587 if (!reverse)
03588 {
03589
03590 is_sorted = is_sorted && ( current >= previous );
03591 }
03592 else
03593 {
03594
03595 is_sorted = is_sorted && ( current <= previous );
03596 }
03597
03598 previous = current;
03599 }
03600 }
03601 else
03602 {
03603
03604 }
03605
03606 cleanup:
03607 return is_sorted;
03608 }
03609
03610
03616
03617 cpl_table *
03618 uves_ordertable_traces_new(void)
03619 {
03620 cpl_table *result = NULL;
03621
03622 check((
03623 result = cpl_table_new(0),
03624 cpl_table_new_column(result, "TraceID" , CPL_TYPE_INT),
03625 cpl_table_new_column(result, "Offset" , CPL_TYPE_DOUBLE),
03626 cpl_table_new_column(result, "Tracemask", CPL_TYPE_INT)),
03627 "Error creating table");
03628
03629 cleanup:
03630 return result;
03631 }
03632
03633
03643
03644 cpl_error_code
03645 uves_ordertable_traces_add(cpl_table *traces,
03646 int fibre_ID, double fibre_offset, int fibre_mask)
03647 {
03648 int size;
03649
03650 assure( traces != NULL, CPL_ERROR_NULL_INPUT, "Null table!");
03651
03652
03653 check((
03654 size = cpl_table_get_nrow(traces),
03655 cpl_table_set_size (traces, size+1),
03656 cpl_table_set_int (traces, "TraceID" , size, fibre_ID),
03657 cpl_table_set_double(traces, "Offset" , size, fibre_offset),
03658 cpl_table_set_int (traces, "Tracemask", size, fibre_mask)),
03659 "Error updating table");
03660
03661 cleanup:
03662 return cpl_error_get_code();
03663 }
03664
03665
03666
03667
03668
03669
03670
03671
03672
03673
03674
03675
03676
03677
03678
03679
03680
03681
03682
03683
03684
03685
03686
03697 static void fmoffa_i(float x,const double a[],double *y,double dyda[])
03698
03699
03700
03701 {
03702 double fac=0, fac2=0, fac4= 0, fac4i=0, arg=0, arg2=0;
03703 double a2i=0, m = 0, p = 0, dif =0;
03704 double sqrt5 = 2.23606797749979;
03705
03706 *y=0.0;
03707
03708 a2i = 1.0/(a[2]*sqrt5);
03709
03710 dif=x-a[1];
03711 arg=dif*a2i;
03712 arg2=arg*arg;
03713
03714 fac=1.0+arg2;
03715 fac2=fac*fac;
03716 fac4=fac2*fac2;
03717 fac4i = 1.0/fac4;
03718
03719
03720 m = a[3]*fac4i * a2i*16/(5.0*M_PI);
03721 *y = m + a[4]*(1.0+dif*a[5]);
03722 p = 8.0*m/fac*arg*a2i;
03723
03724 dyda[3] = m/a[3];
03725 dyda[2] = p*dif/a[2] - m/a[2];
03726
03727
03728 dyda[1]=p-a[4]*a[5];
03729
03730 dyda[4]=1.0+dif*a[5];
03731 dyda[5]=a[4]*dif;
03732
03733
03734 #if 0
03735 {
03736 int i = 0, npar=5 ;
03737 printf("fmoffat_i \n");
03738 for (i = 1;i<=npar;i++) printf("a[%1i] %f :\n",i,a[i]);
03739
03740 printf("fmoffat_i ");
03741 for (i = 1;i<=npar;i++) printf("%i %f :",i,dyda[i]);
03742 printf("\n");
03743 }
03744 #endif
03745
03746 }
03747
03766 static void fmoffa_c(float x,const double a[],double *y,double dyda[])
03767
03768
03769
03770
03771
03772 {
03773 int npoint = 3;
03774 double const xgl[3] = {-0.387298334621,0.,0.387298334621};
03775 double const wgl[3] = {.2777777777778,0.444444444444,0.2777777777778};
03776 int i=0;
03777 int j=0;
03778 int npar = 5;
03779 double xmod = 0;
03780 double dydapar[5];
03781 double ypar;
03782
03783
03784
03785 a = C_TO_FORTRAN_INDEXING(a);
03786 dyda = C_TO_FORTRAN_INDEXING(dyda);
03787
03788 *y = 0.0;
03789 for (i = 1;i<=npar;i++) dyda[i] = 0.;
03790
03791
03792
03793
03794 for (j=0; j < npoint; j++)
03795 {
03796 xmod = x+xgl[j];
03797
03798 fmoffa_i(xmod,a,&ypar,&dydapar[-1]);
03799
03800 *y = *y + ypar*wgl[j];
03801
03802 for (i = 1; i <= npar; i++)
03803 {
03804 dyda[i] = dyda[i] + dydapar[i-1]*wgl[j] ;
03805 }
03806
03807
03808
03809
03810
03811
03812
03813 }
03814
03815 #if 0
03816 printf("fmoffat_c ");
03817 for (i = 1;i<=npar;i++) printf("%i %f %f: \n",i,a[i],dyda[i]);
03818 printf("\n");
03819 #endif
03820 }
03821
03822
03830
03831 int
03832 uves_moffat(const double x[], const double a[], double *result)
03833 {
03834 double dyda[5];
03835
03836 fmoffa_c(x[0], a, result, dyda);
03837
03838 return 0;
03839 }
03840
03841
03849
03850 int
03851 uves_moffat_derivative(const double x[], const double a[], double result[])
03852 {
03853 double y;
03854
03855 fmoffa_c(x[0], a, &y, result);
03856
03857 return 0;
03858 }
03859
03860
03880
03881
03882 int
03883 uves_gauss(const double x[], const double a[], double *result)
03884 {
03885 double my = a[0];
03886 double sigma = a[1];
03887
03888 if (sigma == 0)
03889 {
03890
03891 if (x[0] == my)
03892 {
03893 *result = DBL_MAX;
03894 }
03895 else
03896 {
03897 *result = 0;
03898 }
03899 return 0;
03900 }
03901 else
03902 {
03903 double A = a[2];
03904 double B = a[3];
03905
03906 *result = B +
03907 A/(sqrt(2*M_PI*sigma*sigma)) *
03908 exp(- (x[0] - my)*(x[0] - my)
03909 / (2*sigma*sigma));
03910 }
03911
03912 return 0;
03913 }
03914
03915
03935
03936
03937 int
03938 uves_gauss_derivative(const double x[], const double a[], double result[])
03939 {
03940 double my = a[0];
03941 double sigma = a[1];
03942 double A = a[2];
03943
03944
03945 double factor;
03946
03947
03948
03949
03950
03951
03952
03953
03954
03955
03956
03957
03958 if (sigma == 0)
03959 {
03960
03961 result[0] = 0;
03962 result[1] = 0;
03963 result[2] = 0;
03964 result[3] = 0;
03965 return 0;
03966 }
03967
03968 factor = exp( -(x[0] - my)*(x[0] - my)/(2*sigma*sigma) )
03969 / (sqrt(2*M_PI*sigma*sigma));
03970
03971 result[0] = A * factor * (x[0]-my) / (sigma*sigma);
03972 result[1] = A * factor * ((x[0]-my)*(x[0]-my) / (sigma*sigma) - 1) / sigma;
03973 result[2] = factor;
03974 result[3] = 1;
03975
03976 return 0;
03977 }
03978
03979
04000
04001
04002 int
04003 uves_gauss_linear(const double x[], const double a[], double *result)
04004 {
04005 double my = a[0];
04006 double sigma = a[1];
04007
04008 if (sigma == 0)
04009 {
04010
04011 if (x[0] == my)
04012 {
04013 *result = DBL_MAX;
04014 }
04015 else
04016 {
04017 *result = 0;
04018 }
04019 return 0;
04020 }
04021 else
04022 {
04023 double A = a[2];
04024 double B = a[3];
04025 double C = a[4];
04026
04027 *result = B + C*(x[0] - my) +
04028 A/(sqrt(2*M_PI*sigma*sigma)) *
04029 exp(- (x[0] - my)*(x[0] - my)
04030 / (2*sigma*sigma));
04031 }
04032
04033 return 0;
04034 }
04035
04036
04059
04060
04061 int
04062 uves_gauss_linear_derivative(const double x[], const double a[], double result[])
04063 {
04064 double my = a[0];
04065 double sigma = a[1];
04066 double A = a[2];
04067
04068 double C = a[4];
04069
04070 double factor;
04071
04072
04073
04074
04075
04076
04077
04078
04079
04080
04081
04082
04083
04084
04085 if (sigma == 0)
04086 {
04087
04088 result[0] = -C;
04089 result[1] = 0;
04090 result[2] = 0;
04091 result[3] = 0;
04092 result[4] = x[0];
04093 return 0;
04094 }
04095
04096 factor = exp( -(x[0] - my)*(x[0] - my)/(2*sigma*sigma) )
04097 / (sqrt(2*M_PI*sigma*sigma));
04098
04099 result[0] = A * factor * (x[0]-my) / (sigma*sigma);
04100 result[1] = A * factor * ((x[0]-my)*(x[0]-my) / (sigma*sigma) - 1) / sigma;
04101 result[2] = factor;
04102 result[3] = 1;
04103 result[4] = x[0] - my;
04104
04105 return 0;
04106 }
04107
04108
04109
04110
04111
04124
04125 cpl_image *
04126 uves_create_image(uves_iterate_position *pos, enum uves_chip chip,
04127 const cpl_image *spectrum, const cpl_image *sky,
04128 const cpl_image *cosmic_image,
04129 const uves_extract_profile *profile,
04130 cpl_image **image_noise, uves_propertylist **image_header)
04131 {
04132 cpl_image *image = NULL;
04133
04134 cpl_binary *bpm = NULL;
04135 bool loop_y = false;
04136
04137 double ron = 3;
04138 double gain = 1.0;
04139 bool new_format = true;
04140
04141 image = cpl_image_new(pos->nx, pos->ny, CPL_TYPE_DOUBLE);
04142 assure_mem( image );
04143 if (image_noise != NULL) {
04144 *image_noise = cpl_image_new(pos->nx, pos->ny, CPL_TYPE_DOUBLE);
04145 assure_mem( *image_noise );
04146 cpl_image_add_scalar(*image_noise, 0.01);
04147 }
04148
04149 if (image_header != NULL) {
04150 *image_header = uves_propertylist_new();
04151
04152 uves_propertylist_append_double(*image_header, UVES_MJDOBS, 60000);
04153 uves_propertylist_append_double(*image_header, UVES_RON(new_format, chip), ron);
04154 uves_propertylist_append_double(*image_header, UVES_GAIN(new_format, chip), gain);
04155 }
04156
04157 for (uves_iterate_set_first(pos,
04158 1, pos->nx,
04159 pos->minorder, pos->maxorder,
04160 bpm,
04161 loop_y);
04162 !uves_iterate_finished(pos);
04163 uves_iterate_increment(pos)) {
04164
04165
04166 uves_extract_profile_set(profile, pos, NULL);
04167 for (pos->y = pos->ylow; pos->y <= pos->yhigh; pos->y++) {
04168
04169
04170 double flux, sky_flux;
04171 int bad;
04172 int spectrum_row = pos->order - pos->minorder + 1;
04173 double noise;
04174 double prof = uves_extract_profile_evaluate(profile, pos);
04175
04176 if (sky != NULL)
04177 {
04178 sky_flux = cpl_image_get(sky, pos->x, spectrum_row, &bad)/pos->sg.length;
04179 }
04180 else
04181 {
04182 sky_flux = 0;
04183 }
04184
04185 flux = cpl_image_get(spectrum, pos->x, spectrum_row, &bad) * prof + sky_flux;
04186
04187
04188 noise = sqrt(gain)*sqrt(ron*ron/(gain*gain) + sky_flux/gain + flux/gain);
04189
04190 cpl_image_set(image, pos->x, pos->y,
04191 flux);
04192 if (image_noise != NULL) cpl_image_set(*image_noise, pos->x, pos->y, noise);
04193
04194 }
04195 }
04196
04197 if (cosmic_image != NULL) {
04198 double cr_val = 2*cpl_image_get_max(image);
04199
04200
04201 loop_y = true;
04202
04203 for (uves_iterate_set_first(pos,
04204 1, pos->nx,
04205 pos->minorder, pos->maxorder,
04206 bpm,
04207 loop_y);
04208 !uves_iterate_finished(pos);
04209 uves_iterate_increment(pos)) {
04210
04211 int is_rejected;
04212 if (cpl_image_get(cosmic_image, pos->x, pos->y, &is_rejected) > 0) {
04213 cpl_image_set(image, pos->x, pos->y, cr_val);
04214 }
04215 }
04216 }
04217
04218 cleanup:
04219 return image;
04220 }
04221
04222 void
04223 uves_frameset_dump(cpl_frameset* set)
04224 {
04225
04226 cpl_frame* frm=NULL;
04227 int sz=0;
04228 int i=0;
04229
04230 cknull(set,"Null input frameset");
04231 check_nomsg(sz=cpl_frameset_get_size(set));
04232 check_nomsg(frm=cpl_frameset_get_first(set));
04233 do{
04234 uves_msg("frame %d tag %s filename %s group %d",
04235 i,
04236 cpl_frame_get_tag(frm),
04237 cpl_frame_get_filename(frm),
04238 cpl_frame_get_group(frm));
04239 i++;
04240 } while ((frm=cpl_frameset_get_next(set)) != NULL);
04241
04242 cleanup:
04243
04244 return ;
04245 }
04246