SINFONI Pipeline Reference Manual  2.6.0
sinfo_new_psf.c
1 /*
2  * This file is part of the ESO SINFONI Pipeline
3  * Copyright (C) 2004,2005 European Southern Observatory
4  *
5  * This program 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  File name : sinfo_new_psf.c
22  Author : A. Modigliani
23  Created on : Sep 17, 2003
24  Description :
25 
26  sinfo_new_psf.py does the image reconstruction of a set of
27  sky-subtracted, flatfielded,
28  bad pixel corrected and slope of the spectra aligned exposures of a bright
29  star with continuum spectrum. The resulting image can be used to determine
30  the PSF
31  ---------------------------------------------------------------------------*/
32 #ifdef HAVE_CONFIG_H
33 # include <config.h>
34 #endif
35 
36 /*----------------------------------------------------------------------------
37  Includes
38  ---------------------------------------------------------------------------*/
39 #define _GNU_SOURCE
40 #include <math.h>
41 
42 #include <sinfo_cpl_size.h>
43 
44 #include <irplib_utils.h>
45 #include <irplib_strehl.h>
46 #include "sinfo_new_psf.h"
47 #include "sinfo_pro_save.h"
48 #include "sinfo_hidden.h"
49 #include "sinfo_key_names.h"
50 #include "sinfo_psf_ini.h"
51 #include "sinfo_psf_ini_by_cpl.h"
52 #include "sinfo_utilities_scired.h"
53 #include "sinfo_hidden.h"
54 #include "sinfo_pfits.h"
55 #include "sinfo_functions.h"
56 #include "sinfo_error.h"
57 #include "sinfo_utils_wrappers.h"
58 #include "sinfo_globals.h"
59 //Used only for cpl_propertylist_has
60 #include "sinfo_dfs.h"
61 /*----------------------------------------------------------------------------
62  Defines
63  ---------------------------------------------------------------------------*/
64 //PSO
65 #define SINFO_MATH_PI 3.1415926535897932384626433832795028841971693993751058
66 #define SINFO_MATH_PI_2 1.5707963267948966192313216916397514420985846996875529
67 #define SINFO_MATH_PI_4 0.7853981633974483096156608458198757210492923498437765
68 
69 
70 
71 #define SINFO_STREHL_M1 8.0 //7.9
72 #define SINFO_STREHL_M2 1.1 //1.33
73 #define SINFO_STREHL_BOX_SIZE 64
74 #define SINFO_STREHL_WINDOW 6
75 #define SINFO_PSF_SZ 4
76 #define SINFO_RSTAR 32//25
77 #define SINFO_BKG_R1 32//25
78 #define SINFO_BKG_R2 33//27
79 #define SINFO_STREHL_ERROR_COEFFICIENT SINFO_MATH_PI * 0.007 / 0.0271
80 #ifndef SINFO_STREHL_RAD_CENTRAL
81 #define SINFO_STREHL_RAD_CENTRAL 5
82 #endif
83 
84 //constants for perfect PSF generation
85 // Dimension of the support for generating the perfect PFS
86 #define SINFO_PSF_DIM 1024//256
87 #define SINFO_PSF_BLOCKS 63//11
88 
89 #define SINFO_PSF_BIN 16 // Pixels over "pixel_size"
90 #define SINFO_PSF_NPOINT 10000// number of encircled energy sampling points
91 #define SINFO_BKG_BOX_SZ 8
92 /*----------------------------------------------------------------------------
93  Function Definitions
94  ---------------------------------------------------------------------------*/
95 static cpl_error_code
96 sinfo_add_com_psf_qclog(const char* fname,cpl_table** qclog_tbl);
97 
98 
99 static cpl_error_code
100 sinfo_get_star_features(const cpl_image* im,
101  const int radius,
102  const int xpos,
103  const int ypos,
104  double* xc,
105  double* yc,
106  double* pick,
107  double* flux,
108  double* bkg);
109 
110 static double
111 sinfo_find_min_of_four(const double n1,
112  const double n2,
113  const double n3,
114  const double n4);
115 
116 static cpl_table*
117 sinfo_get_strehl_from_2images(cpl_image* ima1,
118  cpl_image* ima2,
119  cpl_frame* frm1,
120  cpl_frame* frm2);
121 
122 
123 static int
124 sinfo_get_strehl_input1(cpl_frame* frm1,
125  double* dispersion,
126  double* centralWave,
127  double* ws,
128  double* we,
129  double* pscale,
130  double* exptime,
131  double* strehl_star_rad,
132  double* strehl_bg_rmin,
133  double* strehl_bg_rmax);
134 
135 static int
136 sinfo_get_strehl_input2(cpl_frame* frm1,cpl_frame* frm2,
137  double* dispersion,
138  double* centralWave,
139  double* ws,
140  double* we,
141  double* pscale1,
142  double* pscale2,
143  double* exptime1,
144  double* exptime2,
145  double* strehl_star_rad1,
146  double* strehl_star_rad2,
147  double* strehl_bg_rmin1,
148  double* strehl_bg_rmin2,
149  double* strehl_bg_rmax1,
150  double* strehl_bg_rmax2);
151 
152 
153 static void
154 sinfo_check_borders(cpl_size* val,const int max,const int thresh);
155 
156 static void
157 sinfo_get_safe_box(int* llx,
158  int* lly,
159  int* urx,
160  int* ury,
161  const int xpos,
162  const int ypos,
163  const int box,
164  const int szx,
165  const int szy);
166 
167 static int
168 sinfo_get_strehl_from_slice(cpl_imagelist* cube,
169  double disp,
170  double cWave,
171  double ws,
172  double we,
173  double pscale,
174  double strehl_star_radius,
175  double strehl_bg_r1,
176  double strehl_bg_r2,
177  double* strehl,
178  double* strehl_err);
179 
180 
181 static cpl_table*
182 sinfo_get_encircled_energy(cpl_frameset* sof,
183  cpl_image* img,
184  double* fwhm_x,
185  double* fwhm_y,
186  cpl_table** qclog);
187 
188 static double
189 sinfo_get_strehl_from_ima(cpl_image* ima,
190  cpl_frame* frame);
191 
192 static int
193 sinfo_get_strehl_from_image(cpl_image* img,
194  double ws,
195  double we,
196  double pscale,
197  double strehl_star_radius,
198  double strehl_bg_r1,
199  double strehl_bg_r2,
200  double* strehl,
201  double* strehl_err);
202 
203 
204 
205 static cpl_table*
206 sinfo_get_strehl_from_cube(cpl_imagelist* cube,
207  char* name,
208  cpl_frame* frame);
209 
210 static int
211 sinfo_get_frm12(cpl_frameset* sof,cpl_frame** frm1,cpl_frame** frm2);
212 
213 
222 /*----------------------------------------------------------------------------
223  Function : sinfo_new_psf()
224  In : ini_file: file name of according .ini file
225  Out : integer (0 if it worked, -1 if it doesn't)
226  Job :
227 
228  sinfo_new_psf.py does the image reconstruction of a set of sky-subtracted,
229  flatfielded,
230  bad pixel corrected and slope of the spectra aligned exposures of a bright
231  star with continuum spectrum. The resulting image can be used to determine
232  the PSF
233 
234  ---------------------------------------------------------------------------*/
235 
236 int
237 sinfo_new_psf (const char* plugin_id,
238  cpl_parameterlist* config,
239  cpl_frameset* sof, cpl_frameset* ref_set)
240 {
241 
242  cpl_imagelist* cube1=NULL;
243  cpl_imagelist* cube2=NULL;
244  cpl_image * med_img1=NULL ;
245  cpl_image * med_img2=NULL ;
246 
247  cpl_table* ao_performance=NULL;
248  cpl_table* enc_energy=NULL;
249 
250  cpl_frame* frm1=NULL;
251  cpl_frame* frm2=NULL;
252 
253  cpl_table* qclog_tbl=NULL;
254  cpl_frameset* stk=NULL;
255  cpl_propertylist* plist =NULL;
256 
257  psf_config * cfg =NULL;
258 
259  int nsample=0;
260  int i = 0;
261  int status=0;
262 
263 
264 
265  int strehl_sw=0;
266  int ilx1=0;
267  int ily1=0;
268  /*
269  int ilx2=0;
270  int ily2=0;
271  */
272  float cx1=0;
273  float cy1=0;
274  /*
275  float cx2=0;
276  float cy2=0;
277  */
278 
279  double fwhm_x=0;
280  double fwhm_y=0;
281  double lam=0;
282  double strehl=0;
283  double strehl1=0;
284  double strehl2=0;
285 
286  char fname1[MAX_NAME_SIZE];
287  char fname2[MAX_NAME_SIZE];
288 
289  char key_name[MAX_NAME_SIZE];
290 
291  char obs_name1[MAX_NAME_SIZE];
292  char hlamp_st='F';
293  char shut2_st='F';
294  cpl_table* tmp_tbl=NULL;
295 
296 
297  /*
298  -----------------------------------------------------------------
299  1) parse the file names and parameters to the psf_config data
300  structure cfg
301  -----------------------------------------------------------------
302  */
303 
304  sinfo_msg("Parsing cpl input");
305  check_nomsg(stk=cpl_frameset_new());
306 
307  cknull(cfg = sinfo_parse_cpl_input_psf(sof,&stk),
308  "error parsing cpl input");
309 
310  /* TODO the following generate a small leak of 72 bytes */
311  strehl_sw=sinfo_get_strehl_type(sof);
312  if(strehl_sw==0) {
313  sinfo_msg("One target Strehl computation");
314  if(sinfo_is_fits_file(cfg->inFrame) != 1) {
315  sinfo_msg_error("Input file %s is not FITS",cfg->inFrame);
316  goto cleanup;
317  } else {
318  strcpy(fname1,cfg->inFrame);
319  }
320 
321  if(NULL != cpl_frameset_find(sof,PRO_COADD_PSF)) {
322  frm1 = cpl_frameset_find(sof,PRO_COADD_PSF);
323  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_PSF)) {
324  frm1 = cpl_frameset_find(sof,PRO_OBS_PSF);
325  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_STD)) {
326  frm1 = cpl_frameset_find(sof,PRO_COADD_STD);
327  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_STD)) {
328  frm1 = cpl_frameset_find(sof,PRO_OBS_STD);
329  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_OBJ)) {
330  frm1 = cpl_frameset_find(sof,PRO_COADD_OBJ);
331  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_OBJ)) {
332  frm1 = cpl_frameset_find(sof,PRO_OBS_OBJ);
333  } else {
334  sinfo_msg_error("Frame %s or %s or %s or %s or %s or %s not found!",
335  PRO_COADD_PSF,PRO_OBS_PSF,
336  PRO_COADD_STD,PRO_OBS_STD,
337  PRO_COADD_OBJ,PRO_OBS_OBJ);
338  goto cleanup;
339  }
340 
341  sinfo_get_obsname(frm1,obs_name1);
342  check_nomsg(hlamp_st=sinfo_get_keyvalue_bool(frm1,KEY_NAME_LAMP_HALO));
343  check_nomsg(shut2_st=sinfo_get_keyvalue_bool(frm1,KEY_NAME_SHUT2_ST));
344 
345 
346  check_nomsg(cube1 = cpl_imagelist_load(fname1,CPL_TYPE_FLOAT,0));
347  cknull(med_img1=sinfo_new_median_cube(cube1),
348  " could not do sinfo_medianCube()");
349 
350  check_nomsg(ilx1=cpl_image_get_size_x(med_img1));
351  check_nomsg(ily1=cpl_image_get_size_y(med_img1));
352 
353  cx1 = ilx1 / 2. + 0.5;
354  cy1 = ily1 / 2. + 0.5;
355 
356  cknull(ao_performance=sinfo_get_strehl_from_cube(cube1,fname1,frm1),
357  "error computing strehl");
358  strehl=sinfo_get_strehl_from_ima(med_img1,frm1);
359  sinfo_free_imagelist(&cube1);
360  } else {
361  sinfo_msg("Two target Strehl computation");
362  sinfo_get_frm12(sof,&frm1,&frm2);
363  strcpy(fname1,cpl_frame_get_filename(frm1));
364  strcpy(fname2,cpl_frame_get_filename(frm2));
365 
366  check_nomsg(cube1 = cpl_imagelist_load(fname1,CPL_TYPE_FLOAT,0));
367  check_nomsg(cube2 = cpl_imagelist_load(fname2,CPL_TYPE_FLOAT,0));
368  cknull(med_img1=sinfo_new_median_cube(cube1),"Computing median on cube");
369  cknull(med_img2=sinfo_new_median_cube(cube2),"Computing median on cube");
370  check_nomsg(cpl_image_save(med_img1,"med_img1.fits",CPL_BPP_IEEE_FLOAT,
371  NULL,CPL_IO_DEFAULT));
372  check_nomsg(cpl_image_save(med_img2,"med_img2.fits",CPL_BPP_IEEE_FLOAT,
373  NULL,CPL_IO_DEFAULT));
374 
375 
376  check_nomsg(ilx1=cpl_image_get_size_x(med_img1));
377  check_nomsg(ily1=cpl_image_get_size_y(med_img1));
378  /*
379  check_nomsg(ilx2=cpl_image_get_size_x(med_img2));
380  check_nomsg(ily2=cpl_image_get_size_y(med_img2));
381  */
382  cx1 = ilx1 / 2. + 0.5;
383  cy1 = ily1 / 2. + 0.5;
384  /*
385  cx2 = ilx2 / 2. + 0.5;
386  cy2 = ily2 / 2. + 0.5;
387  */
388 
389  sinfo_free_imagelist(&cube1);
390  sinfo_free_imagelist(&cube2);
391 
392  cknull(tmp_tbl=sinfo_get_strehl_from_2images(med_img1,med_img2,frm1,frm2),
393  "Computing strehl");
394  check_nomsg(strehl=cpl_table_get_double(tmp_tbl,"strehl",0,&status));
395  sinfo_free_table(&tmp_tbl);
396  strehl1=sinfo_get_strehl_from_ima(med_img1,frm1);
397  sinfo_msg_debug("Strehl on 1st image=%f",strehl);
398  strehl2=sinfo_get_strehl_from_ima(med_img2,frm2);
399  sinfo_msg_debug("Strehl on 2nd image=%f",strehl);
400 
401  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
402  check_nomsg(sinfo_add_com_psf_qclog(fname1,&qclog_tbl));
403  if(irplib_isnan(strehl1)) strehl1=-100.;
404  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL025",strehl1,
405  "STREHL 25 mas","%f"));
406  ck0(sinfo_pro_save_ima(med_img1,ref_set,sof,PSF_MED_CUB_025_FILENAME,
407  PRO_MED_COADD_PSF,qclog_tbl,plugin_id,config),
408  "cannot save ima %s", PSF_MED_CUB_100_FILENAME);
409  sinfo_free_table(&qclog_tbl);
410 
411 
412  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
413  check_nomsg(sinfo_add_com_psf_qclog(fname2,&qclog_tbl));
414  if(irplib_isnan(strehl2)) strehl2=-100.;
415  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL100",strehl2,
416  "STREHL 100 mas","%f"));
417 
418  if(irplib_isnan(strehl)) strehl=-100.;
419 
420  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL",strehl,
421  "STREHL from both pixel scale images","%f"));
422  ck0(sinfo_pro_save_ima(med_img2,ref_set,sof,PSF_MED_CUB_100_FILENAME,
423  PRO_MED_COADD_PSF,qclog_tbl,plugin_id,config),
424  "cannot save ima %s", PSF_MED_CUB_100_FILENAME);
425 
426  sinfo_free_table(&qclog_tbl);
427  sinfo_free_image(&med_img2);
428 
429  }
430  /* STREHL computation */
431 
432  check_nomsg(nsample=cpl_table_get_nrow(ao_performance));
433  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
434  check_nomsg(sinfo_add_com_psf_qclog(fname1,&qclog_tbl));
435 
436  if(strehl_sw==0) {
437  if(irplib_isnan(strehl)) strehl=-100.;
438 
439  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL",strehl,
440  "STREHL from image","%f"));
441 
442  }
443 
444  check_nomsg(strehl=cpl_table_get_column_median(ao_performance,"strehl"));
445 
446  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL MED",strehl,
447  "STREHL MEDIAN","%f"));
448 
449  check_nomsg(strehl=cpl_table_get_column_mean(ao_performance,"strehl"));
450 
451  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL AVG",strehl,
452  "STREHL AVERAGE","%f"));
453  /*
454  strehl=sinfo_get_strehl_from_ima(med_img1,frm1);
455 
456  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL AVG",strehl,
457  "STREHL AVERAGE","%f"));
458  */
459  for(i=1;i<nsample;i++) {
460 
461  check_nomsg(strehl=cpl_table_get_double(ao_performance,"strehl",
462  i,&status));
463  if(irplib_isnan(strehl)) strehl=-100.;
464 
465  snprintf(key_name,MAX_NAME_SIZE-1,"%s%d","QC STREHL",i);
466  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,key_name,strehl,"STREHL","%f"));
467 
468  check_nomsg(lam=cpl_table_get_double(ao_performance,"wavelength",
469  i,&status));
470  snprintf(key_name,MAX_NAME_SIZE-1,"%s%d","QC LAMBDA",i);
471  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,key_name,lam,
472  "WAVELENGTH","%f"));
473 
474  }
475 
476  check_nomsg(strehl=cpl_table_get_column_median(ao_performance,
477  "strehl_error"));
478  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC STREHL MEDERR",strehl,
479  "STREHL ERROR MEDIAN","%f"));
480  ck0_nomsg(sinfo_qclog_add_string(qclog_tbl,"OBS NAME",obs_name1,
481  "OB name","%s"));
482  ck0_nomsg(sinfo_qclog_add_bool(qclog_tbl,PAF_NAME_LAMP_HALO,hlamp_st,
483  KEY_NAME_LAMP_HALO,"%d"));
484  ck0_nomsg(sinfo_qclog_add_bool(qclog_tbl,PAF_NAME_SHUT2_ST,shut2_st,
485  KEY_NAME_SHUT2_ST,"%d"));
486 
487  ck0(sinfo_pro_save_tbl(ao_performance,ref_set,sof,
488  PSF_AO_PERFORMANCE_OUT_FILENAME,
489  PRO_AO_PERFORMANCE,qclog_tbl,plugin_id,config),
490  "cannot save tbl %s", PSF_AO_PERFORMANCE_OUT_FILENAME);
491 
492  sinfo_free_table(&qclog_tbl);
493  sinfo_free_table(&ao_performance);
494 
495  /* Encircled energy & FWHM computation */
496  cknull_nomsg(qclog_tbl=sinfo_qclog_init());
497  cknull(enc_energy=sinfo_get_encircled_energy(sof,
498  med_img1,
499  &fwhm_x,
500  &fwhm_y,
501  &qclog_tbl),
502  "Computing encircled energy");
503 
504  ck0(sinfo_pro_save_tbl(enc_energy,ref_set,sof,PSF_ENC_ENERGY_OUT_FILENAME,
505  PRO_ENC_ENERGY,qclog_tbl,plugin_id,config),
506  "cannot save tbl %s", PSF_ENC_ENERGY_OUT_FILENAME);
507 
508  sinfo_free_table(&qclog_tbl);
509  sinfo_free_table(&enc_energy);
510 
511  /* QC log */
512  cknull_nomsg(qclog_tbl = sinfo_qclog_init());
513  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHMX",fwhm_x,
514  "QC FWHM X","%f"));
515  ck0_nomsg(sinfo_qclog_add_double(qclog_tbl,"QC FWHMY",fwhm_y,
516  "QC FWHM Y","%f"));
517  ck0_nomsg(sinfo_qclog_add_bool(qclog_tbl,PAF_NAME_LAMP_HALO,
518  hlamp_st,KEY_NAME_LAMP_HALO,"%d"));
519  ck0_nomsg(sinfo_qclog_add_bool(qclog_tbl,PAF_NAME_SHUT2_ST,shut2_st,
520  KEY_NAME_SHUT2_ST,"%d"));
521 
522  ck0(sinfo_pro_save_ima(med_img1,ref_set,sof,cfg->outName,PRO_PSF,
523  qclog_tbl,plugin_id,config),
524  "cannot save ima %s", cfg->outName);
525 
526  sinfo_free_table(&qclog_tbl);
527  sinfo_new_set_wcs_image(med_img1,cfg->outName,cx1, cy1);
528  sinfo_free_image(&med_img1);
529  sinfo_free_frameset(&stk);
530  sinfo_free_psf(&cfg);
531  return 0;
532 
533  cleanup:
534 
535  sinfo_free_table(&qclog_tbl);
536  sinfo_free_imagelist(&cube2);
537  sinfo_free_imagelist(&cube1);
538  sinfo_free_table(&enc_energy);
539  sinfo_free_image(&med_img1);
540  sinfo_free_table(&ao_performance);
541  sinfo_free_propertylist(&plist) ;
542  sinfo_free_psf(&cfg);
543  sinfo_free_frameset(&stk);
544 
545  return -1 ;
546 
547 }
548 
549 
550 
551 
552 static cpl_error_code
553 sinfo_add_com_psf_qclog(const char* fname,cpl_table** qclog_tbl)
554 {
555 
556  cpl_propertylist* plist=NULL;
557 
558  /* QC log */
559  cknull(plist = cpl_propertylist_load(fname, 0),
560  "getting header from reference ima frame %s",fname);
561 
562  if (cpl_propertylist_has(plist, KEY_NAME_LOOP_STATE)) {
563  sinfo_qclog_add_string(*qclog_tbl,KEY_NAME_LOOP_STATE,
564  cpl_propertylist_get_string(plist,KEY_NAME_LOOP_STATE),
565  KEY_HELP_LOOP_STATE,"%s");
566  }
567 
568 
569 
570  if (cpl_propertylist_has(plist, KEY_NAME_LOOP_LGS)) {
571  sinfo_qclog_add_int(*qclog_tbl,KEY_NAME_LOOP_LGS,
572  cpl_propertylist_get_int(plist,KEY_NAME_LOOP_LGS),
573  KEY_HELP_LOOP_LGS,"%d");
574  }
575 
576 
577  if (cpl_propertylist_has(plist, KEY_NAME_INS1_MODE)) {
578  sinfo_qclog_add_string(*qclog_tbl,KEY_NAME_INS1_MODE,
579  cpl_propertylist_get_string(plist,KEY_NAME_INS1_MODE),
580  KEY_HELP_INS1_MODE,"%s");
581  }
582 
583 
584  cleanup:
585  sinfo_free_propertylist(&plist);
586 
587  if (cpl_error_get_code() != CPL_ERROR_NONE) {
588  return cpl_error_get_code();
589  } else {
590  return CPL_ERROR_NONE;
591  }
592 
593 
594 }
595 
596 static int
597 sinfo_get_strehl_from_image(cpl_image* img,
598  double ws,
599  double we,
600  double pscale,
601  double strehl_star_radius,
602  double strehl_bg_r1,
603  double strehl_bg_r2,
604  double* strehl,
605  double* strehl_err)
606 {
607  cpl_errorstate clean_state = cpl_errorstate_get();
608 
609  cpl_image* img_dup=NULL;
610 
611  /*
612  double max_ima_cx=0.;
613  double max_ima_cy=0.;
614  */
615  double psf_peak=0.;
616  double psf_flux=0.;
617  double bkg_noise=0.;
618  double star_bkg=0.;
619  double star_peak=0.;
620  double star_flux=0.;
621 
622  cpl_size max_ima_x=0;
623  cpl_size max_ima_y=0;
624  int wllx=0;
625  int wlly=0;
626  int wurx=0;
627  int wury=0;
628  int ima_szx=0;
629  int ima_szy=0;
630 
631 
632  double lam = (double)0.5*(ws+we);
633  double dlam=we-ws;
634  sinfo_msg_debug("ws=%f we=%f dl=%f",ws,we,dlam);
635  check_nomsg(img_dup=cpl_image_duplicate(img));
636  sinfo_clean_nan(&img_dup);
637  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
638  sinfo_free_image(&img_dup);
639 
640  check_nomsg(ima_szx=cpl_image_get_size_x(img));
641  check_nomsg(ima_szy=cpl_image_get_size_y(img));
642  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
643  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
644  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
645  ima_szx,ima_szy);
646 
647  //cpl_image_get_maxpos_window(img,wllx,wlly,wurx,wury,&max_ima_x,&max_ima_y);
648  /*
649  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
650  wurx,wury));
651  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
652  wurx,wury));
653  */
654 
655  if(CPL_ERROR_NONE != sinfo_strehl_compute_one(img,
656  SINFO_STREHL_M1,
657  SINFO_STREHL_M2,
658  lam,
659  dlam,
660  pscale,
661  max_ima_x,
662  max_ima_y,
663  strehl_star_radius,
664  strehl_bg_r1,
665  strehl_bg_r2,
666  SINFO_STREHL_BOX_SIZE,
667  strehl,
668  strehl_err,
669  &star_bkg,
670  &star_peak,
671  &star_flux,
672  &psf_peak,
673  &psf_flux,
674  &bkg_noise)) {
675 
676 
677  *strehl=-1;
678  *strehl_err=0;
679  irplib_error_recover(clean_state,"Problem computing strehl");
680 
681  }
682 
683  return 0;
684 
685  cleanup:
686 
687  return -1;
688 
689 }
690 
691 
692 
693 
694 
695 
696 static int
697 sinfo_get_strehl_from_slice(cpl_imagelist* cube,
698  double disp,
699  double cWave,
700  double ws,
701  double we,
702  double pscale,
703  double strehl_star_radius,
704  double strehl_bg_r1,
705  double strehl_bg_r2,
706  double* strehl,
707  double* strehl_err)
708 {
709 
710 
711  cpl_errorstate clean_state = cpl_errorstate_get();
712 
713 
714  cpl_image* img_dup=NULL;
715  cpl_image* img=NULL;
716 
717 
718 
719  /*
720  double max_ima_cx=0.;
721  double max_ima_cy=0.;
722  */
723  double psf_peak=0.;
724  double psf_flux=0.;
725  double bkg_noise=0.;
726  double star_bkg=0.;
727  double star_peak=0.;
728  double star_flux=0.;
729 
730  cpl_size max_ima_x=0;
731  cpl_size max_ima_y=0;
732  int wllx=0;
733  int wlly=0;
734  int wurx=0;
735  int wury=0;
736  int ima_szx=0;
737  int ima_szy=0;
738 
739 
740  double lam = (double)0.5*(ws+we);
741  double dlam=we-ws;
742 
743 
744  img=sinfo_new_average_cube_to_image_between_waves(cube,disp,cWave,ws,we);
745  check_nomsg(img_dup=cpl_image_duplicate(img));
746  sinfo_clean_nan(&img_dup);
747  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
748  check_nomsg(cpl_image_delete(img_dup));
749 
750 
751  check_nomsg(ima_szx=cpl_image_get_size_x(img));
752  check_nomsg(ima_szy=cpl_image_get_size_y(img));
753  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
754  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
755 
756 
757  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
758  ima_szx,ima_szy);
759 
760  /*
761  cpl_image_get_maxpos_window(img,wllx,wlly,wurx,wury,&max_ima_x,&max_ima_y);
762  */
763  /*
764  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
765  wurx,wury));
766 
767 
768 
769  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
770  wurx,wury));
771  */
772 
773  cpl_image_reject_value(img, CPL_VALUE_NAN);
774  if(CPL_ERROR_NONE != irplib_strehl_compute(img,
775  SINFO_STREHL_M1,
776  SINFO_STREHL_M2,
777  lam,
778  dlam,
779  pscale,
780  SINFO_STREHL_BOX_SIZE,
781  max_ima_x,
782  max_ima_y,
783  strehl_star_radius,
784  strehl_bg_r1,
785  strehl_bg_r2,
786  NOISE_HSIZE,
787  NOISE_NSAMPLES,
788  strehl,
789  strehl_err,
790  &star_bkg,
791  &star_peak,
792  &star_flux,
793  &psf_peak,
794  &psf_flux,
795  &bkg_noise)) {
796 
797 
798  *strehl=-1;
799  *strehl_err=0;
800  irplib_error_recover(clean_state,"Problem computing strehl");
801 
802  }
803 
804  /*
805  cpl_msg_info(__func__,"stehl=%f err=%f star_bkg=%f star_peak=%f star_flux=%f",
806  *strehl,*strehl_err,star_bkg,star_peak,star_flux);
807  cpl_msg_info(__func__,"psf_peak=%f psf_flux=%f bkg_noise=%f",
808  psf_peak,psf_flux,bkg_noise);
809  */
810  sinfo_free_image(&img);
811 
812 
813  return 0;
814 
815  cleanup:
816  return -1;
817 
818 }
819 
820 
821 
822 cpl_table* sinfo_get_encircled_energy(cpl_frameset* sof,
823  cpl_image* img,
824  double* fwhm_x,
825  double* fwhm_y,
826  cpl_table** qclog_tbl)
827 {
828 
829  cpl_errorstate clean_state = cpl_errorstate_get();
830 
831  cpl_image* img_dup=NULL;
832  cpl_size max_ima_x=0;
833  cpl_size max_ima_y=0;
834  int wllx=0;
835  int wlly=0;
836  int wurx=0;
837  int wury=0;
838  const double d_mirror = 8.;
839  const double factor = 180/PI_NUMB*3600.;
840  /*
841  double max_ima_cx=0;
842  double max_ima_cy=0;
843  */
844  double norm=0.;
845  double xc=0.;
846  double yc=0.;
847  double sx=0.;
848  double sy=0.;
849 
850  double flux=0;
851  double flux_max=1;
852  double pix_scale=0;
853  double lam=0.;
854  double pscale=0.;
855  int dr_difr=0;
856 
857  double r=0.;
858  double bkg=0.;
859  int i=0;
860  int ni=0;
861  int ir_difr=0;
862  int dr=0;
863  int rmin=0;
864 
865  char band[MAX_NAME_SIZE];
866  char spat_res[MAX_NAME_SIZE];
867 
868  cpl_table* enc_energy=NULL;
869  cpl_frame* frame=NULL;
870 
871  int ima_szx=0;
872  int ima_szy=0;
873 
874 
875 
876  if(NULL != cpl_frameset_find(sof,PRO_COADD_PSF)) {
877  frame = cpl_frameset_find(sof,PRO_COADD_PSF);
878  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_PSF)) {
879  frame = cpl_frameset_find(sof,PRO_OBS_PSF);
880  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_STD)) {
881  frame = cpl_frameset_find(sof,PRO_COADD_STD);
882  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_STD)) {
883  frame = cpl_frameset_find(sof,PRO_OBS_STD);
884  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_OBJ)) {
885  frame = cpl_frameset_find(sof,PRO_COADD_OBJ);
886  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_OBJ)) {
887  frame = cpl_frameset_find(sof,PRO_OBS_OBJ);
888  } else {
889  sinfo_msg_error("Frame %s or %s or %s or %s or %s or %s not found!",
890  PRO_COADD_PSF,PRO_OBS_PSF,
891  PRO_COADD_STD, PRO_OBS_STD,
892  PRO_COADD_OBJ, PRO_OBS_OBJ);
893  return NULL;
894  }
895 
896  sinfo_get_spatial_res(frame,spat_res);
897  sinfo_get_band(frame,band);
898  pix_scale=atof(spat_res);
899  lam=sinfo_get_wave_cent(band);
900  /* factor 2 due to change of detector to 2K */
901  pscale=0.5*pix_scale;
902 
903 
904 
905  dr_difr=factor*1.22*lam*1.e-6/d_mirror/pscale;
906  ir_difr=floor(dr_difr+0.5);
907  if (pix_scale==0.025) {
908  ni=10;
909  rmin=ir_difr;
910  dr=rmin;
911  } else {
912  ni=15;
913  sinfo_msg_warning("Reset diffraction limit");
914  ir_difr=10;
915  rmin=1;
916  dr=2;
917  }
918 
919  sinfo_msg("Diffraction limit: %d",ir_difr);
920 
921  check_nomsg(img_dup=cpl_image_duplicate(img));
922  sinfo_clean_nan(&img_dup);
923  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
924  sinfo_free_image(&img_dup);
925 
926 
927 
928  check_nomsg(ima_szx=cpl_image_get_size_x(img));
929  check_nomsg(ima_szy=cpl_image_get_size_y(img));
930  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
931  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
932  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
933  ima_szx,ima_szy);
934  /*
935  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
936  wurx,wury));
937  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
938  wurx,wury));
939  */
940 
941  cpl_image_save(img, "bad_image_psf_c.fits",CPL_BPP_IEEE_DOUBLE, NULL, CPL_IO_CREATE);
942  sinfo_msg("@@@@ sinfo_get_encircled_energy() max_ima_x[%" CPL_SIZE_FORMAT "] max_ima_y[%" CPL_SIZE_FORMAT "] psf_sz[%d]", max_ima_x,
943  max_ima_y,
944  SINFO_PSF_SZ);
945 
946  if(CPL_ERROR_NONE != cpl_image_fit_gaussian(img,max_ima_x,max_ima_y,
947  SINFO_PSF_SZ,
948  &norm,&xc,&yc,&sx,&sy,
949  fwhm_x,fwhm_y)) {
950 
951 
952  irplib_error_recover(clean_state,"Gaussian fit failed");
953 
954  }
955 
956  check_nomsg(enc_energy = cpl_table_new(ni));
957  check_nomsg(cpl_table_new_column(enc_energy,"r_pix", CPL_TYPE_INT));
958  check_nomsg(cpl_table_new_column(enc_energy,"r_mas", CPL_TYPE_DOUBLE));
959  check_nomsg(cpl_table_new_column(enc_energy,"r_dif", CPL_TYPE_DOUBLE));
960  check_nomsg(cpl_table_new_column(enc_energy,"abs_energy" , CPL_TYPE_DOUBLE));
961  check_nomsg(cpl_table_new_column(enc_energy,"rel_energy" , CPL_TYPE_DOUBLE));
962 
963  /* encircled energy computation */
964  check_nomsg(bkg=irplib_strehl_ring_background(img,max_ima_x,max_ima_y,
965  SINFO_BKG_R1,SINFO_BKG_R2,IRPLIB_BG_METHOD_AVER_REJ)) ;
966  r=rmin+(ni-1)*dr;
967  cpl_image_reject_value(img, CPL_VALUE_NAN);
968  check_nomsg(flux_max=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
969  r=rmin;
970 
971  for(i=0; i<ni; i++)
972  {
973  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
974 
975  check_nomsg(cpl_table_set_int(enc_energy,"r_pix",i,r));
976  check_nomsg(cpl_table_set_double(enc_energy,"r_mas",i,r*pscale));
977  check_nomsg(cpl_table_set_double(enc_energy,"r_dif",i,r/ir_difr));
978  if(!isnan(flux)) {
979  check_nomsg(cpl_table_set_double(enc_energy,"abs_energy",i,flux));
980  } else {
981  check_nomsg(cpl_table_set_double(enc_energy,"abs_energy",i,-999));
982  }
983  r+=dr;
984  }
985  /* Because flux may be NAN we compute flux_max in two stages */
986  flux_max=cpl_table_get_column_max(enc_energy,"abs_energy");
987 
988  r=rmin;
989  for(i=0; i<ni; i++)
990  {
991  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
992  if(!isnan(flux)) {
993  check_nomsg(cpl_table_set_double(enc_energy,"rel_energy",i,flux/flux_max));
994  } else {
995  check_nomsg(cpl_table_set_double(enc_energy,"rel_energy",i,1));
996  }
997  r+=dr;
998  }
999 
1000  //sinfo_msg("max ima=%d %d\n",max_ima_x,max_ima_y);
1001  //sinfo_msg("centroid ima=%f %f\n",max_ima_cx,max_ima_cy);
1002  //sinfo_msg("gauss info=%f %f %f %f %f %f %f\n",
1003  // norm,xc,yc,sx,sy,*fwhm_x,*fwhm_y);
1004 
1005 
1006  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,
1007  ir_difr,bkg));
1008  double enc_en=-999;
1009  if(!isnan(flux) && !isnan(flux_max)) {
1010  enc_en=flux/flux_max;
1011  }
1012  ck0_nomsg(sinfo_qclog_add_double(*qclog_tbl,"QC ENC CORE",
1013  enc_en,
1014  "Encircled energy within PSF core","%f"));
1015  return enc_energy;
1016 
1017  cleanup:
1018  sinfo_free_image(&img_dup);
1019 
1020  return NULL;
1021 }
1022 
1023 
1024 static cpl_table* sinfo_get_strehl_from_cube(cpl_imagelist* cube,
1025  char* name,
1026  cpl_frame* frame)
1027 {
1028  cpl_table* strehl_tbl=NULL;
1029 
1030  /* double wrange=0; */
1031  double wstart=0;
1032  double wstep=0;
1033  double wend=0;
1034  double ws=0;
1035  double we=0;
1036  double pix_scale=0;
1037  double lam=0;
1038  /* double dlam=0; */
1039  double pscale = 0;
1040 
1041  double strehl_star_radius=0;
1042  double strehl_bg_r1=0;
1043  double strehl_bg_r2=0;
1044  double strehl=0;
1045  double strehl_err=0;
1046  char spat_res[MAX_NAME_SIZE];
1047  cpl_propertylist* plist=NULL;
1048 
1049  /* int naxis3=0; */
1050  int nsample=0;
1051  int i=0;
1052 
1053 
1054  sinfo_get_spatial_res(frame,spat_res);
1055  pix_scale=atof(spat_res);
1056  sinfo_msg("Camera pixel scale=%f",pix_scale);
1057  /* factor 2 due to change of detector to 2K */
1058  pscale=0.5*pix_scale;
1059 
1060  strehl_star_radius=SINFO_BKG_R1*pscale;
1061  strehl_bg_r1=SINFO_BKG_R1*pscale;
1062  strehl_bg_r2=SINFO_BKG_R2*pscale;
1063 
1064  plist=cpl_propertylist_load(name,0);
1065  double dispersion=sinfo_pfits_get_cdelt3(plist);
1066  double centralWave=sinfo_pfits_get_crval3(plist);
1067  /* naxis3=sinfo_pfits_get_naxis3(plist); */
1068  sinfo_free_propertylist(&plist);
1069  /* wrange=dispersion*naxis3; */
1070 
1071  wstart = centralWave - (float) (cpl_imagelist_get_size(cube) / 2)*
1072  dispersion+dispersion;
1073  wend =wstart + dispersion * cpl_imagelist_get_size(cube);
1074  wstep=0.025;
1075  /*
1076  note:
1077  -wstep as we do not hit the borders where the
1078  sinfo_gaussian fit has a problem
1079  */
1080  nsample=(int)((wend-wstart-wstep)/wstep);
1081  check_nomsg(strehl_tbl = cpl_table_new(nsample));
1082  check_nomsg(cpl_table_new_column(strehl_tbl,"wavelength",CPL_TYPE_DOUBLE));
1083  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl",CPL_TYPE_DOUBLE));
1084  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl_error",CPL_TYPE_DOUBLE));
1085 
1086 
1087  for(i=1;i<nsample;i++) {
1088 
1089  ws=wstart+wstep*i;
1090  we=ws+wstep;
1091 
1092  lam = (double)0.5*(ws+we);
1093  /* dlam=wstep; */
1094 
1095  check(sinfo_get_strehl_from_slice(cube,
1096  dispersion,
1097  centralWave,
1098  ws,
1099  we,
1100  pscale,
1101  strehl_star_radius,
1102  strehl_bg_r1,
1103  strehl_bg_r2,
1104  &strehl,
1105  &strehl_err),"Error computing strehl");
1106 
1107 
1108  if((isnan(lam) ==0) &&
1109  (isnan(lam) ==0) &&
1110  (isnan(lam) ==0)) {
1111  check_nomsg(cpl_table_set_double(strehl_tbl,"wavelength",i,lam));
1112  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl",i,strehl));
1113  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl_error",i,
1114  strehl_err));
1115 
1116  }
1117  }
1118 
1119  return strehl_tbl;
1120 
1121  cleanup:
1122  return NULL;
1123 
1124 
1125 }
1126 
1127 
1128 static double
1129 sinfo_get_strehl_from_ima(cpl_image* ima,
1130  cpl_frame* frame)
1131 {
1132 
1133  double dispersion=0.;
1134  double centralWave=0.;
1135  double wstart=0;
1136  double wend=0;
1137  double pscale = 0;
1138 
1139  double strehl_star_radius=0;
1140  double strehl_bg_r1=0;
1141  double strehl_bg_r2=0;
1142  double strehl=0;
1143  double strehl_err=0;
1144  double exptime=0;
1145 
1146 
1147 
1148  ck0_nomsg(sinfo_get_strehl_input1(frame,&dispersion,&centralWave,
1149  &wstart,&wend,&pscale,&exptime,
1150  &strehl_star_radius,&strehl_bg_r1,
1151  &strehl_bg_r2));
1152 
1153 
1154  check(sinfo_get_strehl_from_image(ima,
1155  wstart,
1156  wend,
1157  pscale,
1158  strehl_star_radius,
1159  strehl_bg_r1,
1160  strehl_bg_r2,
1161  &strehl,
1162  &strehl_err),"Computing Strehl");
1163 
1164 
1165 
1166 
1167 
1168  cleanup:
1169  return strehl;
1170 
1171 
1172 }
1173 
1174 static int
1175 sinfo_get_frm12(cpl_frameset* sof,cpl_frame** frm1,cpl_frame** frm2){
1176 
1177  cpl_frameset* obs=NULL;
1178  int nobs=0;
1179  float* pix_scale=NULL;
1180 
1181  obs = cpl_frameset_new();
1182  sinfo_contains_frames_kind(sof,obs,PRO_OBS_PSF);
1183  nobs=cpl_frameset_get_size(obs);
1184  if (nobs < 1) {
1185  sinfo_contains_frames_kind(sof,obs,PRO_OBS_STD);
1186  nobs=cpl_frameset_get_size(obs);
1187  }
1188 
1189  nobs=cpl_frameset_get_size(obs);
1190 
1191 
1192  if (nobs < 1) {
1193  sinfo_contains_frames_kind(sof,obs,PRO_OBS_OBJ);
1194  nobs=cpl_frameset_get_size(obs);
1195  }
1196 
1197  nobs=cpl_frameset_get_size(obs);
1198 
1199  if (nobs < 1) {
1200  return -1;
1201  } else {
1202  pix_scale=cpl_calloc(nobs,sizeof(float));
1203  float eps=0.0001;
1204  for(int i=0;i<nobs;i++) {
1205  cpl_frame* frame=cpl_frameset_get_frame(obs,i);
1206  pix_scale[i]=sinfo_pfits_get_pixelscale(
1207  (char*)cpl_frame_get_filename(frame));
1208  if(fabs(pix_scale[i]-0.025)< eps) {
1209  *frm1=cpl_frame_duplicate(frame);
1210  } else if (fabs(pix_scale[i]-0.1) <eps) {
1211  *frm2=cpl_frame_duplicate(frame);
1212  } else {
1213  sinfo_msg_error("No proper frame found for strehl computation");
1214  cpl_free(pix_scale);
1215  return -1;
1216  }
1217  }
1218  }
1219  cpl_free(pix_scale);
1220  cpl_frameset_delete(obs);
1221 
1222  return 0;
1223 
1224 }
1225 
1226 
1227 
1228 
1229 static int
1230 sinfo_get_strehl_input1(cpl_frame* frm,
1231  double* dispersion,
1232  double* centralWave,
1233  double* wstart,
1234  double* wend,
1235  double* pscale,
1236  double* exptime,
1237  double* strehl_star_rad,
1238  double* strehl_bg_rmin,
1239  double* strehl_bg_rmax)
1240 
1241 {
1242 
1243  cpl_propertylist* plist=NULL;
1244  char res[MAX_NAME_SIZE];
1245  double pix_scale=0;
1246  double wrange=0;
1247  char fname[MAX_NAME_SIZE];
1248  int naxis3=0;
1249 
1250  sinfo_get_spatial_res(frm,res);
1251  pix_scale=atof(res);
1252 
1253  /* factor 2 due to change of detector to 2K
1254  *pscale=0.5*pix_scale;
1255  */
1256 
1257 
1258  *pscale=pix_scale;
1259 
1260  *strehl_star_rad=SINFO_RSTAR*(*pscale);
1261  *strehl_bg_rmin=SINFO_BKG_R1*(*pscale);
1262  *strehl_bg_rmax=SINFO_BKG_R2*(*pscale);
1263 
1264  strcpy(fname,cpl_frame_get_filename(frm));
1265  check_nomsg(plist=cpl_propertylist_load(fname,0));
1266  check_nomsg(*dispersion=sinfo_pfits_get_cdelt3(plist));
1267  *centralWave=sinfo_pfits_get_crval3(plist);
1268  check_nomsg(naxis3=sinfo_pfits_get_naxis3(plist));
1269  *exptime=sinfo_pfits_get_exp_time(plist);
1270  sinfo_free_propertylist(&plist);
1271 
1272  wrange=(*dispersion)*naxis3;
1273 
1274  *wstart = *centralWave - (wrange / 2) +(*dispersion);
1275  *wend = *wstart + wrange;
1276 
1277 
1278  cleanup:
1279  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1280  return -1;
1281  } else {
1282  return 0;
1283  }
1284 
1285 }
1286 
1287 
1288 static int
1289 sinfo_get_strehl_input2(cpl_frame* frm1,
1290  cpl_frame* frm2,
1291  double* dispersion,
1292  double* centralWave,
1293  double* wstart,
1294  double* wend,
1295  double* pscale1,
1296  double* pscale2,
1297  double* exptime1,
1298  double* exptime2,
1299  double* strehl_star_rad1,
1300  double* strehl_star_rad2,
1301  double* strehl_bg_rmin1,
1302  double* strehl_bg_rmin2,
1303  double* strehl_bg_rmax1,
1304  double* strehl_bg_rmax2)
1305 
1306 {
1307 
1308  cpl_propertylist* plist=NULL;
1309  char res1[MAX_NAME_SIZE];
1310  char res2[MAX_NAME_SIZE];
1311  double pix_scale1=0;
1312  double pix_scale2=0;
1313  double wrange=0;
1314  char fname1[MAX_NAME_SIZE];
1315  char fname2[MAX_NAME_SIZE];
1316  int naxis3=0;
1317 
1318  sinfo_get_spatial_res(frm1,res1);
1319  sinfo_get_spatial_res(frm2,res2);
1320  pix_scale1=atof(res1);
1321  pix_scale2=atof(res2);
1322  /* factor 2 due to change of detector to 2K
1323  *pscale1=0.5*pix_scale1;
1324  *pscale2=0.5*pix_scale2;
1325  */
1326 
1327  *pscale1=pix_scale1;
1328  *pscale2=pix_scale2;
1329 
1330 
1331  *strehl_star_rad1=SINFO_RSTAR*(*pscale1);
1332  *strehl_bg_rmin1=SINFO_BKG_R1*(*pscale1);
1333  *strehl_bg_rmax1=SINFO_BKG_R2*(*pscale1);
1334 
1335  *strehl_star_rad2=SINFO_RSTAR*(*pscale2);
1336  *strehl_bg_rmin2=SINFO_BKG_R1*(*pscale2);
1337  *strehl_bg_rmax2=SINFO_BKG_R2*(*pscale2);
1338 
1339  strcpy(fname1,cpl_frame_get_filename(frm1));
1340  check_nomsg(plist=cpl_propertylist_load(fname1,0));
1341  check_nomsg(*dispersion=sinfo_pfits_get_cdelt3(plist));
1342  *centralWave=sinfo_pfits_get_crval3(plist);
1343  check_nomsg(naxis3=sinfo_pfits_get_naxis3(plist));
1344  *exptime1=sinfo_pfits_get_exp_time(plist);
1345  sinfo_free_propertylist(&plist);
1346  strcpy(fname2,cpl_frame_get_filename(frm2));
1347 
1348 
1349  check_nomsg(plist=cpl_propertylist_load(fname2,0));
1350  *exptime2=sinfo_pfits_get_exp_time(plist);
1351  sinfo_free_propertylist(&plist);
1352 
1353 
1354 
1355  wrange=(*dispersion)*naxis3;
1356 
1357  *wstart = *centralWave - (wrange / 2) +(*dispersion);
1358  *wend = *wstart + wrange;
1359 
1360 
1361  cleanup:
1362  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1363  return -1;
1364  } else {
1365  return 0;
1366  }
1367 
1368 }
1369 
1370 
1371 
1372 static cpl_table*
1373 sinfo_get_strehl_from_2images(cpl_image* ima1,
1374  cpl_image* ima2,
1375  cpl_frame* frm1,
1376  cpl_frame* frm2)
1377 {
1378 
1379  cpl_table* strehl_tbl=NULL;
1380 
1381 
1382  double dispersion=0.;
1383  double centralWave=0.;
1384  double wstart=0;
1385  double wstep=0;
1386  double wend=0;
1387  double lam=0;
1388  double dlam=0;
1389  double pscale1 = 0;
1390  double pscale2 = 0;
1391 
1392  double strehl_star_rad1=0;
1393  double strehl_star_rad2=0;
1394  double strehl_bg_rmin1=0;
1395  double strehl_bg_rmin2=0;
1396  double strehl_bg_rmax1=0;
1397  double strehl_bg_rmax2=0;
1398  double strehl=0;
1399  double strehl_err=0;
1400 
1401  int nsample=1;
1402  double exptime1=0;
1403  double exptime2=0;
1404  cpl_image* img_dup=NULL;
1405 
1406  cpl_size max_ima1_x=0;
1407  cpl_size max_ima1_y=0;
1408 
1409  cpl_size max_ima2_x=0;
1410 
1411 
1412  cpl_size max_ima2_y=0;
1413  double star_bkg=0;
1414  double star_peak=0;
1415  double star_flux=0;
1416 
1417  double psf_peak=0;
1418  double psf_flux=0;
1419  double bkg_noise=0;
1420 
1421  cpl_errorstate clean_state = cpl_errorstate_get();
1422 
1423  ck0_nomsg(sinfo_get_strehl_input2(frm1,frm2,&dispersion, &centralWave,
1424  &wstart,&wend,&pscale1,&pscale2,
1425  &exptime1,&exptime2,
1426  &strehl_star_rad1,&strehl_star_rad2,
1427  &strehl_bg_rmin1,&strehl_bg_rmin2,
1428  &strehl_bg_rmax1,&strehl_bg_rmax2));
1429 
1430 
1431 
1432 
1433 
1434  check_nomsg(img_dup=cpl_image_duplicate(ima1));
1435  sinfo_clean_nan(&img_dup);
1436  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima1_x,&max_ima1_y));
1437  sinfo_free_image(&img_dup);
1438 
1439 
1440  check_nomsg(img_dup=cpl_image_duplicate(ima2));
1441  sinfo_clean_nan(&img_dup);
1442  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima2_x,&max_ima2_y));
1443  sinfo_free_image(&img_dup);
1444 
1445  /*
1446  note:
1447  -wstep as we do not hit the borders where the
1448  sinfo_gaussian fit has a problem
1449  */
1450 
1451 
1452 
1453  check_nomsg(strehl_tbl = cpl_table_new(nsample));
1454  check_nomsg(cpl_table_new_column(strehl_tbl,"wavelength",CPL_TYPE_DOUBLE));
1455  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl",CPL_TYPE_DOUBLE));
1456  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl_error",CPL_TYPE_DOUBLE));
1457  wstep = wend-wstart;
1458 
1459 
1460 
1461  lam = (double)0.5*(wstart+wend);
1462  dlam=wstep;
1463  sinfo_msg("lambda=%f dlambda=%f",lam,dlam);
1464  sinfo_msg("wstart=%f wend=%f",wstart,wend);
1465  sinfo_msg("wstep=%f",wstep);
1466 
1467 
1468  if(CPL_ERROR_NONE != sinfo_strehl_compute_two(ima1,ima2,
1469  SINFO_STREHL_M1,SINFO_STREHL_M2,
1470  lam,
1471  pscale1,pscale2,
1472  exptime1,exptime2,
1473  max_ima1_x,max_ima1_y,
1474  max_ima2_x,max_ima2_y,
1475  strehl_star_rad1,
1476  strehl_bg_rmin1,
1477  strehl_bg_rmax1,
1478  &strehl,&strehl_err,&star_bkg,
1479  &star_peak,&star_flux,
1480  &psf_peak,&psf_flux,&bkg_noise))
1481  {
1482 
1483  strehl=-1;
1484  strehl_err=0;
1485  irplib_error_recover(clean_state,
1486  "Problem computing strehl, set it to -1");
1487 
1488  }
1489 
1490 
1491  if((isnan(lam) ==0) &&
1492  (isnan(lam) ==0) &&
1493  (isnan(lam) ==0)) {
1494  check_nomsg(cpl_table_set_double(strehl_tbl,"wavelength",0,lam));
1495  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl",0,strehl));
1496  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl_error",
1497  0,strehl_err));
1498 
1499  }
1500 
1501 
1502 
1503  return strehl_tbl;
1504  cleanup:
1505 
1506 
1507  return NULL;
1508 }
1509 
1510 
1511 
1512 /*---------------------------------------------------------------------------*/
1547 /*---------------------------------------------------------------------------*/
1548 #define irplib_assure_code cpl_ensure_code
1549 int sinfo_strehl_compute_two(
1550  const cpl_image * im1,
1551  const cpl_image * im2,
1552  double m1,
1553  double m2,
1554  double lam,
1555  double pscale1,
1556  double pscale2,
1557  double exptime1,
1558  double exptime2,
1559  int xpos1,
1560  int ypos1,
1561  int xpos2,
1562  int ypos2,
1563  double r1,
1564  double r2,
1565  double r3,
1566  double * strehl,
1567  double * strehl_err,
1568  double * star_bkg,
1569  double * star_peak,
1570  double * star_flux,
1571  double * psf_peak,
1572  double * psf_flux,
1573  double * bg_noise)
1574 {
1575  double psf_peak1=0;
1576  double psf_peak2=0;
1577  /*
1578  double psf_flux1=0;
1579  double psf_flux2=0;
1580  */
1581  double star_bkg1=0;
1582  double star_bkg2=0;
1583  double star_flux1=0;
1584  double star_flux2=0;
1585  double star_peak1=0;
1586  double star_peak2=0;
1587 
1588  const double window_size = 5.0 ;
1589  //double star_radius;
1590  //double max_radius ;
1591  double ring[4];
1592 
1593  double prat=pscale2/pscale1;
1594  double prat2=prat*prat;
1595  double trat=exptime1/exptime2;
1596  double frat=sinfo_scale_flux(pscale1,pscale2,exptime1,exptime2);
1597  double xc=0;
1598  double yc=0;
1599  /*
1600  int sx=0;
1601  int sy=0;
1602  */
1603  int d=16;
1604  cpl_errorstate initial_errorstate = cpl_errorstate_get();
1605 
1606 
1607  /* Test inputs */
1608  irplib_assure_code(im1 != NULL, CPL_ERROR_NULL_INPUT);
1609  irplib_assure_code(im2 != NULL, CPL_ERROR_NULL_INPUT);
1610  irplib_assure_code(strehl != NULL, CPL_ERROR_NULL_INPUT);
1611  irplib_assure_code(strehl_err != NULL, CPL_ERROR_NULL_INPUT);
1612  irplib_assure_code(star_bkg != NULL, CPL_ERROR_NULL_INPUT);
1613  irplib_assure_code(star_peak != NULL, CPL_ERROR_NULL_INPUT);
1614  irplib_assure_code(star_flux != NULL, CPL_ERROR_NULL_INPUT);
1615  irplib_assure_code(psf_peak != NULL, CPL_ERROR_NULL_INPUT);
1616  irplib_assure_code(psf_flux != NULL, CPL_ERROR_NULL_INPUT);
1617 
1618  irplib_assure_code(pscale1 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1619  irplib_assure_code(pscale2 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1620 
1621  irplib_assure_code(xpos1-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1622  irplib_assure_code(ypos1-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1623  irplib_assure_code(xpos2-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1624  irplib_assure_code(ypos2-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1625 
1626  irplib_assure_code(xpos1+window_size <= cpl_image_get_size_x(im1),
1627  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1628  irplib_assure_code(ypos1+window_size <= cpl_image_get_size_y(im1),
1629  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1630 
1631  irplib_assure_code(xpos2+window_size <= cpl_image_get_size_x(im2),
1632  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1633  irplib_assure_code(ypos2+window_size <= cpl_image_get_size_y(im2),
1634  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1635 
1636  irplib_assure_code(r1 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1637  irplib_assure_code(r2 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1638  irplib_assure_code(r3 > r2, CPL_ERROR_ILLEGAL_INPUT);
1639 
1640  /* Computing a Strehl ratio is a story between an ideal PSF */
1641  /* and a candidate image supposed to approximate this ideal PSF. */
1642 
1643  /* Generate first appropriate PSF to find max peak: same pscale as
1644  the one of the image where we compute the flux */
1645 
1646  /*
1647  sx=cpl_image_get_size_x(im1);
1648  sy=cpl_image_get_size_y(im1);
1649  */
1650 
1651  /* psf_flux1 = 1.0; // The psf flux, cpl_image_get_flux(psf), is always 1 */
1652  /* psf_flux2 = 1.0; // The psf flux, cpl_image_get_flux(psf), is always 1 */
1653  *psf_flux=1.0;
1654  ring[0] = xpos2;
1655  ring[1] = ypos2;
1656  ring[2] = r2/pscale2;
1657  ring[3] = r3/pscale2;
1658 
1659  sinfo_msg_debug("star_pos=%d %d %d %d",xpos1,ypos1,xpos2,ypos2);
1660  sinfo_msg_debug("star_ring=%f %f %f %f",ring[0],ring[1],ring[2],ring[3]);
1661 
1662  /* Compute star_radius in pixels */
1663  //star_radius = r1/pscale2;
1664 
1665  /* Find the peak value on the central part of the candidate image */
1666 
1667 
1668  /* Find the peak value on the central part of the candidate image */
1669  //max_radius = window_size < star_radius ? window_size : star_radius;
1670 
1671  check_nomsg(sinfo_get_star_features(im1,d,xpos1,ypos1,&xc,&yc,
1672  &star_peak1,&star_flux1,&star_bkg1));
1673 
1674 
1675  *star_peak=star_peak1;
1676 
1677  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale1,xc,yc,1.,
1678  &psf_peak1));
1679 
1680  check_nomsg(sinfo_get_star_features(im2,d,xpos2,ypos2,&xc,&yc,
1681  &star_peak2,&star_flux2,&star_bkg2));
1682 
1683  *star_flux=star_flux2;
1684  *star_bkg=star_bkg2;
1685 
1686  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale2,xc,yc,1.,
1687  &psf_peak2));
1688 
1689 
1690 
1691 
1692  sinfo_msg_debug("p1=%g p2=%g",*star_peak,star_peak2);
1693  sinfo_msg_debug("corr peak: p1=%g p2=%g",*star_peak,star_peak2/frat);
1694  sinfo_msg_debug("corr bkg: bkg1=%g bkg2=%g",star_bkg1/frat,*star_bkg);
1695  sinfo_msg_debug("rel diff: %g",
1696  fabs(star_peak2/frat- *star_peak)/(star_peak2/frat));
1697 
1698 
1699 
1700  sinfo_msg_debug("Rescaled star_flux1=%g star_flux2=%g",
1701  star_flux1*trat,*star_flux);
1702 
1703  //Check that flux value as measured on im1 and on 1m2 are close one
1704  //to another. Note that flux1, measured on im1, need to be rescaled
1705  //by exposure time to match to flux2=star_flux
1706  if ( fabs((star_flux1*frat-*star_flux)/(*star_flux)) > 0.25) {
1707  sinfo_msg_debug("Star flux rel diff: %g",
1708  fabs((star_flux1*frat-*star_flux)/(*star_flux)));
1709  }
1710 
1711  //Check that pick value as measured on im1 and on 1m2 are close one
1712  //to another. Note that peak2, measured on im2, need to be rescaled
1713  //by exposure time and pixel scale to match to peak1=star_peak
1714  if ( fabs(star_peak2-star_peak1*frat)/(star_peak2) > 0.25) {
1715  sinfo_msg_debug("Star pick rel diff: %g",
1716  fabs(star_peak2-star_peak1*frat)/(star_peak2));
1717  }
1718  sinfo_msg_debug("ak1 star peak=%g",*star_peak);
1719  irplib_assure_code(*star_peak > 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
1720  *star_peak=star_peak1;
1721 
1722  *star_bkg=star_bkg2;
1723  *star_flux=star_flux2;
1724 
1725  sinfo_msg_debug("ak2");
1726 
1727  //psf1 = irplib_strehl_generate_psf(m1, m2, lam, dlam, pscale1, size*4);
1728  //psf_peak1 = cpl_image_get_max(psf1) ;
1729 
1730 
1731 
1732  /* Compute Strehl */
1733  //*strehl = (*star_peak *prat2/trat/ *star_flux) / (*psf_peak / *psf_flux);
1734  *strehl = (*star_peak/(*star_flux*trat)) / (psf_peak1 );
1735  //*strehl = (*star_peak/(*star_flux)) / (psf_peak1 / *psf_flux) ;
1736  sinfo_msg_debug("peak=%g flux1=%f flux2=%f flux=%f cflux=%g "
1737  "fct=%g psf_peak=%g",
1738  *star_peak,star_flux1,star_flux2,*star_flux,
1739  *star_flux/frat*prat2,prat2/frat,psf_peak1);
1740  sinfo_msg_debug("=======strehl=%g",*strehl);
1741  /*
1742  if (*strehl > 1)
1743  cpl_msg_warning(cpl_func, "Extreme Strehl-ratio=%g, star_peak=%g, "
1744  "star_flux=%g, psf_peak=%g, psf_flux=%g", *strehl,
1745  *star_peak, *star_flux, *psf_peak, *psf_flux);
1746 
1747 
1748  // Compute Strehl error
1749  if (cpl_flux_get_noise_ring(im2, ring, noise_box_sz, noise_nsamples,
1750  bg_noise, NULL) == CPL_ERROR_NONE) {
1751  *strehl_err = SINFO_STREHL_ERROR_COEFFICIENT * (*bg_noise) * pscale2 *
1752  star_radius * star_radius / *star_flux;
1753  irplib_assure_code(*strehl_err >= 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
1754  } else {
1755  sinfo_msg_warning("Problem computing noise");
1756  }
1757  */
1758  *bg_noise=0;
1759 
1760  cleanup:
1761 
1762 
1763  if (!cpl_errorstate_is_equal(initial_errorstate)) {
1764  /* Dump the error history since recipe execution start.
1765  At this point the recipe cannot recover from the error */
1766  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
1767  }
1768 
1769  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1770  return cpl_error_get_code();
1771  } else {
1772  return CPL_ERROR_NONE;
1773  }
1774 
1775 }
1776 
1777 
1778 
1779 
1780 static cpl_error_code
1781 sinfo_get_star_features(const cpl_image* im,
1782  const int radius,
1783  const int xpos,
1784  const int ypos,
1785  double* xc,
1786  double* yc,
1787  double* peak,
1788  double* flux,
1789  double* bkg)
1790 {
1791  int sx=0;
1792  int sy=0;
1793  int ixm=0;
1794  int iym=0;
1795  int llx=0;
1796  int lly=0;
1797  int urx=0;
1798  int ury=0;
1799  int dim_new=0;
1800  double kappa=2;
1801  double xm=0;
1802  double ym=0;
1803  double bkg_stdev=0;
1804  int bkg_sx=SINFO_BKG_BOX_SZ;
1805  int bkg_sy=SINFO_BKG_BOX_SZ;
1806 
1807  cpl_bivector* iqe=NULL;
1808  double* piqe=NULL;
1809  cpl_image* im_new=NULL;
1810 
1811  sx=cpl_image_get_size_x(im);
1812  sy=cpl_image_get_size_y(im);
1813 
1814  sinfo_msg_debug("star_radius=%d",radius);
1815  //We find the image centroid
1816 
1817  if(NULL != (iqe=cpl_image_iqe(im,sx/2-radius,sy/2-radius,
1818  sx/2+radius,sy/2+radius))) {
1819 
1820  piqe=cpl_bivector_get_x_data(iqe);
1821  //*star_peak=piqe[5];
1822  xm=piqe[0];
1823  ym=piqe[1];
1824  //Extract a square sub-image of minimal size not to hit the image borders
1825  //centered on the previous image centroid
1826  sinfo_msg_debug("Max ima: %g %g",xm,ym);
1827  sinfo_msg_debug("Find min of: %g %g %g %g",xm,sx-xm,ym,sy-ym);
1828  ixm=floor(xm);
1829  iym=floor(ym);
1830 
1831  sinfo_msg_debug("ixm=%d iym=%d",ixm,iym);
1832  dim_new=floor(sinfo_find_min_of_four(xm,sx-xm,ym,sy-ym));
1833  sinfo_msg_debug("dim_new=%d",dim_new);
1834  llx=(ixm-dim_new > 1) ? ixm-dim_new : 1;
1835  lly=(iym-dim_new > 1) ? iym-dim_new : 1;
1836  urx=(ixm+dim_new < sx) ? ixm+dim_new : sx;
1837  ury=(iym+dim_new < sy) ? iym+dim_new : sy;
1838  sinfo_msg_debug("llx=%d lly=%d urx=%d ury=%d",llx,lly,urx,ury);
1839  check_nomsg(im_new=cpl_image_extract(im,llx,lly,urx,ury));
1840 
1841  //compute the background of this last image
1842  check_nomsg(sinfo_get_bkg_4corners(im_new,bkg_sx,bkg_sy,bkg,&bkg_stdev));
1843 
1844  sinfo_free_bivector(&iqe);
1845  //Determine the image pick on the new coordinate system
1846  if(NULL != (iqe=cpl_image_iqe(im_new,dim_new-radius,dim_new-radius,
1847  dim_new+radius,dim_new+radius))) {
1848 
1849  piqe=cpl_bivector_get_x_data(iqe);
1850  sinfo_msg_debug("xc=%g yc=%g",piqe[0],piqe[1]);
1851  *xc=piqe[0]-dim_new-1;
1852  *yc=piqe[1]-dim_new-1;
1853 
1854  sinfo_msg_debug("xc=%g yc=%g",*xc,*yc);
1855  //*peak=piqe[5];
1856  *peak=cpl_image_get_max_window(im_new,dim_new-radius,dim_new-radius,
1857  dim_new+radius,dim_new+radius);
1858 
1859  sinfo_get_flux_above_bkg(im_new,kappa,bkg_stdev,flux);
1860  *peak -= (*bkg);
1861  sinfo_msg_debug("star peak=%g bkg=%g",*peak,*bkg);
1862  sinfo_free_bivector(&iqe);
1863 
1864  } else {
1865 
1866  sinfo_msg_warning("IQE fit failed");
1867  cpl_error_reset();
1868  sinfo_msg_debug("xc=%d yc=%d radius=%d",xpos,ypos,radius);
1869  *xc=xpos-sx/2;
1870  *yc=ypos-sy/2;
1871  sinfo_msg_debug("xc=%g yc=%g",*xc,*yc);
1872  check_nomsg(sinfo_get_bkg_4corners(im,bkg_sx,bkg_sy,bkg,&bkg_stdev));
1873  check_nomsg(sinfo_get_safe_box(&llx, &lly, &urx, &ury, xpos,ypos,radius,
1874  64,64));
1875  check_nomsg(*peak=cpl_image_get_max_window(im,llx,lly,urx,ury)-(*bkg));
1876  sinfo_get_flux_above_bkg(im,kappa,bkg_stdev,flux);
1877  sinfo_msg_debug("star peak=%g bkg=%g",*peak,*bkg);
1878 
1879  }
1880 
1881  } else {
1882  sinfo_msg_warning("IQE fit failed");
1883  cpl_error_reset();
1884  sinfo_msg_debug("xc=%d yc=%d radius=%d",xpos,ypos,radius);
1885  *xc=xpos-sx/2;
1886  *yc=ypos-sy/2;
1887  sinfo_msg_debug("xc=%g yc=%g",*xc,*yc);
1888  check_nomsg(sinfo_get_bkg_4corners(im,bkg_sx,bkg_sy,bkg,&bkg_stdev));
1889  check_nomsg(sinfo_get_safe_box(&llx, &lly, &urx, &ury, xpos,ypos,radius,
1890  64,64));
1891  check_nomsg(*peak=cpl_image_get_max_window(im,llx,lly,urx,ury)-(*bkg));
1892  sinfo_get_flux_above_bkg(im,kappa,bkg_stdev,flux);
1893  sinfo_msg_debug("star peak=%g bkg=%g",*peak,*bkg);
1894  }
1895 
1896  cleanup:
1897  sinfo_free_image(&im_new);
1898  sinfo_free_bivector(&iqe);
1899 
1900  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1901  return cpl_error_get_code();
1902  } else {
1903  return CPL_ERROR_NONE;
1904  }
1905 
1906 }
1907 
1908 
1909 
1910 
1911 
1912 
1913 /*----------------------------------------------------------------------------*/
1940 /*----------------------------------------------------------------------------*/
1941 cpl_error_code
1942 sinfo_strehl_compute_one(const cpl_image * im,
1943  double m1,
1944  double m2,
1945  double lam,
1946  double dlam,
1947  double pscale,
1948  int xpos,
1949  int ypos,
1950  double r1,
1951  double r2,
1952  double r3,
1953  int size,
1954  double * strehl,
1955  double * strehl_err,
1956  double * star_bkg,
1957  double * star_peak,
1958  double * star_flux,
1959  double * psf_peak,
1960  double * psf_flux,
1961  double * bg_noise)
1962 {
1963  cpl_image * psf;
1964  /* double star_radius; */
1965 
1966  /* FIXME: Arbitrary choice of image border */
1967  const double window_size = (double)(SINFO_STREHL_RAD_CENTRAL);
1968 
1969  /* Determined empirically by C. Lidman for Strehl error computation */
1970  //Commented as not used
1971  //const double strehl_error_coefficient = SINFO_MATH_PI * 0.007 / 0.0271;
1972 
1973  /* double ring[4]; */
1974 
1975  cpl_bivector* iqe1=NULL;
1976  double xc=0;
1977  double yc=0;
1978  int d=16;
1979 
1980 
1981 
1982  /* Check compile-time constant */
1983  cpl_ensure_code(window_size > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1984 
1985  /* Test inputs */
1986  cpl_ensure_code(im != NULL, CPL_ERROR_NULL_INPUT);
1987  cpl_ensure_code(strehl != NULL, CPL_ERROR_NULL_INPUT);
1988  cpl_ensure_code(strehl_err != NULL, CPL_ERROR_NULL_INPUT);
1989  cpl_ensure_code(star_bkg != NULL, CPL_ERROR_NULL_INPUT);
1990  cpl_ensure_code(star_peak != NULL, CPL_ERROR_NULL_INPUT);
1991  cpl_ensure_code(star_flux != NULL, CPL_ERROR_NULL_INPUT);
1992  cpl_ensure_code(psf_peak != NULL, CPL_ERROR_NULL_INPUT);
1993  cpl_ensure_code(psf_flux != NULL, CPL_ERROR_NULL_INPUT);
1994 
1995  cpl_ensure_code(pscale > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1996 
1997 
1998  cpl_ensure_code(r1 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1999  cpl_ensure_code(r2 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
2000 
2001  cpl_ensure_code(r3 > r2, CPL_ERROR_ILLEGAL_INPUT);
2002 
2003 
2004  /* Computing a Strehl ratio is a story between an ideal PSF */
2005  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale,xc,yc,
2006  1.,psf_peak));
2007  /* and a candidate image supposed to approximate this ideal PSF. */
2008 
2009  /* Generate first appropriate PSF to find max peak */
2010 
2011  psf = irplib_strehl_generate_psf(m1, m2, lam, dlam, pscale, size);
2012  cpl_ensure_code(psf != NULL, CPL_ERROR_ILLEGAL_OUTPUT);
2013 
2014  /* Compute flux in PSF and find max peak */
2015  *psf_peak = cpl_image_get_max(psf);
2016 
2017  cpl_image_delete(psf);
2018 
2019 
2020 
2021 
2022  cpl_ensure( *psf_peak > 0.0, CPL_ERROR_ILLEGAL_OUTPUT,CPL_ERROR_ILLEGAL_OUTPUT); /* The ideal PSF has a positive maximum */
2023  *psf_flux = 1.0; /* The psf flux, cpl_image_get_flux(psf), is always 1 */
2024 
2025 
2026  /* Compute star_radius in pixels */
2027  /*star_radius = r1/pscale; */
2028 
2029 
2030  check_nomsg(sinfo_get_star_features(im,d,xpos,ypos,&xc,&yc,
2031  star_peak,star_flux,star_bkg));
2032 
2033 
2034  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale,xc,yc,1.,psf_peak));
2035 
2036 
2037 
2038  *star_peak -= *star_bkg;
2039 
2040 
2041  cpl_ensure_code(*star_peak > 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
2042 
2043 
2044  /* Compute Strehl */
2045  /* (StarPeak / StarFlux) / (PsfPeak / PsfFlux) */
2046  sinfo_msg_debug("Star flux=%g", *star_flux);
2047  sinfo_msg_debug("Star peak=%g", *star_peak);
2048  sinfo_msg_debug("PSF flux=%g", *psf_flux);
2049  sinfo_msg_debug("PSF peak=%g", *psf_peak);
2050 
2051  *strehl = (*star_peak * *psf_flux ) / ( *star_flux * *psf_peak);
2052 
2053 
2054 
2055  if (*strehl > 1)
2056  cpl_msg_warning(cpl_func, "Extreme Strehl-ratio=%g, star_peak=%g, "
2057  "star_flux=%g, psf_peak=%g, psf_flux=%g", *strehl,
2058  *star_peak, *star_flux, *psf_peak, *psf_flux);
2059 
2060  /* Compute Strehl error */
2061  /*
2062  ring[0] = xpos;
2063  ring[1] = ypos;
2064  ring[2] = r2/pscale;
2065  ring[3] = r3/pscale;
2066  */
2067  /*
2068  *strehl_err = strehl_error_coefficient * (*bg_noise) * pscale *
2069  star_radius * star_radius / *star_flux;
2070 
2071  // This check should not be able to fail, but just to be sure
2072  cpl_ensure_code(*strehl_err >= 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
2073  */
2074  *bg_noise=0;
2075 
2076 
2077  cleanup:
2078  sinfo_free_bivector(&iqe1);
2079  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2080  return cpl_error_get_code();
2081  } else {
2082  return CPL_ERROR_NONE;
2083  }
2084 
2085 
2086 }
2087 
2088 
2089 
2090 static void
2091 sinfo_check_borders(cpl_size* val,const int max,const int thresh)
2092 {
2093 
2094  *val = ((*val-thresh) > 0) ? *val : thresh;
2095  *val = ((*val+thresh) < max) ? *val : max-thresh-1;
2096  return;
2097 }
2098 
2099 static void
2100 sinfo_get_safe_box(int* llx,
2101  int* lly,
2102  int* urx,
2103  int* ury,
2104  const int xpos,
2105  const int ypos,
2106  const int box,
2107  const int szx,
2108  const int szy)
2109 
2110 {
2111  *llx= ((xpos-box)>0) ? (xpos-box) : 1;
2112  *lly= ((ypos-box)>0) ? (ypos-box) : 1;
2113  *urx= ((xpos+box)<szx) ? (xpos+box) : szx-1 ;
2114  *ury= ((ypos+box)<szy) ? (ypos+box) : szy-1 ;
2115 
2116  return;
2117 }
2118 
2119 
2120 
2121 
2122 
2123 /*---------------------------------------------------------------------------*/
2133 /*---------------------------------------------------------------------------*/
2134 cpl_error_code
2135 sinfo_get_bkg_4corners(const cpl_image *img,
2136  const int bkg_sx,
2137  const int bkg_sy,
2138  double* bkg,
2139  double* std)
2140 {
2141 
2142  int sx=0;
2143  int sy=0;
2144  cpl_image* img_bkg=NULL;
2145  *bkg=0;
2146 
2147  cknull(img,"NULL input image!");
2148  check_nomsg(sx=cpl_image_get_size_x(img));
2149  check_nomsg(sy=cpl_image_get_size_y(img));
2150 
2151  check_nomsg(img_bkg=cpl_image_new(2*bkg_sx,2*bkg_sy,CPL_TYPE_FLOAT));
2152  cpl_image* img_ext=NULL;
2153  img_ext=cpl_image_extract(img,1,1,bkg_sx,bkg_sy);
2154  check_nomsg(cpl_image_copy(img_bkg,img_ext,1,1));
2155  sinfo_free_image(&img_ext);
2156 
2157  img_ext=cpl_image_extract(img,sx-bkg_sx,1, sx,bkg_sy);
2158  check_nomsg(cpl_image_copy(img_bkg,img_ext,bkg_sx+1,1));
2159  sinfo_free_image(&img_ext);
2160 
2161  img_ext=cpl_image_extract(img,1,sy-bkg_sy,bkg_sx,sy);
2162  check_nomsg(cpl_image_copy(img_bkg,img_ext,1,bkg_sy+1));
2163  sinfo_free_image(&img_ext);
2164 
2165  img_ext=cpl_image_extract(img,sx-bkg_sx,sy-bkg_sy,sx,sy);
2166  check_nomsg(cpl_image_copy(img_bkg,img_ext,bkg_sx+1,bkg_sy+1));
2167  sinfo_free_image(&img_ext);
2168 
2169  check_nomsg(*bkg=cpl_image_get_median(img_bkg));
2170  check_nomsg(*std=cpl_image_get_stdev(img_bkg));
2171  sinfo_msg_debug("sky bkg: %f",*bkg);
2172  sinfo_msg_debug("sky stdev: %f",*std);
2173 
2174 
2175  cleanup:
2176  sinfo_free_image(&img_ext);
2177  sinfo_free_image(&img_bkg);
2178 
2179  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2180  return cpl_error_get_code();
2181  } else {
2182  return CPL_ERROR_NONE;
2183  }
2184 
2185 
2186 }
2187 
2200 /*---------------------------------------------------------------------------*/
2201 cpl_error_code
2202 sinfo_compute_psf(const double dia,
2203  const double occ,
2204  const double lambda,
2205  const double psize,
2206  const double cx,
2207  const double cy,
2208  const double anamorph,
2209  double* psf_peak)
2210 {
2211 
2212  int bin=SINFO_PSF_BIN;
2213  int npoints=SINFO_PSF_NPOINT;
2214 
2215  int dim=SINFO_PSF_DIM;
2216  int blocks=SINFO_PSF_BLOCKS;
2217  int sx=dim;
2218  int sy=dim;
2219 
2220 
2221  int i=0;
2222  int j=0;
2223  double k=0;
2224 
2225  int ii=0;
2226  int jj=0;
2227  int start=0;
2228 
2229  double nyquist=lambda/dia/2.*206265/psize*bin;
2230  double cor=0.;
2231  double v0=0;
2232  double ll[npoints];
2233  double part[npoints];
2234  double ee;
2235  double dll=0;
2236  double tot1=0;
2237  double tot2=0;
2238 
2239 
2240  double fct=0;
2241 
2242  double* pxx=NULL;
2243  double* pyy=NULL;
2244  double* prr=NULL;
2245  double* ppsf0=NULL;
2246 
2247  double* pcor=NULL;
2248  double* pairy=NULL;
2249  /* double* pw=NULL; */
2250 
2251  cpl_image* img_xx=NULL;
2252  cpl_image* img_yy=NULL;
2253  cpl_image* img_rr=NULL;
2254  cpl_image* img_rrcor=NULL;
2255  cpl_image* img_airy=NULL;
2256  cpl_image* img_w=NULL;
2257  cpl_image* img_psf0=NULL;
2258 
2259 
2260 
2261  sinfo_msg_debug("lambda=%g",lambda);
2262  sinfo_msg_debug("dia=%f",dia);
2263  sinfo_msg_debug("psize=%f",psize);
2264  sinfo_msg_debug("bin=%d",bin);
2265  sinfo_msg_debug("nyquist=%f",nyquist);
2266 
2267  check_nomsg(img_xx=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE));
2268  img_yy=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2269  img_rr=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2270  //img_rrcor=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2271 
2272  pxx=cpl_image_get_data_double(img_xx);
2273  pyy=cpl_image_get_data_double(img_yy);
2274  prr=cpl_image_get_data_double(img_rr);
2275 
2276  for(j=0;j<sy;j++) {
2277  for(i=0;i<sx;i++) {
2278  //xz plane increasing along y
2279  pxx[j*sx+i]=(i-sx/2-cx*bin)/nyquist*SINFO_MATH_PI/2;
2280  //yz plane increasing along x
2281  pyy[j*sx+i]=(j-sy/2-cy*bin)/nyquist*SINFO_MATH_PI/2*anamorph;
2282 
2283  //combinex xyz surface
2284  prr[j*sx+i]=sqrt(pxx[j*sx+i]*pxx[j*sx+i]+pyy[j*sx+i]*pyy[j*sx+i]);
2285  }
2286  }
2287 
2288  /*
2289  check_nomsg(cpl_image_save(img_xx,"out_xx.fits", CPL_BPP_IEEE_DOUBLE,
2290  NULL,CPL_IO_DEFAULT));
2291 
2292  check_nomsg(cpl_image_save(img_yy,"out_yy.fits", CPL_BPP_IEEE_DOUBLE,
2293  NULL,CPL_IO_DEFAULT));
2294 
2295  check_nomsg(cpl_image_save(img_rr,"out_rr.fits", CPL_BPP_IEEE_DOUBLE,
2296  NULL,CPL_IO_DEFAULT));
2297 
2298  */
2299 
2300  //img_rrcor=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2301 
2302  cor=1./(1.-occ*occ);
2303  cor*=cor;
2304 
2305  img_rrcor=cpl_image_duplicate(img_rr);
2306  cpl_image_multiply_scalar(img_rrcor,cor);
2307  pcor=cpl_image_get_data_double(img_rrcor);
2308 
2309  /*
2310  check_nomsg(cpl_image_save(img_rrcor,"out_rrcor.fits", CPL_BPP_IEEE_DOUBLE,
2311  NULL,CPL_IO_DEFAULT));
2312  */
2313 
2314  img_airy=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2315  pairy=cpl_image_get_data_double(img_airy);
2316 
2317 
2318  if (occ == 0.0) {
2319 
2320  for(j=0;j<sx;j++) {
2321  for(i=0;i<sy;i++) {
2322  fct=(2.*j1(prr[j*sx+i])/prr[j*sx+i]);
2323  pairy[j*sx+i]=fct*fct;
2324 
2325  }
2326  }
2327 
2328  } else {
2329  for(j=0;j<sy;j++) {
2330  for(i=0;i<sx;i++) {
2331 
2332  fct=(2.*j1(prr[j*sx+i])/prr[j*sx+i]-occ*occ*2.*j1(pcor[j*sx+i])/pcor[j*sx+i]);
2333  pairy[j*sx+i]=cor*fct*fct;
2334 
2335  }
2336  }
2337  }
2338 
2339  /*
2340  check_nomsg(cpl_image_save(img_airy,"out_airy.fits", CPL_BPP_IEEE_DOUBLE,
2341  NULL,CPL_IO_DEFAULT));
2342 
2343  */
2344 
2345  //To remove an expected NAN value at the PSF centre we re-set PSF(centre)=1
2346  img_w=cpl_image_duplicate(img_airy);
2347  /* pw=cpl_image_get_data_double(img_w); */
2348  pairy=cpl_image_get_data_double(img_airy);
2349 
2350  for(j=0;j<sy;j++) {
2351  for(i=0;i<sx;i++) {
2352  if(!irplib_isnan(pairy[i+j*sx]) && (pairy[i+j*sx] ==0)) {
2353  pairy[i+j*sx]=1.;
2354  sinfo_msg_debug("====> %f",pairy[i+j*sx]);
2355  }
2356  }
2357  }
2358  pairy[sx/2+sy/2*sx]=1.;
2359 
2360  sinfo_msg_debug("total-airy=%f",cpl_image_get_flux(img_airy));
2361 
2362  /*
2363  check_nomsg(cpl_image_save(img_airy,"out_airy1.fits", CPL_BPP_IEEE_DOUBLE,
2364  NULL,CPL_IO_DEFAULT));
2365 
2366  */
2367 
2368 
2369  // Computation of EE
2370 
2371 
2372  v0=prr[0+dim/4-1];
2373  sinfo_msg_debug("v0=%12.10g",v0);
2374  for(i=0;i<npoints;i++) {
2375  ll[i]=(double)i/npoints*v0;
2376  }
2377  dll=ll[1]-ll[0];
2378  cor=1./(1.-occ*occ);
2379 
2380  for(i=0;i<npoints;i++) {
2381  part[i]=2.*j1(ll[i])/ll[i];
2382  }
2383  part[0]=1.0;
2384 
2385  tot1=0.;
2386  for(i=0;i<npoints;i++) {
2387  tot1+=j1(occ*ll[i])*part[i]*dll;
2388  }
2389  sinfo_msg_debug("tot=%10.8f",tot1);
2390 
2391 
2392  sinfo_msg_debug("cor=%10.8f",cor);
2393 
2394  ee=(1.-j0(v0)*j0(v0));
2395 
2396  sinfo_msg_debug("(1-j0(v0)*j0(v0))=%10.8f",ee);
2397 
2398 
2399  ee-=(j1(v0))*(j1(v0));
2400  sinfo_msg_debug("j1^2=%10.8f",(j1(v0))*(j1(v0)));
2401  sinfo_msg_debug("ee=%10.8f",ee);
2402 
2403  sinfo_msg_debug("factor=%10.8f",
2404  occ*occ*(1-j0(occ*v0)*j0(occ*v0)-j1(occ*v0)*j1(occ*v0)));
2405 
2406 
2407  ee+=occ*occ*(1-j0(occ*v0)*j0(occ*v0)-j1(occ*v0)*j1(occ*v0));
2408  sinfo_msg_debug("ee=%10.8f",ee);
2409 
2410  ee-=2.*occ*tot1;
2411  sinfo_msg_debug("ee=%10.8f",ee);
2412 
2413  ee*=cor;
2414  sinfo_msg_debug("ee=%10.8f",ee);
2415 
2416 
2417  tot1=0;
2418  pairy=cpl_image_get_data_double(img_airy);
2419  prr=cpl_image_get_data_double(img_rr);
2420  for(j=0;j<sy;j++) {
2421  for(i=0;i<sx;i++) {
2422  if(!irplib_isnan(pairy[i+j*sx]) && (prr[i+j*sx] <v0)) {
2423  tot1+=pairy[i+j*sx]*ee;
2424  //sinfo_msg_debug("tot=%f",tot1);
2425 
2426  }
2427  }
2428  }
2429 
2430  sinfo_msg_debug("tot=%10.8f",tot1);
2431  cpl_image_divide_scalar(img_airy,tot1);
2432 
2433  /*
2434  check_nomsg(cpl_image_save(img_airy,"out_airy2.fits", CPL_BPP_IEEE_DOUBLE,
2435  NULL,CPL_IO_DEFAULT));
2436 
2437  */
2438 
2439 
2440  // Computation of maximum
2441 
2442  sinfo_msg_debug("dim=%d blocks=%d,bin=%d",dim,blocks,bin);
2443  start=(dim/2-1)-(blocks/2*bin-1)-bin/2;
2444  sinfo_msg_debug("start=%d",start);
2445 
2446  img_psf0=cpl_image_new(blocks,blocks,CPL_TYPE_DOUBLE);
2447  ppsf0=cpl_image_get_data_double(img_psf0);
2448  tot1=0.;
2449  tot2=0.;
2450 
2451  for(j=0;j<blocks;j++) {
2452  for(i=0;i<blocks;i++) {
2453  tot1=0;
2454  for(jj=start+j*bin;jj<start+(j+1)*bin-1;jj++){
2455  for(ii=start+i*bin;ii<start+(i+1)*bin-1;ii++){
2456  if(!irplib_isnan(pairy[ii+jj*sx])) {
2457  tot1+=pairy[ii+jj*sx];
2458  }
2459  }
2460  }
2461  ppsf0[i+j*blocks]=tot1;
2462  tot2+=tot1;
2463  }
2464  }
2465 
2466  cpl_image_divide_scalar(img_psf0,tot2);
2467  /*
2468  check_nomsg(cpl_image_save(img_psf0,"out_psf0.fits", CPL_BPP_IEEE_DOUBLE,
2469  NULL,CPL_IO_DEFAULT));
2470 
2471  */
2472  k=180.*3600./SINFO_MATH_PI;
2473  sinfo_msg_debug("k=%f",k);
2474  sinfo_msg_debug("radius of first zero: 1.22*lambda/d*k:=%f",
2475  1.22*lambda/dia*k);
2476  sinfo_msg_debug("tot: %f",tot2);
2477  sinfo_msg_debug("max: %f",cpl_image_get_max(img_psf0)*tot2);
2478  sinfo_msg_debug("max/tot: %f",cpl_image_get_max(img_psf0));
2479  *psf_peak=cpl_image_get_max(img_psf0);
2480 
2481  sinfo_msg_debug("d=%g ob=%g w=%g ps=%g cx=%g cy=%g a=%g peak=%10.8g",
2482  dia,occ,lambda,psize,cx,cy,anamorph,*psf_peak);
2483 
2484 
2485 
2486  cleanup:
2487  sinfo_free_image(&img_w);
2488  sinfo_free_image(&img_psf0);
2489  sinfo_free_image(&img_xx);
2490  sinfo_free_image(&img_yy);
2491  sinfo_free_image(&img_rr);
2492  sinfo_free_image(&img_rrcor);
2493  sinfo_free_image(&img_airy);
2494 
2495 
2496  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2497  return cpl_error_get_code();
2498  } else {
2499  return CPL_ERROR_NONE;
2500  }
2501 
2502 }
2503 
2504 
2505 cpl_error_code
2506 sinfo_get_flux_above_bkg(const cpl_image* img,
2507  const float kappa,
2508  const float std,
2509  double* f)
2510 {
2511 
2512  const float* pimg=NULL;
2513  int sx=0;
2514  int sy=0;
2515  int i=0;
2516  int j=0;
2517  int k=0;
2518  float tot=0;
2519 
2520  cpl_image* timg=NULL;
2521  double sky_bkg=0;
2522  double sky_std=0;
2523 
2524  timg=cpl_image_duplicate(img);
2525  cpl_image_subtract_scalar(timg,std);
2526  check_nomsg(sinfo_get_bkg_4corners(timg,SINFO_BKG_BOX_SZ,SINFO_BKG_BOX_SZ,
2527  &sky_bkg,&sky_std));
2528 
2529  check_nomsg(pimg=cpl_image_get_data_float_const(timg));
2530 
2531  sx=cpl_image_get_size_x(img);
2532  sy=cpl_image_get_size_y(img);
2533 
2534  for(j=0;j<sy;j++) {
2535  for(i=0;i<sx;i++) {
2536  if(!irplib_isnan(pimg[i+j*sx]) &&
2537  (pimg[i+j*sx]>(sky_bkg+kappa*sky_std))) {
2538  tot+=(double)pimg[i+j*sx];
2539  k++;
2540  }
2541  }
2542  }
2543 
2544  *f=(double)(tot-k*sky_bkg);
2545 
2546  cleanup:
2547  sinfo_free_image(&timg);
2548 
2549  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2550  return cpl_error_get_code();
2551  } else {
2552  return CPL_ERROR_NONE;
2553  }
2554 
2555 }
2556 
2557 
2558 
2559 /*
2560 cpl_error_code
2561 sinfo_get_centroid(const cpl_image* img,
2562  const int d,
2563  const double xc,
2564  const double yc,
2565  double* xcen,
2566  double* ycen,
2567  double* xfwhm,
2568  double* yfwhm,
2569  double* angle)
2570 {
2571 
2572  cpl_bivector* q=NULL;
2573  int sx=0;
2574  int sy=0;
2575  double* pq=NULL;
2576  double peak=0;
2577  double bkg=0;
2578 
2579  check_nomsg(sx=cpl_image_get_size_x(img));
2580  check_nomsg(sy=cpl_image_get_size_y(img));
2581 
2582  check_nomsg(q=cpl_image_iqe(img,sx/2-d,sy/2-d,sx/2+d,sy/2+d));
2583  pq=cpl_bivector_get_data(q);
2584 
2585  *xcen=pq[0];
2586  *ycen=pq[1];
2587  *xfwhm=pq[2];
2588  *yfwhm=pq[3];
2589  *angle=pq[4];
2590  peak=pq[5];
2591  bkg=pq[6];
2592 
2593 
2594  cleanup:
2595 
2596  sinfo_free_bivector(&q);
2597 
2598  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2599  return cpl_error_get_code();
2600  } else {
2601  return CPL_ERROR_NONE;
2602  }
2603 
2604 }
2605  */
2606 
2607 
2608 
2609 static double
2610 sinfo_find_min_of_four(const double n1,
2611  const double n2,
2612  const double n3,
2613  const double n4)
2614 {
2615  double min=0;
2616  min = (n1 < n2) ? n1 : n2;
2617  min = (min < n3) ? min : n3;
2618  min = (min < n4) ? min : n4;
2619  return min;
2620 }
2621 
2622 double
2623 sinfo_scale_flux(const double p1,
2624  const double p2,
2625  const double t1,
2626  const double t2)
2627 {
2628 
2629  return (p2/p1)*(p2/p1)*(t2/t1);
2630 
2631 }
2632 
2633 
#define sinfo_msg_debug(...)
Print a debug message.
Definition: sinfo_msg.h:103
#define sinfo_msg_error(...)
Print an error message.
Definition: sinfo_msg.h:69
#define sinfo_msg_warning(...)
Print an warning message.
Definition: sinfo_msg.h:93