SINFONI Pipeline Reference Manual  2.5.2
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 sinfo_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 (sinfo_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 (sinfo_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 (sinfo_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  double dlam=0.;
612  double lam=0.;
613  /*
614  double max_ima_cx=0.;
615  double max_ima_cy=0.;
616  */
617  double psf_peak=0.;
618  double psf_flux=0.;
619  double bkg_noise=0.;
620  double star_bkg=0.;
621  double star_peak=0.;
622  double star_flux=0.;
623 
624  cpl_size max_ima_x=0;
625  cpl_size max_ima_y=0;
626  int wllx=0;
627  int wlly=0;
628  int wurx=0;
629  int wury=0;
630  int ima_szx=0;
631  int ima_szy=0;
632 
633 
634  lam = (double)0.5*(ws+we);
635  dlam=we-ws;
636  sinfo_msg_debug("ws=%f we=%f dl=%f",ws,we,dlam);
637  check_nomsg(img_dup=cpl_image_duplicate(img));
638  sinfo_clean_nan(&img_dup);
639  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
640  sinfo_free_image(&img_dup);
641 
642  check_nomsg(ima_szx=cpl_image_get_size_x(img));
643  check_nomsg(ima_szy=cpl_image_get_size_y(img));
644  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
645  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
646  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
647  ima_szx,ima_szy);
648 
649  //cpl_image_get_maxpos_window(img,wllx,wlly,wurx,wury,&max_ima_x,&max_ima_y);
650  /*
651  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
652  wurx,wury));
653  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
654  wurx,wury));
655  */
656 
657  if(CPL_ERROR_NONE != sinfo_strehl_compute_one(img,
658  SINFO_STREHL_M1,
659  SINFO_STREHL_M2,
660  lam,
661  dlam,
662  pscale,
663  max_ima_x,
664  max_ima_y,
665  strehl_star_radius,
666  strehl_bg_r1,
667  strehl_bg_r2,
668  SINFO_STREHL_BOX_SIZE,
669  strehl,
670  strehl_err,
671  &star_bkg,
672  &star_peak,
673  &star_flux,
674  &psf_peak,
675  &psf_flux,
676  &bkg_noise)) {
677 
678 
679  *strehl=-1;
680  *strehl_err=0;
681  irplib_error_recover(clean_state,"Problem computing strehl");
682 
683  }
684 
685  return 0;
686 
687  cleanup:
688 
689  return -1;
690 
691 }
692 
693 
694 
695 
696 
697 
698 static int
699 sinfo_get_strehl_from_slice(cpl_imagelist* cube,
700  double disp,
701  double cWave,
702  double ws,
703  double we,
704  double pscale,
705  double strehl_star_radius,
706  double strehl_bg_r1,
707  double strehl_bg_r2,
708  double* strehl,
709  double* strehl_err)
710 {
711 
712 
713  cpl_errorstate clean_state = cpl_errorstate_get();
714 
715 
716  cpl_image* img_dup=NULL;
717  cpl_image* img=NULL;
718 
719  double dlam=0.;
720  double lam=0.;
721  /*
722  double max_ima_cx=0.;
723  double max_ima_cy=0.;
724  */
725  double psf_peak=0.;
726  double psf_flux=0.;
727  double bkg_noise=0.;
728  double star_bkg=0.;
729  double star_peak=0.;
730  double star_flux=0.;
731 
732  cpl_size max_ima_x=0;
733  cpl_size max_ima_y=0;
734  int wllx=0;
735  int wlly=0;
736  int wurx=0;
737  int wury=0;
738  int ima_szx=0;
739  int ima_szy=0;
740 
741 
742  lam = (double)0.5*(ws+we);
743  dlam=we-ws;
744 
745 
746  img=sinfo_new_average_cube_to_image_between_waves(cube,disp,cWave,ws,we);
747  check_nomsg(img_dup=cpl_image_duplicate(img));
748  sinfo_clean_nan(&img_dup);
749  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
750  check_nomsg(cpl_image_delete(img_dup));
751 
752 
753  check_nomsg(ima_szx=cpl_image_get_size_x(img));
754  check_nomsg(ima_szy=cpl_image_get_size_y(img));
755  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
756  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
757 
758 
759  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
760  ima_szx,ima_szy);
761 
762  /*
763  cpl_image_get_maxpos_window(img,wllx,wlly,wurx,wury,&max_ima_x,&max_ima_y);
764  */
765  /*
766  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
767  wurx,wury));
768 
769 
770 
771  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
772  wurx,wury));
773  */
774 
775  cpl_image_reject_value(img, CPL_VALUE_NAN);
776  if(CPL_ERROR_NONE != irplib_strehl_compute(img,
777  SINFO_STREHL_M1,
778  SINFO_STREHL_M2,
779  lam,
780  dlam,
781  pscale,
782  SINFO_STREHL_BOX_SIZE,
783  max_ima_x,
784  max_ima_y,
785  strehl_star_radius,
786  strehl_bg_r1,
787  strehl_bg_r2,
788  NOISE_HSIZE,
789  NOISE_NSAMPLES,
790  strehl,
791  strehl_err,
792  &star_bkg,
793  &star_peak,
794  &star_flux,
795  &psf_peak,
796  &psf_flux,
797  &bkg_noise)) {
798 
799 
800  *strehl=-1;
801  *strehl_err=0;
802  irplib_error_recover(clean_state,"Problem computing strehl");
803 
804  }
805 
806  /*
807  cpl_msg_info(__func__,"stehl=%f err=%f star_bkg=%f star_peak=%f star_flux=%f",
808  *strehl,*strehl_err,star_bkg,star_peak,star_flux);
809  cpl_msg_info(__func__,"psf_peak=%f psf_flux=%f bkg_noise=%f",
810  psf_peak,psf_flux,bkg_noise);
811  */
812  sinfo_free_image(&img);
813 
814 
815  return 0;
816 
817  cleanup:
818  return -1;
819 
820 }
821 
822 
823 
824 cpl_table* sinfo_get_encircled_energy(cpl_frameset* sof,
825  cpl_image* img,
826  double* fwhm_x,
827  double* fwhm_y,
828  cpl_table** qclog_tbl)
829 {
830 
831  cpl_errorstate clean_state = cpl_errorstate_get();
832 
833  cpl_image* img_dup=NULL;
834  cpl_size max_ima_x=0;
835  cpl_size max_ima_y=0;
836  int wllx=0;
837  int wlly=0;
838  int wurx=0;
839  int wury=0;
840  const double d_mirror = 8.;
841  const double factor = 180/PI_NUMB*3600.;
842  /*
843  double max_ima_cx=0;
844  double max_ima_cy=0;
845  */
846  double norm=0.;
847  double xc=0.;
848  double yc=0.;
849  double sx=0.;
850  double sy=0.;
851 
852  double flux=0;
853  double flux_max=1;
854  double pix_scale=0;
855  double lam=0.;
856  double pscale=0.;
857  int dr_difr=0;
858 
859  double r=0.;
860  double bkg=0.;
861  int i=0;
862  int ni=0;
863  int ir_difr=0;
864  int dr=0;
865  int rmin=0;
866 
867  char band[MAX_NAME_SIZE];
868  char spat_res[MAX_NAME_SIZE];
869 
870  cpl_table* enc_energy=NULL;
871  cpl_frame* frame=NULL;
872 
873  int ima_szx=0;
874  int ima_szy=0;
875 
876 
877 
878  if(NULL != cpl_frameset_find(sof,PRO_COADD_PSF)) {
879  frame = cpl_frameset_find(sof,PRO_COADD_PSF);
880  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_PSF)) {
881  frame = cpl_frameset_find(sof,PRO_OBS_PSF);
882  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_STD)) {
883  frame = cpl_frameset_find(sof,PRO_COADD_STD);
884  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_STD)) {
885  frame = cpl_frameset_find(sof,PRO_OBS_STD);
886  } else if(NULL != cpl_frameset_find(sof,PRO_COADD_OBJ)) {
887  frame = cpl_frameset_find(sof,PRO_COADD_OBJ);
888  } else if(NULL != cpl_frameset_find(sof,PRO_OBS_OBJ)) {
889  frame = cpl_frameset_find(sof,PRO_OBS_OBJ);
890  } else {
891  sinfo_msg_error("Frame %s or %s or %s or %s or %s or %s not found!",
892  PRO_COADD_PSF,PRO_OBS_PSF,
893  PRO_COADD_STD, PRO_OBS_STD,
894  PRO_COADD_OBJ, PRO_OBS_OBJ);
895  return NULL;
896  }
897 
898  sinfo_get_spatial_res(frame,spat_res);
899  sinfo_get_band(frame,band);
900  pix_scale=atof(spat_res);
901  lam=sinfo_get_wave_cent(band);
902  /* factor 2 due to change of detector to 2K */
903  pscale=0.5*pix_scale;
904 
905 
906 
907  dr_difr=factor*1.22*lam*1.e-6/d_mirror/pscale;
908  ir_difr=floor(dr_difr+0.5);
909  if (pix_scale==0.025) {
910  ni=10;
911  rmin=ir_difr;
912  dr=rmin;
913  } else {
914  ni=15;
915  sinfo_msg_warning("Reset diffraction limit");
916  ir_difr=10;
917  rmin=1;
918  dr=2;
919  }
920 
921  sinfo_msg("Diffraction limit: %d",ir_difr);
922 
923  check_nomsg(img_dup=cpl_image_duplicate(img));
924  sinfo_clean_nan(&img_dup);
925  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima_x,&max_ima_y));
926  sinfo_free_image(&img_dup);
927 
928 
929 
930  check_nomsg(ima_szx=cpl_image_get_size_x(img));
931  check_nomsg(ima_szy=cpl_image_get_size_y(img));
932  sinfo_check_borders(&max_ima_x,ima_szx,SINFO_STREHL_WINDOW);
933  sinfo_check_borders(&max_ima_y,ima_szy,SINFO_STREHL_WINDOW);
934  sinfo_get_safe_box(&wllx,&wlly,&wurx,&wury,max_ima_x,max_ima_y,SINFO_PSF_SZ,
935  ima_szx,ima_szy);
936  /*
937  check_nomsg(max_ima_cx=cpl_image_get_centroid_x_window(img,wllx,wlly,
938  wurx,wury));
939  check_nomsg(max_ima_cy=cpl_image_get_centroid_y_window(img,wllx,wlly,
940  wurx,wury));
941  */
942 
943  cpl_image_save(img, "bad_image_psf_c.fits",CPL_BPP_IEEE_DOUBLE, NULL, CPL_IO_CREATE);
944  sinfo_msg("@@@@ sinfo_get_encircled_energy() max_ima_x[%" CPL_SIZE_FORMAT "] max_ima_y[%" CPL_SIZE_FORMAT "] psf_sz[%d]", max_ima_x,
945  max_ima_y,
946  SINFO_PSF_SZ);
947 
948  if(CPL_ERROR_NONE != cpl_image_fit_gaussian(img,max_ima_x,max_ima_y,
949  SINFO_PSF_SZ,
950  &norm,&xc,&yc,&sx,&sy,
951  fwhm_x,fwhm_y)) {
952 
953 
954  irplib_error_recover(clean_state,"Gaussian fit failed");
955 
956  }
957 
958  check_nomsg(enc_energy = cpl_table_new(ni));
959  check_nomsg(cpl_table_new_column(enc_energy,"r_pix", CPL_TYPE_INT));
960  check_nomsg(cpl_table_new_column(enc_energy,"r_mas", CPL_TYPE_DOUBLE));
961  check_nomsg(cpl_table_new_column(enc_energy,"r_dif", CPL_TYPE_DOUBLE));
962  check_nomsg(cpl_table_new_column(enc_energy,"abs_energy" , CPL_TYPE_DOUBLE));
963  check_nomsg(cpl_table_new_column(enc_energy,"rel_energy" , CPL_TYPE_DOUBLE));
964 
965  /* encircled energy computation */
966  check_nomsg(bkg=irplib_strehl_ring_background(img,max_ima_x,max_ima_y,
967  SINFO_BKG_R1,SINFO_BKG_R2,IRPLIB_BG_METHOD_AVER_REJ)) ;
968  r=rmin+(ni-1)*dr;
969  cpl_image_reject_value(img, CPL_VALUE_NAN);
970  check_nomsg(flux_max=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
971  r=rmin;
972 
973  for(i=0; i<ni; i++)
974  {
975  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
976 
977  check_nomsg(cpl_table_set_int(enc_energy,"r_pix",i,r));
978  check_nomsg(cpl_table_set_double(enc_energy,"r_mas",i,r*pscale));
979  check_nomsg(cpl_table_set_double(enc_energy,"r_dif",i,r/ir_difr));
980  if(!isnan(flux)) {
981  check_nomsg(cpl_table_set_double(enc_energy,"abs_energy",i,flux));
982  } else {
983  check_nomsg(cpl_table_set_double(enc_energy,"abs_energy",i,-999));
984  }
985  r+=dr;
986  }
987  /* Because flux may be NAN we compute flux_max in two stages */
988  flux_max=cpl_table_get_column_max(enc_energy,"abs_energy");
989 
990  r=rmin;
991  for(i=0; i<ni; i++)
992  {
993  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,r,bkg));
994  if(!isnan(flux)) {
995  check_nomsg(cpl_table_set_double(enc_energy,"rel_energy",i,flux/flux_max));
996  } else {
997  check_nomsg(cpl_table_set_double(enc_energy,"rel_energy",i,1));
998  }
999  r+=dr;
1000  }
1001 
1002  //sinfo_msg("max ima=%d %d\n",max_ima_x,max_ima_y);
1003  //sinfo_msg("centroid ima=%f %f\n",max_ima_cx,max_ima_cy);
1004  //sinfo_msg("gauss info=%f %f %f %f %f %f %f\n",
1005  // norm,xc,yc,sx,sy,*fwhm_x,*fwhm_y);
1006 
1007 
1008  check_nomsg(flux=irplib_strehl_disk_flux(img,max_ima_x,max_ima_y,
1009  ir_difr,bkg));
1010  double enc_en=-999;
1011  if(!isnan(flux) && !isnan(flux_max)) {
1012  enc_en=flux/flux_max;
1013  }
1014  ck0_nomsg(sinfo_qclog_add_double(*qclog_tbl,"QC ENC CORE",
1015  enc_en,
1016  "Encircled energy within PSF core","%f"));
1017  return enc_energy;
1018 
1019  cleanup:
1020  sinfo_free_image(&img_dup);
1021 
1022  return NULL;
1023 }
1024 
1025 
1026 static cpl_table* sinfo_get_strehl_from_cube(cpl_imagelist* cube,
1027  char* name,
1028  cpl_frame* frame)
1029 {
1030  cpl_table* strehl_tbl=NULL;
1031 
1032  double dispersion=0.;
1033  double centralWave=0.;
1034  /* double wrange=0; */
1035  double wstart=0;
1036  double wstep=0;
1037  double wend=0;
1038  double ws=0;
1039  double we=0;
1040  double pix_scale=0;
1041  double lam=0;
1042  /* double dlam=0; */
1043  double pscale = 0;
1044 
1045  double strehl_star_radius=0;
1046  double strehl_bg_r1=0;
1047  double strehl_bg_r2=0;
1048  double strehl=0;
1049  double strehl_err=0;
1050  char spat_res[MAX_NAME_SIZE];
1051  cpl_propertylist* plist=NULL;
1052 
1053  /* int naxis3=0; */
1054  int nsample=0;
1055  int i=0;
1056 
1057 
1058  sinfo_get_spatial_res(frame,spat_res);
1059  pix_scale=atof(spat_res);
1060  sinfo_msg("Camera pixel scale=%f",pix_scale);
1061  /* factor 2 due to change of detector to 2K */
1062  pscale=0.5*pix_scale;
1063 
1064  strehl_star_radius=SINFO_BKG_R1*pscale;
1065  strehl_bg_r1=SINFO_BKG_R1*pscale;
1066  strehl_bg_r2=SINFO_BKG_R2*pscale;
1067 
1068  plist=cpl_propertylist_load(name,0);
1069  dispersion=sinfo_pfits_get_cdelt3(plist);
1070  centralWave=sinfo_pfits_get_crval3(plist);
1071  /* naxis3=sinfo_pfits_get_naxis3(plist); */
1072  sinfo_free_propertylist(&plist);
1073  /* wrange=dispersion*naxis3; */
1074 
1075  wstart = centralWave - (float) (cpl_imagelist_get_size(cube) / 2)*
1076  dispersion+dispersion;
1077  wend =wstart + dispersion * cpl_imagelist_get_size(cube);
1078  wstep=0.025;
1079  /*
1080  note:
1081  -wstep as we do not hit the borders where the
1082  sinfo_gaussian fit has a problem
1083  */
1084  nsample=(int)((wend-wstart-wstep)/wstep);
1085  check_nomsg(strehl_tbl = cpl_table_new(nsample));
1086  check_nomsg(cpl_table_new_column(strehl_tbl,"wavelength",CPL_TYPE_DOUBLE));
1087  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl",CPL_TYPE_DOUBLE));
1088  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl_error",CPL_TYPE_DOUBLE));
1089 
1090 
1091  for(i=1;i<nsample;i++) {
1092 
1093  ws=wstart+wstep*i;
1094  we=ws+wstep;
1095 
1096  lam = (double)0.5*(ws+we);
1097  /* dlam=wstep; */
1098 
1099  check(sinfo_get_strehl_from_slice(cube,
1100  dispersion,
1101  centralWave,
1102  ws,
1103  we,
1104  pscale,
1105  strehl_star_radius,
1106  strehl_bg_r1,
1107  strehl_bg_r2,
1108  &strehl,
1109  &strehl_err),"Error computing strehl");
1110 
1111 
1112  if((isnan(lam) ==0) &&
1113  (isnan(lam) ==0) &&
1114  (isnan(lam) ==0)) {
1115  check_nomsg(cpl_table_set_double(strehl_tbl,"wavelength",i,lam));
1116  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl",i,strehl));
1117  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl_error",i,
1118  strehl_err));
1119 
1120  }
1121  }
1122 
1123  return strehl_tbl;
1124 
1125  cleanup:
1126  return NULL;
1127 
1128 
1129 }
1130 
1131 
1132 static double
1133 sinfo_get_strehl_from_ima(cpl_image* ima,
1134  cpl_frame* frame)
1135 {
1136 
1137  double dispersion=0.;
1138  double centralWave=0.;
1139  double wstart=0;
1140  double wend=0;
1141  double pscale = 0;
1142 
1143  double strehl_star_radius=0;
1144  double strehl_bg_r1=0;
1145  double strehl_bg_r2=0;
1146  double strehl=0;
1147  double strehl_err=0;
1148  double exptime=0;
1149 
1150 
1151 
1152  ck0_nomsg(sinfo_get_strehl_input1(frame,&dispersion,&centralWave,
1153  &wstart,&wend,&pscale,&exptime,
1154  &strehl_star_radius,&strehl_bg_r1,
1155  &strehl_bg_r2));
1156 
1157 
1158  check(sinfo_get_strehl_from_image(ima,
1159  wstart,
1160  wend,
1161  pscale,
1162  strehl_star_radius,
1163  strehl_bg_r1,
1164  strehl_bg_r2,
1165  &strehl,
1166  &strehl_err),"Computing Strehl");
1167 
1168 
1169 
1170 
1171 
1172  cleanup:
1173  return strehl;
1174 
1175 
1176 }
1177 
1178 static int
1179 sinfo_get_frm12(cpl_frameset* sof,cpl_frame** frm1,cpl_frame** frm2){
1180 
1181  cpl_frameset* obs=NULL;
1182  int nobs=0;
1183  float eps=0.0001;
1184  float* pix_scale=NULL;
1185  int i=0;
1186  cpl_frame* frame=NULL;
1187 
1188  obs = cpl_frameset_new();
1189  sinfo_contains_frames_kind(sof,obs,PRO_OBS_PSF);
1190  nobs=cpl_frameset_get_size(obs);
1191  if (nobs < 1) {
1192  sinfo_contains_frames_kind(sof,obs,PRO_OBS_STD);
1193  nobs=cpl_frameset_get_size(obs);
1194  }
1195 
1196  nobs=cpl_frameset_get_size(obs);
1197 
1198 
1199  if (nobs < 1) {
1200  sinfo_contains_frames_kind(sof,obs,PRO_OBS_OBJ);
1201  nobs=cpl_frameset_get_size(obs);
1202  }
1203 
1204  nobs=cpl_frameset_get_size(obs);
1205 
1206  if (nobs < 1) {
1207  return -1;
1208  } else {
1209  pix_scale=cpl_calloc(nobs,sizeof(float));
1210  for(i=0;i<nobs;i++) {
1211  frame=cpl_frameset_get_frame(obs,i);
1212  pix_scale[i]=sinfo_pfits_get_pixelscale(
1213  (char*)cpl_frame_get_filename(frame));
1214  if(fabs(pix_scale[i]-0.025)< eps) {
1215  *frm1=cpl_frame_duplicate(frame);
1216  } else if (fabs(pix_scale[i]-0.1) <eps) {
1217  *frm2=cpl_frame_duplicate(frame);
1218  } else {
1219  sinfo_msg_error("No proper frame found for strehl computation");
1220  return -1;
1221  }
1222  }
1223  }
1224  cpl_free(pix_scale);
1225  cpl_frameset_delete(obs);
1226 
1227  return 0;
1228 
1229 }
1230 
1231 
1232 
1233 
1234 static int
1235 sinfo_get_strehl_input1(cpl_frame* frm,
1236  double* dispersion,
1237  double* centralWave,
1238  double* wstart,
1239  double* wend,
1240  double* pscale,
1241  double* exptime,
1242  double* strehl_star_rad,
1243  double* strehl_bg_rmin,
1244  double* strehl_bg_rmax)
1245 
1246 {
1247 
1248  cpl_propertylist* plist=NULL;
1249  char res[MAX_NAME_SIZE];
1250  double pix_scale=0;
1251  double wrange=0;
1252  char fname[MAX_NAME_SIZE];
1253  int naxis3=0;
1254 
1255  sinfo_get_spatial_res(frm,res);
1256  pix_scale=atof(res);
1257 
1258  /* factor 2 due to change of detector to 2K
1259  *pscale=0.5*pix_scale;
1260  */
1261 
1262 
1263  *pscale=pix_scale;
1264 
1265  *strehl_star_rad=SINFO_RSTAR*(*pscale);
1266  *strehl_bg_rmin=SINFO_BKG_R1*(*pscale);
1267  *strehl_bg_rmax=SINFO_BKG_R2*(*pscale);
1268 
1269  strcpy(fname,cpl_frame_get_filename(frm));
1270  check_nomsg(plist=cpl_propertylist_load(fname,0));
1271  check_nomsg(*dispersion=sinfo_pfits_get_cdelt3(plist));
1272  *centralWave=sinfo_pfits_get_crval3(plist);
1273  check_nomsg(naxis3=sinfo_pfits_get_naxis3(plist));
1274  *exptime=sinfo_pfits_get_exp_time(plist);
1275  sinfo_free_propertylist(&plist);
1276 
1277  wrange=(*dispersion)*naxis3;
1278 
1279  *wstart = *centralWave - (wrange / 2) +(*dispersion);
1280  *wend = *wstart + wrange;
1281 
1282 
1283  cleanup:
1284  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1285  return -1;
1286  } else {
1287  return 0;
1288  }
1289 
1290 }
1291 
1292 
1293 static int
1294 sinfo_get_strehl_input2(cpl_frame* frm1,
1295  cpl_frame* frm2,
1296  double* dispersion,
1297  double* centralWave,
1298  double* wstart,
1299  double* wend,
1300  double* pscale1,
1301  double* pscale2,
1302  double* exptime1,
1303  double* exptime2,
1304  double* strehl_star_rad1,
1305  double* strehl_star_rad2,
1306  double* strehl_bg_rmin1,
1307  double* strehl_bg_rmin2,
1308  double* strehl_bg_rmax1,
1309  double* strehl_bg_rmax2)
1310 
1311 {
1312 
1313  cpl_propertylist* plist=NULL;
1314  char res1[MAX_NAME_SIZE];
1315  char res2[MAX_NAME_SIZE];
1316  double pix_scale1=0;
1317  double pix_scale2=0;
1318  double wrange=0;
1319  char fname1[MAX_NAME_SIZE];
1320  char fname2[MAX_NAME_SIZE];
1321  int naxis3=0;
1322 
1323  sinfo_get_spatial_res(frm1,res1);
1324  sinfo_get_spatial_res(frm2,res2);
1325  pix_scale1=atof(res1);
1326  pix_scale2=atof(res2);
1327  /* factor 2 due to change of detector to 2K
1328  *pscale1=0.5*pix_scale1;
1329  *pscale2=0.5*pix_scale2;
1330  */
1331 
1332  *pscale1=pix_scale1;
1333  *pscale2=pix_scale2;
1334 
1335 
1336  *strehl_star_rad1=SINFO_RSTAR*(*pscale1);
1337  *strehl_bg_rmin1=SINFO_BKG_R1*(*pscale1);
1338  *strehl_bg_rmax1=SINFO_BKG_R2*(*pscale1);
1339 
1340  *strehl_star_rad2=SINFO_RSTAR*(*pscale2);
1341  *strehl_bg_rmin2=SINFO_BKG_R1*(*pscale2);
1342  *strehl_bg_rmax2=SINFO_BKG_R2*(*pscale2);
1343 
1344  strcpy(fname1,cpl_frame_get_filename(frm1));
1345  check_nomsg(plist=cpl_propertylist_load(fname1,0));
1346  check_nomsg(*dispersion=sinfo_pfits_get_cdelt3(plist));
1347  *centralWave=sinfo_pfits_get_crval3(plist);
1348  check_nomsg(naxis3=sinfo_pfits_get_naxis3(plist));
1349  *exptime1=sinfo_pfits_get_exp_time(plist);
1350  sinfo_free_propertylist(&plist);
1351  strcpy(fname2,cpl_frame_get_filename(frm2));
1352 
1353 
1354  check_nomsg(plist=cpl_propertylist_load(fname2,0));
1355  *exptime2=sinfo_pfits_get_exp_time(plist);
1356  sinfo_free_propertylist(&plist);
1357 
1358 
1359 
1360  wrange=(*dispersion)*naxis3;
1361 
1362  *wstart = *centralWave - (wrange / 2) +(*dispersion);
1363  *wend = *wstart + wrange;
1364 
1365 
1366  cleanup:
1367  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1368  return -1;
1369  } else {
1370  return 0;
1371  }
1372 
1373 }
1374 
1375 
1376 
1377 static cpl_table*
1378 sinfo_get_strehl_from_2images(cpl_image* ima1,
1379  cpl_image* ima2,
1380  cpl_frame* frm1,
1381  cpl_frame* frm2)
1382 {
1383 
1384  cpl_table* strehl_tbl=NULL;
1385 
1386 
1387  double dispersion=0.;
1388  double centralWave=0.;
1389  double wstart=0;
1390  double wstep=0;
1391  double wend=0;
1392  double lam=0;
1393  double dlam=0;
1394  double pscale1 = 0;
1395  double pscale2 = 0;
1396 
1397  double strehl_star_rad1=0;
1398  double strehl_star_rad2=0;
1399  double strehl_bg_rmin1=0;
1400  double strehl_bg_rmin2=0;
1401  double strehl_bg_rmax1=0;
1402  double strehl_bg_rmax2=0;
1403  double strehl=0;
1404  double strehl_err=0;
1405 
1406  int nsample=1;
1407  double exptime1=0;
1408  double exptime2=0;
1409  cpl_image* img_dup=NULL;
1410 
1411  cpl_size max_ima1_x=0;
1412  cpl_size max_ima1_y=0;
1413 
1414  cpl_size max_ima2_x=0;
1415 
1416 
1417  cpl_size max_ima2_y=0;
1418  double star_bkg=0;
1419  double star_peak=0;
1420  double star_flux=0;
1421 
1422  double psf_peak=0;
1423  double psf_flux=0;
1424  double bkg_noise=0;
1425 
1426  cpl_errorstate clean_state = cpl_errorstate_get();
1427 
1428  ck0_nomsg(sinfo_get_strehl_input2(frm1,frm2,&dispersion, &centralWave,
1429  &wstart,&wend,&pscale1,&pscale2,
1430  &exptime1,&exptime2,
1431  &strehl_star_rad1,&strehl_star_rad2,
1432  &strehl_bg_rmin1,&strehl_bg_rmin2,
1433  &strehl_bg_rmax1,&strehl_bg_rmax2));
1434 
1435 
1436 
1437 
1438 
1439  check_nomsg(img_dup=cpl_image_duplicate(ima1));
1440  sinfo_clean_nan(&img_dup);
1441  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima1_x,&max_ima1_y));
1442  sinfo_free_image(&img_dup);
1443 
1444 
1445  check_nomsg(img_dup=cpl_image_duplicate(ima2));
1446  sinfo_clean_nan(&img_dup);
1447  check_nomsg(cpl_image_get_maxpos(img_dup,&max_ima2_x,&max_ima2_y));
1448  sinfo_free_image(&img_dup);
1449 
1450  /*
1451  note:
1452  -wstep as we do not hit the borders where the
1453  sinfo_gaussian fit has a problem
1454  */
1455 
1456 
1457 
1458  check_nomsg(strehl_tbl = cpl_table_new(nsample));
1459  check_nomsg(cpl_table_new_column(strehl_tbl,"wavelength",CPL_TYPE_DOUBLE));
1460  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl",CPL_TYPE_DOUBLE));
1461  check_nomsg(cpl_table_new_column(strehl_tbl,"strehl_error",CPL_TYPE_DOUBLE));
1462  wstep = wend-wstart;
1463 
1464 
1465 
1466  lam = (double)0.5*(wstart+wend);
1467  dlam=wstep;
1468  sinfo_msg("lambda=%f dlambda=%f",lam,dlam);
1469  sinfo_msg("wstart=%f wend=%f",wstart,wend);
1470  sinfo_msg("wstep=%f",wstep);
1471 
1472 
1473  if(CPL_ERROR_NONE != sinfo_strehl_compute_two(ima1,ima2,
1474  SINFO_STREHL_M1,SINFO_STREHL_M2,
1475  lam,
1476  pscale1,pscale2,
1477  exptime1,exptime2,
1478  max_ima1_x,max_ima1_y,
1479  max_ima2_x,max_ima2_y,
1480  strehl_star_rad1,
1481  strehl_bg_rmin1,
1482  strehl_bg_rmax1,
1483  &strehl,&strehl_err,&star_bkg,
1484  &star_peak,&star_flux,
1485  &psf_peak,&psf_flux,&bkg_noise))
1486  {
1487 
1488  strehl=-1;
1489  strehl_err=0;
1490  irplib_error_recover(clean_state,
1491  "Problem computing strehl, set it to -1");
1492 
1493  }
1494 
1495 
1496  if((isnan(lam) ==0) &&
1497  (isnan(lam) ==0) &&
1498  (isnan(lam) ==0)) {
1499  check_nomsg(cpl_table_set_double(strehl_tbl,"wavelength",0,lam));
1500  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl",0,strehl));
1501  check_nomsg(cpl_table_set_double(strehl_tbl,"strehl_error",
1502  0,strehl_err));
1503 
1504  }
1505 
1506 
1507 
1508  return strehl_tbl;
1509  cleanup:
1510 
1511 
1512  return NULL;
1513 }
1514 
1515 
1516 
1517 /*---------------------------------------------------------------------------*/
1552 /*---------------------------------------------------------------------------*/
1553 #define irplib_assure_code cpl_ensure_code
1554 int sinfo_strehl_compute_two(
1555  const cpl_image * im1,
1556  const cpl_image * im2,
1557  double m1,
1558  double m2,
1559  double lam,
1560  double pscale1,
1561  double pscale2,
1562  double exptime1,
1563  double exptime2,
1564  int xpos1,
1565  int ypos1,
1566  int xpos2,
1567  int ypos2,
1568  double r1,
1569  double r2,
1570  double r3,
1571  double * strehl,
1572  double * strehl_err,
1573  double * star_bkg,
1574  double * star_peak,
1575  double * star_flux,
1576  double * psf_peak,
1577  double * psf_flux,
1578  double * bg_noise)
1579 {
1580  double psf_peak1=0;
1581  double psf_peak2=0;
1582  /*
1583  double psf_flux1=0;
1584  double psf_flux2=0;
1585  */
1586  double star_bkg1=0;
1587  double star_bkg2=0;
1588  double star_flux1=0;
1589  double star_flux2=0;
1590  double star_peak1=0;
1591  double star_peak2=0;
1592 
1593  const double window_size = 5.0 ;
1594  //double star_radius;
1595  //double max_radius ;
1596  double ring[4];
1597 
1598  double prat=pscale2/pscale1;
1599  double prat2=prat*prat;
1600  double trat=exptime1/exptime2;
1601  double frat=sinfo_scale_flux(pscale1,pscale2,exptime1,exptime2);
1602  double xc=0;
1603  double yc=0;
1604  /*
1605  int sx=0;
1606  int sy=0;
1607  */
1608  int d=16;
1609  cpl_errorstate initial_errorstate = cpl_errorstate_get();
1610 
1611 
1612  /* Test inputs */
1613  irplib_assure_code(im1 != NULL, CPL_ERROR_NULL_INPUT);
1614  irplib_assure_code(im2 != NULL, CPL_ERROR_NULL_INPUT);
1615  irplib_assure_code(strehl != NULL, CPL_ERROR_NULL_INPUT);
1616  irplib_assure_code(strehl_err != NULL, CPL_ERROR_NULL_INPUT);
1617  irplib_assure_code(star_bkg != NULL, CPL_ERROR_NULL_INPUT);
1618  irplib_assure_code(star_peak != NULL, CPL_ERROR_NULL_INPUT);
1619  irplib_assure_code(star_flux != NULL, CPL_ERROR_NULL_INPUT);
1620  irplib_assure_code(psf_peak != NULL, CPL_ERROR_NULL_INPUT);
1621  irplib_assure_code(psf_flux != NULL, CPL_ERROR_NULL_INPUT);
1622 
1623  irplib_assure_code(pscale1 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1624  irplib_assure_code(pscale2 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1625 
1626  irplib_assure_code(xpos1-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1627  irplib_assure_code(ypos1-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1628  irplib_assure_code(xpos2-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1629  irplib_assure_code(ypos2-window_size > 0, CPL_ERROR_ACCESS_OUT_OF_RANGE);
1630 
1631  irplib_assure_code(xpos1+window_size <= cpl_image_get_size_x(im1),
1632  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1633  irplib_assure_code(ypos1+window_size <= cpl_image_get_size_y(im1),
1634  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1635 
1636  irplib_assure_code(xpos2+window_size <= cpl_image_get_size_x(im2),
1637  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1638  irplib_assure_code(ypos2+window_size <= cpl_image_get_size_y(im2),
1639  CPL_ERROR_ACCESS_OUT_OF_RANGE);
1640 
1641  irplib_assure_code(r1 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1642  irplib_assure_code(r2 > 0.0, CPL_ERROR_ILLEGAL_INPUT);
1643  irplib_assure_code(r3 > r2, CPL_ERROR_ILLEGAL_INPUT);
1644 
1645  /* Computing a Strehl ratio is a story between an ideal PSF */
1646  /* and a candidate image supposed to approximate this ideal PSF. */
1647 
1648  /* Generate first appropriate PSF to find max peak: same pscale as
1649  the one of the image where we compute the flux */
1650 
1651  /*
1652  sx=cpl_image_get_size_x(im1);
1653  sy=cpl_image_get_size_y(im1);
1654  */
1655 
1656  /* psf_flux1 = 1.0; // The psf flux, cpl_image_get_flux(psf), is always 1 */
1657  /* psf_flux2 = 1.0; // The psf flux, cpl_image_get_flux(psf), is always 1 */
1658  *psf_flux=1.0;
1659  ring[0] = xpos2;
1660  ring[1] = ypos2;
1661  ring[2] = r2/pscale2;
1662  ring[3] = r3/pscale2;
1663 
1664  sinfo_msg_debug("star_pos=%d %d %d %d",xpos1,ypos1,xpos2,ypos2);
1665  sinfo_msg_debug("star_ring=%f %f %f %f",ring[0],ring[1],ring[2],ring[3]);
1666 
1667  /* Compute star_radius in pixels */
1668  //star_radius = r1/pscale2;
1669 
1670  /* Find the peak value on the central part of the candidate image */
1671 
1672 
1673  /* Find the peak value on the central part of the candidate image */
1674  //max_radius = window_size < star_radius ? window_size : star_radius;
1675 
1676  check_nomsg(sinfo_get_star_features(im1,d,xpos1,ypos1,&xc,&yc,
1677  &star_peak1,&star_flux1,&star_bkg1));
1678 
1679 
1680  *star_peak=star_peak1;
1681 
1682  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale1,xc,yc,1.,
1683  &psf_peak1));
1684 
1685  check_nomsg(sinfo_get_star_features(im2,d,xpos2,ypos2,&xc,&yc,
1686  &star_peak2,&star_flux2,&star_bkg2));
1687 
1688  *star_flux=star_flux2;
1689  *star_bkg=star_bkg2;
1690 
1691  check_nomsg(sinfo_compute_psf(m1,m2/m1,lam*1.e-6,pscale2,xc,yc,1.,
1692  &psf_peak2));
1693 
1694 
1695 
1696 
1697  sinfo_msg_debug("p1=%g p2=%g",*star_peak,star_peak2);
1698  sinfo_msg_debug("corr peak: p1=%g p2=%g",*star_peak,star_peak2/frat);
1699  sinfo_msg_debug("corr bkg: bkg1=%g bkg2=%g",star_bkg1/frat,*star_bkg);
1700  sinfo_msg_debug("rel diff: %g",
1701  fabs(star_peak2/frat- *star_peak)/(star_peak2/frat));
1702 
1703 
1704 
1705  sinfo_msg_debug("Rescaled star_flux1=%g star_flux2=%g",
1706  star_flux1*trat,*star_flux);
1707 
1708  //Check that flux value as measured on im1 and on 1m2 are close one
1709  //to another. Note that flux1, measured on im1, need to be rescaled
1710  //by exposure time to match to flux2=star_flux
1711  if ( fabs((star_flux1*frat-*star_flux)/(*star_flux)) > 0.25) {
1712  sinfo_msg_debug("Star flux rel diff: %g",
1713  fabs((star_flux1*frat-*star_flux)/(*star_flux)));
1714  }
1715 
1716  //Check that pick value as measured on im1 and on 1m2 are close one
1717  //to another. Note that peak2, measured on im2, need to be rescaled
1718  //by exposure time and pixel scale to match to peak1=star_peak
1719  if ( fabs(star_peak2-star_peak1*frat)/(star_peak2) > 0.25) {
1720  sinfo_msg_debug("Star pick rel diff: %g",
1721  fabs(star_peak2-star_peak1*frat)/(star_peak2));
1722  }
1723  sinfo_msg_debug("ak1 star peak=%g",*star_peak);
1724  irplib_assure_code(*star_peak > 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
1725  *star_peak=star_peak1;
1726 
1727  *star_bkg=star_bkg2;
1728  *star_flux=star_flux2;
1729 
1730  sinfo_msg_debug("ak2");
1731 
1732  //psf1 = irplib_strehl_generate_psf(m1, m2, lam, dlam, pscale1, size*4);
1733  //psf_peak1 = cpl_image_get_max(psf1) ;
1734 
1735 
1736 
1737  /* Compute Strehl */
1738  //*strehl = (*star_peak *prat2/trat/ *star_flux) / (*psf_peak / *psf_flux);
1739  *strehl = (*star_peak/(*star_flux*trat)) / (psf_peak1 );
1740  //*strehl = (*star_peak/(*star_flux)) / (psf_peak1 / *psf_flux) ;
1741  sinfo_msg_debug("peak=%g flux1=%f flux2=%f flux=%f cflux=%g "
1742  "fct=%g psf_peak=%g",
1743  *star_peak,star_flux1,star_flux2,*star_flux,
1744  *star_flux/frat*prat2,prat2/frat,psf_peak1);
1745  sinfo_msg_debug("=======strehl=%g",*strehl);
1746  /*
1747  if (*strehl > 1)
1748  cpl_msg_warning(cpl_func, "Extreme Strehl-ratio=%g, star_peak=%g, "
1749  "star_flux=%g, psf_peak=%g, psf_flux=%g", *strehl,
1750  *star_peak, *star_flux, *psf_peak, *psf_flux);
1751 
1752 
1753  // Compute Strehl error
1754  if (cpl_flux_get_noise_ring(im2, ring, noise_box_sz, noise_nsamples,
1755  bg_noise, NULL) == CPL_ERROR_NONE) {
1756  *strehl_err = SINFO_STREHL_ERROR_COEFFICIENT * (*bg_noise) * pscale2 *
1757  star_radius * star_radius / *star_flux;
1758  irplib_assure_code(*strehl_err >= 0.0, CPL_ERROR_ILLEGAL_OUTPUT);
1759  } else {
1760  sinfo_msg_warning("Problem computing noise");
1761  }
1762  */
1763  *bg_noise=0;
1764 
1765  cleanup:
1766 
1767 
1768  if (!cpl_errorstate_is_equal(initial_errorstate)) {
1769  /* Dump the error history since recipe execution start.
1770  At this point the recipe cannot recover from the error */
1771  cpl_errorstate_dump(initial_errorstate, CPL_FALSE, NULL);
1772  }
1773 
1774  if (cpl_error_get_code() != CPL_ERROR_NONE) {
1775  return cpl_error_get_code();
1776  } else {
1777  return CPL_ERROR_NONE;
1778  }
1779 
1780 }
1781 
1782 
1783 
1784 
1785 static cpl_error_code
1786 sinfo_get_star_features(const cpl_image* im,
1787  const int radius,
1788  const int xpos,
1789  const int ypos,
1790  double* xc,
1791  double* yc,
1792  double* peak,
1793  double* flux,
1794  double* bkg)
1795 {
1796  int sx=0;
1797  int sy=0;
1798  int ixm=0;
1799  int iym=0;
1800  int llx=0;
1801  int lly=0;
1802  int urx=0;
1803  int ury=0;
1804  int dim_new=0;
1805  double kappa=2;
1806  double xm=0;
1807  double ym=0;
1808  double bkg_stdev=0;
1809  int bkg_sx=SINFO_BKG_BOX_SZ;
1810  int bkg_sy=SINFO_BKG_BOX_SZ;
1811 
1812  cpl_bivector* iqe=NULL;
1813  double* piqe=NULL;
1814  cpl_image* im_new=NULL;
1815 
1816  sx=cpl_image_get_size_x(im);
1817  sy=cpl_image_get_size_y(im);
1818 
1819  sinfo_msg_debug("star_radius=%d",radius);
1820  //We find the image centroid
1821  if(NULL != (iqe=cpl_image_iqe(im,sx/2-radius,sy/2-radius,
1822  sx/2+radius,sy/2+radius))) {
1823 
1824 
1825  piqe=cpl_bivector_get_x_data(iqe);
1826  //*star_peak=piqe[5];
1827  xm=piqe[0];
1828  ym=piqe[1];
1829  //Extract a square sub-image of minimal size not to hit the image borders
1830  //centered on the previous image centroid
1831  sinfo_msg_debug("Max ima: %g %g",xm,ym);
1832  sinfo_msg_debug("Find min of: %g %g %g %g",xm,sx-xm,ym,sy-ym);
1833  ixm=floor(xm);
1834  iym=floor(ym);
1835  sinfo_msg_debug("ixm=%d iym=%d",ixm,iym);
1836  dim_new=floor(sinfo_find_min_of_four(xm,sx-xm,ym,sy-ym));
1837  sinfo_msg_debug("dim_new=%d",dim_new);
1838  llx=(ixm-dim_new > 1) ? ixm-dim_new : 1;
1839  lly=(iym-dim_new > 1) ? iym-dim_new : 1;
1840  urx=(ixm+dim_new < sx) ? ixm+dim_new : sx;
1841  ury=(iym+dim_new < sy) ? iym+dim_new : sy;
1842  sinfo_msg_debug("llx=%d lly=%d urx=%d ury=%d",llx,lly,urx,ury);
1843  check_nomsg(im_new=cpl_image_extract(im,llx,lly,urx,ury));
1844 
1845  //compute the background of this last image
1846  check_nomsg(sinfo_get_bkg_4corners(im_new,bkg_sx,bkg_sy,bkg,&bkg_stdev));
1847 
1848 
1849 
1850  sinfo_free_bivector(&iqe);
1851 
1852  //Determine the image pick on the new coordinate system
1853  iqe=cpl_image_iqe(im_new,dim_new-radius,dim_new-radius,
1854  dim_new+radius,dim_new+radius);
1855  piqe=cpl_bivector_get_x_data(iqe);
1856  sinfo_msg_debug("xc=%g yc=%g",piqe[0],piqe[1]);
1857  *xc=piqe[0]-dim_new-1;
1858  *yc=piqe[1]-dim_new-1;
1859 
1860 
1861  sinfo_msg_debug("xc=%g yc=%g",*xc,*yc);
1862  //*peak=piqe[5];
1863  *peak=cpl_image_get_max_window(im_new,dim_new-radius,dim_new-radius,
1864  dim_new+radius,dim_new+radius);
1865 
1866  sinfo_get_flux_above_bkg(im_new,kappa,bkg_stdev,flux);
1867  *peak -= (*bkg);
1868  sinfo_msg_debug("star peak=%g bkg=%g",*peak,*bkg);
1869 
1870 
1871  sinfo_free_bivector(&iqe);
1872 
1873 
1874  } else {
1875  sinfo_msg_warning("IQE fit failed");
1876  cpl_error_reset();
1877  sinfo_msg_debug("xc=%d yc=%d radius=%d",xpos,ypos,radius);
1878  *xc=xpos-sx/2;
1879  *yc=ypos-sy/2;
1880  sinfo_msg_debug("xc=%g yc=%g",*xc,*yc);
1881  check_nomsg(sinfo_get_bkg_4corners(im,bkg_sx,bkg_sy,bkg,&bkg_stdev));
1882  check_nomsg(sinfo_get_safe_box(&llx, &lly, &urx, &ury, xpos,ypos,radius,
1883  64,64));
1884  check_nomsg(*peak=cpl_image_get_max_window(im,llx,lly,urx,ury)-(*bkg));
1885  sinfo_get_flux_above_bkg(im,kappa,bkg_stdev,flux);
1886  sinfo_msg_debug("star peak=%g bkg=%g",*peak,*bkg);
1887 
1888 
1889  }
1890 
1891 
1892 
1893  cleanup:
1894  sinfo_free_image(&im_new);
1895  sinfo_free_bivector(&iqe);
1896 
1897 
1898 
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;
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_bkg);
2177 
2178  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2179  return cpl_error_get_code();
2180  } else {
2181  return CPL_ERROR_NONE;
2182  }
2183 
2184 
2185 }
2186 
2199 /*---------------------------------------------------------------------------*/
2200 cpl_error_code
2201 sinfo_compute_psf(const double dia,
2202  const double occ,
2203  const double lambda,
2204  const double psize,
2205  const double cx,
2206  const double cy,
2207  const double anamorph,
2208  double* psf_peak)
2209 {
2210 
2211  int bin=SINFO_PSF_BIN;
2212  int npoints=SINFO_PSF_NPOINT;
2213 
2214  int dim=SINFO_PSF_DIM;
2215  int blocks=SINFO_PSF_BLOCKS;
2216  int sx=dim;
2217  int sy=dim;
2218 
2219 
2220  int i=0;
2221  int j=0;
2222  double k=0;
2223 
2224  int ii=0;
2225  int jj=0;
2226  int start=0;
2227 
2228  double nyquist=lambda/dia/2.*206265/psize*bin;
2229  double cor=0.;
2230  double v0=0;
2231  double ll[npoints];
2232  double part[npoints];
2233  double ee;
2234  double dll=0;
2235  double tot1=0;
2236  double tot2=0;
2237 
2238 
2239  double fct=0;
2240 
2241  double* pxx=NULL;
2242  double* pyy=NULL;
2243  double* prr=NULL;
2244  double* ppsf0=NULL;
2245 
2246  double* pcor=NULL;
2247  double* pairy=NULL;
2248  /* double* pw=NULL; */
2249 
2250  cpl_image* img_xx=NULL;
2251  cpl_image* img_yy=NULL;
2252  cpl_image* img_rr=NULL;
2253  cpl_image* img_rrcor=NULL;
2254  cpl_image* img_airy=NULL;
2255  cpl_image* img_w=NULL;
2256  cpl_image* img_psf0=NULL;
2257 
2258 
2259 
2260  sinfo_msg_debug("lambda=%g",lambda);
2261  sinfo_msg_debug("dia=%f",dia);
2262  sinfo_msg_debug("psize=%f",psize);
2263  sinfo_msg_debug("bin=%d",bin);
2264  sinfo_msg_debug("nyquist=%f",nyquist);
2265 
2266  check_nomsg(img_xx=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE));
2267  img_yy=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2268  img_rr=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2269  //img_rrcor=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2270 
2271  pxx=cpl_image_get_data_double(img_xx);
2272  pyy=cpl_image_get_data_double(img_yy);
2273  prr=cpl_image_get_data_double(img_rr);
2274 
2275  for(j=0;j<sy;j++) {
2276  for(i=0;i<sx;i++) {
2277  //xz plane increasing along y
2278  pxx[j*sx+i]=(i-sx/2-cx*bin)/nyquist*SINFO_MATH_PI/2;
2279  //yz plane increasing along x
2280  pyy[j*sx+i]=(j-sy/2-cy*bin)/nyquist*SINFO_MATH_PI/2*anamorph;
2281 
2282  //combinex xyz surface
2283  prr[j*sx+i]=sqrt(pxx[j*sx+i]*pxx[j*sx+i]+pyy[j*sx+i]*pyy[j*sx+i]);
2284  }
2285  }
2286 
2287  /*
2288  check_nomsg(cpl_image_save(img_xx,"out_xx.fits", CPL_BPP_IEEE_DOUBLE,
2289  NULL,CPL_IO_DEFAULT));
2290 
2291  check_nomsg(cpl_image_save(img_yy,"out_yy.fits", CPL_BPP_IEEE_DOUBLE,
2292  NULL,CPL_IO_DEFAULT));
2293 
2294  check_nomsg(cpl_image_save(img_rr,"out_rr.fits", CPL_BPP_IEEE_DOUBLE,
2295  NULL,CPL_IO_DEFAULT));
2296 
2297  */
2298 
2299  //img_rrcor=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2300 
2301  cor=1./(1.-occ*occ);
2302  cor*=cor;
2303 
2304  img_rrcor=cpl_image_duplicate(img_rr);
2305  cpl_image_multiply_scalar(img_rrcor,cor);
2306  pcor=cpl_image_get_data_double(img_rrcor);
2307 
2308  /*
2309  check_nomsg(cpl_image_save(img_rrcor,"out_rrcor.fits", CPL_BPP_IEEE_DOUBLE,
2310  NULL,CPL_IO_DEFAULT));
2311  */
2312 
2313  img_airy=cpl_image_new(sx,sy,CPL_TYPE_DOUBLE);
2314  pairy=cpl_image_get_data_double(img_airy);
2315 
2316 
2317  if (occ == 0.0) {
2318 
2319  for(j=0;j<sx;j++) {
2320  for(i=0;i<sy;i++) {
2321  fct=(2.*j1(prr[j*sx+i])/prr[j*sx+i]);
2322  pairy[j*sx+i]=fct*fct;
2323 
2324  }
2325  }
2326 
2327  } else {
2328  for(j=0;j<sy;j++) {
2329  for(i=0;i<sx;i++) {
2330 
2331  fct=(2.*j1(prr[j*sx+i])/prr[j*sx+i]-occ*occ*2.*j1(pcor[j*sx+i])/pcor[j*sx+i]);
2332  pairy[j*sx+i]=cor*fct*fct;
2333 
2334  }
2335  }
2336  }
2337 
2338  /*
2339  check_nomsg(cpl_image_save(img_airy,"out_airy.fits", CPL_BPP_IEEE_DOUBLE,
2340  NULL,CPL_IO_DEFAULT));
2341 
2342  */
2343 
2344  //To remove an expected NAN value at the PSF centre we re-set PSF(centre)=1
2345  img_w=cpl_image_duplicate(img_airy);
2346  /* pw=cpl_image_get_data_double(img_w); */
2347  pairy=cpl_image_get_data_double(img_airy);
2348 
2349  for(j=0;j<sy;j++) {
2350  for(i=0;i<sx;i++) {
2351  if(!irplib_isnan(pairy[i+j*sx]) && (pairy[i+j*sx] ==0)) {
2352  pairy[i+j*sx]=1.;
2353  sinfo_msg_debug("====> %f",pairy[i+j*sx]);
2354  }
2355  }
2356  }
2357  pairy[sx/2+sy/2*sx]=1.;
2358 
2359  sinfo_msg_debug("total-airy=%f",cpl_image_get_flux(img_airy));
2360 
2361  /*
2362  check_nomsg(cpl_image_save(img_airy,"out_airy1.fits", CPL_BPP_IEEE_DOUBLE,
2363  NULL,CPL_IO_DEFAULT));
2364 
2365  */
2366 
2367 
2368  // Computation of EE
2369 
2370 
2371  v0=prr[0+dim/4-1];
2372  sinfo_msg_debug("v0=%12.10g",v0);
2373  for(i=0;i<npoints;i++) {
2374  ll[i]=(double)i/npoints*v0;
2375  }
2376  dll=ll[1]-ll[0];
2377  cor=1./(1.-occ*occ);
2378 
2379  for(i=0;i<npoints;i++) {
2380  part[i]=2.*j1(ll[i])/ll[i];
2381  }
2382  part[0]=1.0;
2383 
2384  tot1=0.;
2385  for(i=0;i<npoints;i++) {
2386  tot1+=j1(occ*ll[i])*part[i]*dll;
2387  }
2388  sinfo_msg_debug("tot=%10.8f",tot1);
2389 
2390 
2391  sinfo_msg_debug("cor=%10.8f",cor);
2392 
2393  ee=(1.-j0(v0)*j0(v0));
2394 
2395  sinfo_msg_debug("(1-j0(v0)*j0(v0))=%10.8f",ee);
2396 
2397 
2398  ee-=(j1(v0))*(j1(v0));
2399  sinfo_msg_debug("j1^2=%10.8f",(j1(v0))*(j1(v0)));
2400  sinfo_msg_debug("ee=%10.8f",ee);
2401 
2402  sinfo_msg_debug("factor=%10.8f",
2403  occ*occ*(1-j0(occ*v0)*j0(occ*v0)-j1(occ*v0)*j1(occ*v0)));
2404 
2405 
2406  ee+=occ*occ*(1-j0(occ*v0)*j0(occ*v0)-j1(occ*v0)*j1(occ*v0));
2407  sinfo_msg_debug("ee=%10.8f",ee);
2408 
2409  ee-=2.*occ*tot1;
2410  sinfo_msg_debug("ee=%10.8f",ee);
2411 
2412  ee*=cor;
2413  sinfo_msg_debug("ee=%10.8f",ee);
2414 
2415 
2416  tot1=0;
2417  pairy=cpl_image_get_data_double(img_airy);
2418  prr=cpl_image_get_data_double(img_rr);
2419  for(j=0;j<sy;j++) {
2420  for(i=0;i<sx;i++) {
2421  if(!irplib_isnan(pairy[i+j*sx]) && (prr[i+j*sx] <v0)) {
2422  tot1+=pairy[i+j*sx]*ee;
2423  //sinfo_msg_debug("tot=%f",tot1);
2424 
2425  }
2426  }
2427  }
2428 
2429  sinfo_msg_debug("tot=%10.8f",tot1);
2430  cpl_image_divide_scalar(img_airy,tot1);
2431 
2432  /*
2433  check_nomsg(cpl_image_save(img_airy,"out_airy2.fits", CPL_BPP_IEEE_DOUBLE,
2434  NULL,CPL_IO_DEFAULT));
2435 
2436  */
2437 
2438 
2439  // Computation of maximum
2440 
2441  sinfo_msg_debug("dim=%d blocks=%d,bin=%d",dim,blocks,bin);
2442  start=(dim/2-1)-(blocks/2*bin-1)-bin/2;
2443  sinfo_msg_debug("start=%d",start);
2444 
2445  img_psf0=cpl_image_new(blocks,blocks,CPL_TYPE_DOUBLE);
2446  ppsf0=cpl_image_get_data_double(img_psf0);
2447  tot1=0.;
2448  tot2=0.;
2449 
2450  for(j=0;j<blocks;j++) {
2451  for(i=0;i<blocks;i++) {
2452  tot1=0;
2453  for(jj=start+j*bin;jj<start+(j+1)*bin-1;jj++){
2454  for(ii=start+i*bin;ii<start+(i+1)*bin-1;ii++){
2455  if(!irplib_isnan(pairy[ii+jj*sx])) {
2456  tot1+=pairy[ii+jj*sx];
2457  }
2458  }
2459  }
2460  ppsf0[i+j*blocks]=tot1;
2461  tot2+=tot1;
2462  }
2463  }
2464 
2465  cpl_image_divide_scalar(img_psf0,tot2);
2466  /*
2467  check_nomsg(cpl_image_save(img_psf0,"out_psf0.fits", CPL_BPP_IEEE_DOUBLE,
2468  NULL,CPL_IO_DEFAULT));
2469 
2470  */
2471  k=180.*3600./SINFO_MATH_PI;
2472  sinfo_msg_debug("k=%f",k);
2473  sinfo_msg_debug("radius of first zero: 1.22*lambda/d*k:=%f",
2474  1.22*lambda/dia*k);
2475  sinfo_msg_debug("tot: %f",tot2);
2476  sinfo_msg_debug("max: %f",cpl_image_get_max(img_psf0)*tot2);
2477  sinfo_msg_debug("max/tot: %f",cpl_image_get_max(img_psf0));
2478  *psf_peak=cpl_image_get_max(img_psf0);
2479 
2480  sinfo_msg_debug("d=%g ob=%g w=%g ps=%g cx=%g cy=%g a=%g peak=%10.8g",
2481  dia,occ,lambda,psize,cx,cy,anamorph,*psf_peak);
2482 
2483 
2484 
2485  cleanup:
2486  sinfo_free_image(&img_w);
2487  sinfo_free_image(&img_psf0);
2488  sinfo_free_image(&img_xx);
2489  sinfo_free_image(&img_yy);
2490  sinfo_free_image(&img_rr);
2491  sinfo_free_image(&img_rrcor);
2492  sinfo_free_image(&img_airy);
2493 
2494 
2495  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2496  return cpl_error_get_code();
2497  } else {
2498  return CPL_ERROR_NONE;
2499  }
2500 
2501 }
2502 
2503 
2504 cpl_error_code
2505 sinfo_get_flux_above_bkg(const cpl_image* img,
2506  const float kappa,
2507  const float std,
2508  double* f)
2509 {
2510 
2511  const float* pimg=NULL;
2512  int sx=0;
2513  int sy=0;
2514  int i=0;
2515  int j=0;
2516  int k=0;
2517  float tot=0;
2518 
2519  cpl_image* timg=NULL;
2520  double sky_bkg=0;
2521  double sky_std=0;
2522 
2523  timg=cpl_image_duplicate(img);
2524  cpl_image_subtract_scalar(timg,std);
2525  check_nomsg(sinfo_get_bkg_4corners(timg,SINFO_BKG_BOX_SZ,SINFO_BKG_BOX_SZ,
2526  &sky_bkg,&sky_std));
2527 
2528  check_nomsg(pimg=cpl_image_get_data_float_const(timg));
2529 
2530  sx=cpl_image_get_size_x(img);
2531  sy=cpl_image_get_size_y(img);
2532 
2533  for(j=0;j<sy;j++) {
2534  for(i=0;i<sx;i++) {
2535  if(!irplib_isnan(pimg[i+j*sx]) &&
2536  (pimg[i+j*sx]>(sky_bkg+kappa*sky_std))) {
2537  tot+=(double)pimg[i+j*sx];
2538  k++;
2539  }
2540  }
2541  }
2542 
2543  *f=(double)(tot-k*sky_bkg);
2544 
2545  cleanup:
2546  sinfo_free_image(&timg);
2547 
2548  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2549  return cpl_error_get_code();
2550  } else {
2551  return CPL_ERROR_NONE;
2552  }
2553 
2554 }
2555 
2556 
2557 
2558 /*
2559 cpl_error_code
2560 sinfo_get_centroid(const cpl_image* img,
2561  const int d,
2562  const double xc,
2563  const double yc,
2564  double* xcen,
2565  double* ycen,
2566  double* xfwhm,
2567  double* yfwhm,
2568  double* angle)
2569 {
2570 
2571  cpl_bivector* q=NULL;
2572  int sx=0;
2573  int sy=0;
2574  double* pq=NULL;
2575  double peak=0;
2576  double bkg=0;
2577 
2578  check_nomsg(sx=cpl_image_get_size_x(img));
2579  check_nomsg(sy=cpl_image_get_size_y(img));
2580 
2581  check_nomsg(q=cpl_image_iqe(img,sx/2-d,sy/2-d,sx/2+d,sy/2+d));
2582  pq=cpl_bivector_get_data(q);
2583 
2584  *xcen=pq[0];
2585  *ycen=pq[1];
2586  *xfwhm=pq[2];
2587  *yfwhm=pq[3];
2588  *angle=pq[4];
2589  peak=pq[5];
2590  bkg=pq[6];
2591 
2592 
2593  cleanup:
2594 
2595  sinfo_free_bivector(&q);
2596 
2597  if (cpl_error_get_code() != CPL_ERROR_NONE) {
2598  return cpl_error_get_code();
2599  } else {
2600  return CPL_ERROR_NONE;
2601  }
2602 
2603 }
2604  */
2605 
2606 
2607 
2608 static double
2609 sinfo_find_min_of_four(const double n1,
2610  const double n2,
2611  const double n3,
2612  const double n4)
2613 {
2614  double min=0;
2615  min = (n1 < n2) ? n1 : n2;
2616  min = (min < n3) ? min : n3;
2617  min = (min < n4) ? min : n4;
2618  return min;
2619 }
2620 
2621 double
2622 sinfo_scale_flux(const double p1,
2623  const double p2,
2624  const double t1,
2625  const double t2)
2626 {
2627 
2628  return (p2/p1)*(p2/p1)*(t2/t1);
2629 
2630 }
2631 
2632