X-shooter Pipeline Reference Manual 3.8.15
xsh_compute_noise_map.c
Go to the documentation of this file.
1/* *
2 * This file is part of the ESO X-shooter Pipeline *
3 * Copyright (C) 2006 European Southern Observatory *
4 * *
5 * This library is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the Free Software *
17 * Foundation, 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA *
18 * */
19
20/*
21 * $Author: amodigli $
22 * $Date: 2012-06-13 09:24:33 $
23 * $Revision: 1.57 $
24 * $Name: not supported by cvs2svn $
25 */
26
27#ifdef HAVE_CONFIG_H
28#include <config.h>
29#endif
30
31/*----------------------------------------------------------------------------*/
37/*----------------------------------------------------------------------------*/
40/*-----------------------------------------------------------------------------
41 Includes
42 -----------------------------------------------------------------------------*/
43#include <math.h>
44
45#include <xsh_drl.h>
46#include <xsh_data_pre.h>
47#include <xsh_dfs.h>
48#include <xsh_pfits.h>
49#include <xsh_error.h>
50#include <xsh_msg.h>
51#include <xsh_badpixelmap.h>
52
53#include <cpl.h>
54
55/*-----------------------------------------------------------------------------
56 Typedefs
57 -----------------------------------------------------------------------------*/
58
59/*-----------------------------------------------------------------------------
60 Functions prototypes
61 -----------------------------------------------------------------------------*/
62
63/*-----------------------------------------------------------------------------
64 Implementation
65 -----------------------------------------------------------------------------*/
66
67static void add_noisy_pixel_to_ascii_file( int x, int y )
68{
69 static FILE *fout ;
70 const char * fname = "noisy_pixels.dat" ;
71
72 if ( fout == NULL )
73 fout = fopen( fname, "w" ) ;
74 fprintf( fout, "%d %d\n", x, y ) ;
75 if ( fout ) fclose( fout ) ;
76
77}
78
91static int
92flag_noisy_pixels (cpl_imagelist * raws,
93 cpl_image * bpmap,
94 cpl_image * noisymap,
95 int nx, int ny,
96 xsh_clipping_param * noise_clipping,xsh_instrument* inst)
97{
98 int ix, iy, i;
99 cpl_image **pimg = NULL;
100 int nimg, nbad = 0, npix = 0;
101 double medStackv = 0.,
102 aveStackv = 0.,
103 sumStackv = 0., errorStackv = 0.;
104 double *Stackv = NULL,
106 *pStackv = NULL;
107 double *stack = NULL;
108 double *bisStackv = NULL,
109 *pbis = NULL;
110 double diff = 0.0, diff2 = 0.0;
111 double min = 999999., max = -9999999.;
112 double maxdelta = 0.0;
113 cpl_binary *bpmap_mask = NULL;
114 int idpix = 0;
115 float ** pixdata = NULL;
116 cpl_binary **pixmask = NULL;
117 int nhot = 0;
118 int totpix = nx * ny;
119 nimg = cpl_imagelist_get_size(raws);
120
121 XSH_MALLOC(pimg, cpl_image*, nimg);
122
123 /* Populate images pointer array */
124for( i = 0; i < nimg; i++) {
125 *(pimg + i) = cpl_imagelist_get (raws, i);
126 }
127 /* Create array of sigmas */
128 XSH_MALLOC(Stackv, double, nx * ny);
129
130pStackv = Stackv;
131
132 xsh_msg_dbg_low( "Rejected in bpmap: %" CPL_SIZE_FORMAT "", cpl_image_count_rejected( bpmap ));
133
134 /* allocate a temporary array for 1 pixel stack */
135 XSH_MALLOC(stack, double, nimg);
136
137 /* Get bad pixel mask */
138bpmap_mask = cpl_mask_get_data(cpl_image_get_bpm(bpmap));
139 assure( bpmap_mask != NULL, cpl_error_get_code(),
140 "Cant get bpmap Mask" );
141
142 XSH_MALLOC(bisStackv, double, totpix);
143pbis = bisStackv;
144
145 /* Get pixel data and masks of images */
146 {
147 int j;
148 XSH_MALLOC(pixdata, float *, nimg);
149XSH_MALLOC (pixmask,cpl_binary *,nimg);
150
151 for (j = 0; j < nimg; j++) {
152 *(pixdata + j) = cpl_image_get_data_float(*(pimg + j));
153 *(pixmask + j) = cpl_mask_get_data(cpl_image_get_bpm(*(pimg + j)));
154 }
155 }
156 idpix = 0;
157
158 for (iy = 1; iy <= ny; iy++) {
159 for (ix = 1; ix <= nx; ix++) {
160 int j, count = 0;
161 double sum = 0.;
162
163 /* Loop over all images (1 pixel) */
164 if ((*(bpmap_mask + idpix) & inst->decode_bp) > 0) {
165 nbad++;
166 xsh_msg_dbg_medium("Pixel %d,%d globally bad", ix, iy);
167 *pStackv = 0.;
168 } else {
169 for (j = 0; j < nimg; j++) {
170 int rej;
171 double fval = *(*(pixdata + j) + idpix);
172 rej = (*(*(pixmask + j) + idpix ) & inst->decode_bp);
173 //xsh_msg( "pixel[%d,%d] (%d) = %lf", ix, iy, idpix, fval ) ;
174 if (rej > 0) {
175 /* bad pixel */
176 xsh_msg_dbg_medium("Don't use pixel %d,%d [%d]", ix, iy, j);
177 continue;
178 }
179 sum += fval;
180
181 *(stack + count) = fval;
182 count++;
183 }
184 }
185
186 if (count > 1) {
187 /* Calculate sigma of this stack */
188 double avg = sum / (double) count;
189 double dif, dif2 = 0., sigma = 0.;
190 int k;
191
193 " [%d,%d] Count=%d - sum = %lf, avg = %lf", ix, iy, count, sum, avg);
194 //TEST
195 for (k = 0; k < count; k++) {
196 xsh_msg_dbg_medium( " stack[%d] = %lf", k, *(stack+k));
197 dif = *(stack + k) - avg;
198 dif2 += dif * dif;
199 }
200 sigma = sqrt(dif2 / (double) (count - 1));
201 *pStackv = sigma;
202 *pbis++ = sigma;
203 sumStackv += sigma;
205 "++ dif2 = %lf, count= %d, sigma=%lf, Stackv=%lf, sum=%lf", dif2, count, sigma, *pStackv, sumStackv);
206 if ((npix % 500) == 0)
208 "+++++ (%d,%d) sumStackv = %lf", ix, iy, sumStackv);
209 npix++;
210 } else {
211 xsh_msg_dbg_medium( "Not enough good pixels (%d)", count);
212 *pStackv = 0.;
213 }
214 pStackv++;
215 idpix++;
216 } /* end loop on x */
217 } /* end loop on y */
218 xsh_msg_dbg_medium( "+++++ sumStackv = %lf", sumStackv);
219 /* Calculate medstackv
220 ATTENTION: La fonction cpl_tools_get_median_double modifie le
221 vecteur !
222 */
223 medStackv = xsh_tools_get_median_double(bisStackv, npix);
224
225 /* Calculate aveStackv */
226 aveStackv = sumStackv / (double) npix;
228 "--- Npix=%d - sumStackv=%lf - aveStackv=%lf", npix, sumStackv, aveStackv);
229
230 /* Calculate errorStackv */
231 //for (pStackv = Stackv, i = 0; i < npix; i++, pStackv++) {
232 for (pStackv = bisStackv, i = 0; i < npix; i++, pStackv++) {
233 diff = *pStackv - aveStackv;
234 if (diff < min)
235 min = diff;
236 if (diff > max)
237 max = diff;
238 diff2 += diff * diff;
239 }
240 cpl_free(bisStackv);
241 bisStackv = NULL;
242
243 xsh_msg_dbg_low("Diff Min: %lf, Max: %lf", min, max);
244 errorStackv = sqrt(diff2 / (double) (npix - 1));
245 xsh_msg_dbg_low( "errorStackv=%lf", errorStackv);
246
247 /* Now sigma clipping */
248 maxdelta = noise_clipping->sigma * errorStackv;
249
251 "Npix:%d/%d, sum: %lf, med:%lf, avg:%lf, err:%lf, delta: %lf", npix, nx * ny, sumStackv, medStackv, aveStackv, errorStackv, maxdelta);
252
253 pStackv = Stackv;
254 idpix = 0;
255
256 for (iy = 1; iy <= ny; iy++) {
257 for (ix = 1; ix <= nx; ix++) {
258 if ( (*(bpmap_mask + idpix) & inst->decode_bp) == 0 ) {
259 double delta = *pStackv - medStackv;
260 if (fabs(delta) > maxdelta) {
261 nhot++;
262 /* Flag this pixel in bpmap */
266 // And in the noisymap as well !
268
269 }
270
271 }
272 pStackv++;
273 idpix++;
274 }
275 }
276 xsh_msg( "Found %d Electronic Pickup Noise Hot Pixels", nhot );
277
278 cleanup:
279 XSH_FREE(stack);
280 XSH_FREE(Stackv);
281 XSH_FREE(bisStackv);
282 XSH_FREE(pimg);
283 XSH_FREE(pixdata);
284 XSH_FREE(pixmask);
285 return nhot;
286}
287
288static void
289set_pickup_noise_pixels_qc (cpl_propertylist * header, int nbad,
291{
292 xsh_pfits_set_qc( header, (void *)&nbad,
294}
295
306cpl_frame *
307xsh_compute_noise_map (cpl_imagelist * dataList,
308 cpl_frame * medFrame,
309 xsh_clipping_param * noise_clipping,
310 xsh_instrument* instr,
311 cpl_frame ** noisyFrame
312 )
313{
314 int nx, ny, nframes = 0;
315 cpl_image *resBpMap = NULL;
316 cpl_propertylist *bpmapHeader = NULL;
317 cpl_frame *resFrame = NULL;
318 int prevnbad;
319 const char *bpmapFile = cpl_frame_get_filename (medFrame);
320 xsh_pre *medPre = NULL;
321 int iter = 0,curnbad = 0;
322 char result_name[256] ;
323 const char* tag = XSH_GET_TAG_FROM_ARM(XSH_BP_MAP_PN,instr);
324 char noisy_name[256];
325 cpl_image * noisyMap = NULL ;
326 cpl_propertylist * noisymapHeader = NULL ;
327
328 int binx=0;
329 int biny=0;
330 cpl_image* ima_aux=NULL;
331
332 /*
333 Compute noise for each pixel stack
334 Compare with average noise
335 Declare pixel bad is difference exceeds clip_sigma
336 */
337
338 cpl_msg_indent_more ();
339 xsh_msg ("*** Removing Noisy Pixels (%s)",
341
342 /* Get bad pixel map (from medFrame) */
343 xsh_msg ("Bpmap file = \"%s\"", bpmapFile);
344
345 /* Loader PRE structure */
346 medPre = xsh_pre_load (medFrame,instr);
347 XSH_ASSURE_NOT_NULL(medPre);
348
349 resBpMap = xsh_pre_get_qual (medPre);
350 bpmapHeader = medPre->qual_header;
351
352 nx = medPre->nx;
353 ny = medPre->ny;
354
355 check( noisyMap = cpl_image_new( nx, ny, CPL_TYPE_INT ) ) ;
356 check( noisymapHeader = cpl_propertylist_duplicate( bpmapHeader ) ) ;
357 xsh_msg( " Image size: %d,%d", nx, ny ) ;
358
359 xsh_set_image_cpl_bpmap (resBpMap, resBpMap, instr->decode_bp);
360 prevnbad = cpl_image_count_rejected (resBpMap);
361
362 nframes = cpl_imagelist_get_size (dataList);
363 xsh_msg ("%d dark images in image list", nframes);
364
365 /* Iterate */
366 for (iter = 0; iter < noise_clipping->niter; iter++) {
367 int nhot=0 ;
368
369 xsh_msg (">>>> Iteration Nb %d/%d", iter+1, noise_clipping->niter);
370 cpl_msg_indent_more ();
371
372 if(nframes>1) {
373 /* Suppress noisy pixels and add to bad pixel map as ??? */
374 nhot = flag_noisy_pixels (dataList, resBpMap, noisyMap,
375 nx, ny, noise_clipping,instr);
376 }
377 cpl_msg_indent_less ();
378 if ( nhot == 0 ) break ;
379 }
380
381 /* Print total number of bad pixels */
382 curnbad = cpl_image_count_rejected (resBpMap);
383 xsh_msg ("End of noisy pixels, total bad pixels: %d", curnbad);
384
385 xsh_msg (" Nb of noisy pixels: %d", curnbad - prevnbad);
386
387 /* Populate resFrame from medFrame + badpixelmap */
388 /* Now save the relevant frame of PRE
389 With: median image, errs image and bad pixel map
390 */
391 //strcpy(result_name,xsh_stringcat_any( tag, ".fits", "" )) ;
392 strcpy(result_name,bpmapFile) ;
393 xsh_msg ("save frame %s\n", result_name);
394
395 /* Calculate QC parameters */
396 /* QC.DARKMED.AVE
397 QC.DARKMED.STDEV
398 QC.BP-MAP.NBADPIX = current_nb_badpix - previous_nb_badpix
399 */
400 check(set_pickup_noise_pixels_qc (medPre->data_header, curnbad, instr ));
401 /* Add QC.NHPIX parameters */
402 check(xsh_pfits_set_qc_nhpix( medPre->data_header, curnbad - prevnbad )) ;
403 if ( xsh_instrument_get_arm(instr) == XSH_ARM_NIR ) {
404 sprintf(noisy_name,"%s.fits",XSH_GET_TAG_FROM_ARM(XSH_BP_MAP_PN,instr));
405 } else {
408 sprintf(noisy_name,"%s_%dx%d.fits",XSH_GET_TAG_FROM_ARM(XSH_BP_MAP_PN,
409 instr),
410 binx,biny);
411 }
412 ima_aux=cpl_image_cast(medPre->data,CPL_TYPE_FLOAT);
413 check(cpl_image_save (ima_aux,result_name, CPL_BPP_IEEE_FLOAT,
414 medPre->data_header, CPL_IO_DEFAULT));
415
416 xsh_free_image(&ima_aux);
417
418 xsh_pfits_set_extname (medPre->errs_header, "ERRS");
419 ima_aux=cpl_image_cast(medPre->errs,CPL_TYPE_FLOAT);
420 check(cpl_image_save (ima_aux,result_name, CPL_BPP_IEEE_FLOAT,
421 medPre->errs_header, CPL_IO_EXTEND));
422 xsh_free_image(&ima_aux);
423
424
425 xsh_pfits_set_extname (bpmapHeader, "QUAL");
426 check(cpl_image_save (resBpMap, result_name, XSH_PRE_DATA_BPP, bpmapHeader,
427 CPL_IO_EXTEND));
428
429
430 check(resFrame=xsh_frame_product(result_name,tag,
431 CPL_FRAME_TYPE_IMAGE,
432 CPL_FRAME_GROUP_PRODUCT,
433 CPL_FRAME_LEVEL_FINAL));
434
435 // save hot pixel image
436 /* Add QC.NHPIX parameters */
437 set_pickup_noise_pixels_qc (noisymapHeader, curnbad, instr );
438 xsh_pfits_set_qc_nhpix( noisymapHeader, (curnbad - prevnbad) ) ;
439 cpl_image_save (noisyMap, noisy_name, XSH_PRE_DATA_BPP,
440 noisymapHeader,
441 CPL_IO_DEFAULT );
442 xsh_add_temporary_file(noisy_name);
443 // Create Frame
444 check(*noisyFrame=xsh_frame_product(noisy_name,tag,
445 CPL_FRAME_TYPE_IMAGE,
446 CPL_FRAME_GROUP_PRODUCT,
447 CPL_FRAME_LEVEL_TEMPORARY));
448 //xsh_add_temporary_file(noisy_name);
449
450cleanup:
451
452 xsh_free_propertylist(&noisymapHeader);
453 xsh_free_image(&noisyMap);
454 xsh_free_image(&ima_aux);
455 xsh_pre_free( &medPre ) ;
456
457 return resFrame ;
458}
459
460/*----------------------------------------------------------------------------*/
461
static double sigma
static xsh_instrument * instrument
int binx
int biny
void xsh_bpmap_set_bad_pixel(cpl_image *bpmap, int ix, int iy, int flag)
void xsh_set_image_cpl_bpmap(cpl_image *image, cpl_image *bpmap, const int decode_bp)
static int flag_noisy_pixels(cpl_imagelist *raws, cpl_image *bpmap, cpl_image *noisymap, int nx, int ny, xsh_clipping_param *noise_clipping, xsh_instrument *inst)
static void add_noisy_pixel_to_ascii_file(int x, int y)
cpl_frame * xsh_compute_noise_map(cpl_imagelist *dataList, cpl_frame *medFrame, xsh_clipping_param *noise_clipping, xsh_instrument *instr, cpl_frame **noisyFrame)
static void set_pickup_noise_pixels_qc(cpl_propertylist *header, int nbad, xsh_instrument *instrument)
xsh_pre * xsh_pre_load(cpl_frame *frame, xsh_instrument *instr)
Load a xsh_pre structure from a frame.
Definition: xsh_data_pre.c:849
cpl_image * xsh_pre_get_qual(xsh_pre *pre)
Get qual.
void xsh_pre_free(xsh_pre **pre)
Free a xsh_pre structure.
Definition: xsh_data_pre.c:823
#define assure(CONDITION, ERROR_CODE,...)
Definition: xsh_error.h:54
#define check(COMMAND)
Definition: xsh_error.h:71
#define XSH_ASSURE_NOT_NULL(pointer)
Definition: xsh_error.h:99
const char * xsh_instrument_arm_tostring(xsh_instrument *i)
Get the string associated with an arm.
XSH_ARM xsh_instrument_get_arm(xsh_instrument *i)
Get an arm on instrument structure.
int * y
int * x
#define xsh_msg_dbg_medium(...)
Definition: xsh_msg.h:44
#define xsh_msg(...)
Print a message on info level.
Definition: xsh_msg.h:121
#define xsh_msg_dbg_low(...)
Definition: xsh_msg.h:48
int xsh_pfits_get_binx(const cpl_propertylist *plist)
find out the BINX value
Definition: xsh_pfits.c:289
void xsh_pfits_set_extname(cpl_propertylist *plist, const char *value)
Write the EXTNAME value.
Definition: xsh_pfits.c:979
int xsh_pfits_get_biny(const cpl_propertylist *plist)
find out the BINY value
Definition: xsh_pfits.c:306
void xsh_pfits_set_qc_nhpix(cpl_propertylist *plist, int value)
Write the QC.NHPIX value.
Definition: xsh_pfits_qc.c:703
void xsh_pfits_set_qc(cpl_propertylist *plist, void *value, const char *kw, xsh_instrument *instrument)
void xsh_free_image(cpl_image **i)
Deallocate an image and set the pointer to NULL.
Definition: xsh_utils.c:2116
int xsh_debug_level_get(void)
get debug level
Definition: xsh_utils.c:3142
double xsh_tools_get_median_double(double *array, int size)
Calculates the median value of an array of double.
Definition: xsh_utils.c:2721
void xsh_free_propertylist(cpl_propertylist **p)
Deallocate a property list and set the pointer to NULL.
Definition: xsh_utils.c:2179
void xsh_add_temporary_file(const char *name)
Add temporary file to temprary files list.
Definition: xsh_utils.c:1432
cpl_propertylist * qual_header
Definition: xsh_data_pre.h:72
cpl_image * data
Definition: xsh_data_pre.h:65
cpl_propertylist * errs_header
Definition: xsh_data_pre.h:69
cpl_propertylist * data_header
Definition: xsh_data_pre.h:66
cpl_image * errs
Definition: xsh_data_pre.h:68
#define QFLAG_ELECTRONIC_PICKUP
@ XSH_ARM_NIR
#define XSH_PRE_DATA_BPP
Definition: xsh_data_pre.h:43
int nx
int ny
cpl_frame * xsh_frame_product(const char *fname, const char *tag, cpl_frame_type type, cpl_frame_group group, cpl_frame_level level)
Creates a frame with given characteristics.
Definition: xsh_dfs.c:930
#define XSH_BP_MAP_PN
Definition: xsh_dfs.h:349
#define XSH_GET_TAG_FROM_ARM(TAG, instr)
Definition: xsh_dfs.h:1548
#define max(a, b)
#define XSH_QC_BP_MAP_PICKUP_NOISE_PIX
Definition: xsh_pfits_qc.h:164
#define XSH_FREE(POINTER)
Definition: xsh_utils.h:92
@ XSH_DEBUG_LEVEL_LOW
Definition: xsh_utils.h:137
#define XSH_MALLOC(POINTER, TYPE, SIZE)
Definition: xsh_utils.h:49