MIDI Pipeline Reference Manual  2.8.3
photometry.c
1 /******************************************************************************
2 *******************************************************************************
3 * European Southern Observatory
4 * VLTI MIDI Data Reduction Software
5 *
6 * Module name: photometry.c
7 * Description:
8 *
9 * History:
10 * 03-Feb-03 (jmeisner) Created
11 * 03-Mar-03 (csabet) Added title, directives and included in the MIDI pipeline
12 * 21-Jan-05 (csabet) Major clean up and redesign
13 *******************************************************************************
14 ******************************************************************************/
15 
16 /******************************************************************************
17 * Compiler directives
18 ******************************************************************************/
19 
20 /******************************************************************************
21 * Include files
22 ******************************************************************************/
23 #include <stdio.h>
24 #include <cpl.h>
25 #include <stdlib.h>
26 #include <math.h>
27 #include "midiGlobal.h"
28 #include <string.h>
29 #include "midiLib.h"
30 #include "statistics.h"
31 #include "diagnostics.h"
32 #include "photometry.h"
33 #include "errorHandling.h"
34 
35 
36 /**********************************************************
37 * Constant definitions
38 **********************************************************/
39 
40 /**********************************************************
41 * Global Variables
42 **********************************************************/
43 
44 /*============================ C O D E A R E A ===========================*/
45 
46 
47 /******************************************************************************
48 * European Southern Observatory
49 * VLTI MIDI Data Reduction Software
50 *
51 * Module name: estimatePhotom
52 * Input/Output: See function arguments to avoid duplication
53 * Description:
54 *
55 * History:
56 * 11-Aug-05 (csabet) Created
57 *****************************************************************************/
58 void estimatePhotom(
59  char key, // In: Strig character indicating type
60  CompressedData *compressed, // In: Compressed data
61  ImageFormat *format, // In: Photometry size
62  float **photom, // Ou: Photometry result
63  float **photomErr, // Ou: Estimated photometry RMS error
64  int *error)
65 {
66 
67  // Local Declarations
68  // ------------------
69  const char routine[] = "estimatePhotom";
70  int region, X, regionId;
71  float choppingRMS; // Measure of chop-to-chop rms RELATIVE to full photometry, NOT USED;
72  char *string, *title;
73  float *arrayPlot;
74 
75  // Algorithm
76  // ---------
77  if (diagnostic > 4)cpl_msg_info(cpl_func,"\nInvoking routine '%s' \n", routine);
78  if (diagnostic > 4) fprintf(midiReportPtr, "\nInvoking routine '%s' \n", routine);
79 
80  // Reset parameters
81  *error = 0;
82 
83  // Exception
84  if (format->numOfFrames < 2)
85  {
86  cpl_msg_info(cpl_func,"Not enough data. Expected more than 1. Found %d", format->numOfFrames);
87  fprintf (midiReportPtr, "Not enough data. Expected more than 1. Found %d", format->numOfFrames);
88  *error = 1;
89  return;
90  }
91 
92  // If not chopped exit
93  if (!(format->chopped))
94  {
95  *error = 1;
96  return;
97  }
98 
99  cpl_msg_info(cpl_func,"\n");
100  fprintf (midiReportPtr, "\n");
101 
102  for (region = 0; region < format->numOfRegionsToProcess; region++)
103  {
104  if (plotFile)
105  arrayPlot = (float *) calloc (format->iXWidth, sizeof(float));
106 
107  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
108  {
109  if (key == 'A') regionId = 1;
110  else if (key == 'B') regionId = 4;
111  else regionId = region+2;
112  }
113  else
114  regionId = region+1;
115 
116  if (diagnostic)cpl_msg_info(cpl_func, "Running dispersed Photom %c, for region %d\n", key, regionId);
117  fprintf (midiReportPtr, "Running dispersed Photom %c, for region %d\n", key, regionId);
118 
119  for (X = 0; X < format->iXWidth; X++)
120  {
121  if (badChannelList[X])
122  continue;
123 
124  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
125  {
126  photom[region][X] = getChopPhotomSP (X, (((compressed->iDispFringe)[region])[X]),
127  format->numOfScans, format->framesPerScan, compressed->rejectList[X], &(photomErr[region][X]),
128  &choppingRMS);
129  }
130  else
131  {
132  photom[region][X] = getChopPhotom (X, (((compressed->iDispFringe)[region])[X]),
133  compressed->tarType, &(photomErr[region][X]), &choppingRMS, format->numOfFrames);
134  }
135 
136  if (isnan(photom[region][X]))
137  badChannelList[X] |= BSL_DATA_ERROR;
138 
139  if (plotFile)
140  {
141  if (isnan(photom[region][X]))
142  arrayPlot[X] = 0.0;
143  else
144  arrayPlot[X] = photom[region][X];
145  }
146  }
147 
148  if (plotFile)
149  {
150  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
151  string = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
152  sprintf (string, "Photom%cDATA%d", key, regionId);
153  sprintf (title, "Photometry %c, for Region %d", key, regionId);
154  midiCreatePlotFile2D (string, title, "Channel", "Photometry", 0, photom[region], 0, format->iXWidth, 1, 0);
155  sprintf (string, "Photom%cErrDATA%d", key, regionId);
156  sprintf (title, "Photometry %c Error, for Region %d", key, regionId);
157  midiCreatePlotFile2D (string, title, "Channel", "Photometry Error", 0, photomErr[region], 0, format->iXWidth, 1, 0);
158  free (string);
159  free (title);
160  free (arrayPlot);
161  }
162  }
163 
164  return;
165 }
166 /*****************************************************************************/
167 
168 
169 
170 /******************************************************************************
171 * European Southern Observatory
172 * VLTI MIDI Data Reduction Software
173 *
174 * Module name: getChopPhotomSP
175 * Input/Output: See function arguments to avoid duplication
176 * Description:
177 *
178 * History:
179 * 14-Feb-06 (csabet) Created
180 ******************************************************************************/
181 float getChopPhotomSP ( // Ou: Photometry
182  int X, // In: Wavelength channel
183  float *compressed, // In: Pointer to compressed data for one X and one R
184  int numOfScans, // In: Number of frames
185  int framesPerScan, // In: Number of frames per scan
186  int *rejectList, // In: Bad Frame List
187  float *errRMS, // Ou: rms error returned
188  float *choppingRMS) // Ou: Measure of chop-to-chop rms RELATIVE to full photometry;
189 {
190 
191  // Local Declarations
192  // ------------------
193  const char routine[] = "getChopPhotomSP";
194  int f, j, s, numOfAccum, length;
195  float accum, *results, photom, variance, rms;
196 
197  // Algorithm
198  // ---------
199 
200  // Allocate memory
201  results = (float *) calloc (numOfScans, sizeof (float));
202 
203  // Create an array of photometric results for 'T' only
204  length = 0;
205  for (s = 0; s < numOfScans; s++)
206  {
207  numOfAccum = 0;
208  accum = 0.F;
209  for (j = 0; j < framesPerScan; j++)
210  {
211  f = j + s * framesPerScan;
212  if (!(rejectList[f]))
213  {
214  accum += (float) compressed[f];
215  numOfAccum++;
216  }
217  }
218  if (numOfAccum)
219  {
220  results[length] = accum / ((float) numOfAccum);
221  length++;
222  }
223  }
224 
225  // Compute statistics
226  if (length)
227  {
228  photom = signalMean (results, 0, length);
229  variance = signalVariance (results, 0, length, &rms);
230 
231  // If zero variance, set rms to a small value
232  if (variance == 0.0)
233  rms = 0.1F;
234 
235  *errRMS = rms / sqrt((float)length);
236 
237  // Return relative error per chop
238  if (photom > 0.0)
239  *choppingRMS = rms / photom;
240  }
241 
242  // Exception
243  if (photom <= 0.0 || !length)
244  {
245  photom = NOT_A_NUMBER;
246  sprintf (midiMessage, "Cannot compute photometry for channel %3d", X);
247  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
248 
249  // Reject this channel
250  badChannelList[X] |= BSL_DATA_ERROR;
251  }
252 
253  // Release local memory
254  free(results);
255 
256  return (photom);
257 }
258 /*****************************************************************************/
259 
260 
261 
262 /******************************************************************************
263 * European Southern Observatory
264 * VLTI MIDI Data Reduction Software
265 *
266 * Module name: getChopPhotom
267 * Input/Output: See function arguments to avoid duplication
268 * Description:
269 *
270 * History:
271 * 14-Feb-06 (csabet) Created from JM. Removed goto statements and restructured
272 ******************************************************************************/
273 float getChopPhotom (
274  int X, // In: Wavelength channel
275  float *collapsedData, // In: Pointer to linear array of chopping data, sequential with time
276  char *targetType, // In: Pointer to description array. 'S'=offsource, 'T'=on source, 'U'=???
277  float *errRMS, // Ou: rms error returned
278  float *choppingRMS, // Ou: Measure of chop-to-chop rms RELATIVE to full photometry;
279  int numData) // In: Number of data points in the above arrays to use.
280 {
281 
282  // Local Declarations
283  // ------------------
284  const char routine[] = "getChopPhotom";
285  char lastType;
286  int index, numOfaccum;
287  float accum, accum2, *results, photom, mean, variance, rms;
288 
289  // Algorithm
290  // ---------
291 
292  // Initialise
293  lastType = 'U';
294  accum = 0.F;
295  numOfaccum = 0;
296 
297  // Allocate memory
298  results = (float *) calloc (numData, sizeof (float));
299 
300  // Create an array of photometric results for 'T' only
301  for (index = 0; index < numData; index++)
302  {
303  // If state has changed then compute the average brightness in the previous state
304  if ((targetType[index] != lastType) && numOfaccum)
305  {
306  if (targetType[index] == 'T')
307  {
308  results[index] = accum / ((float) numOfaccum);
309 
310  // Reset parameters
311  numOfaccum = 0;
312  accum = 0.F;
313  }
314  }
315 
316  // Now accumulate
317  if (targetType[index] == 'T')
318  {
319  accum += (float) collapsedData[index];
320  numOfaccum++;
321  }
322 
323  // Save current state
324  lastType = targetType[index];
325  }
326 
327  // Alright, now results[] has a number of non-zero values. Compute statistics
328  accum = 0.F;
329  accum2 = 0.F;
330  numOfaccum = 0;
331  for (index = 0; index < numData; index++)
332  {
333  if (results[index] != 0.F)
334  {
335  accum += results[index];
336  accum2 += results[index] * results[index];
337  numOfaccum++;
338  }
339  }
340 
341  // Compute mean and variance
342  if (numOfaccum)
343  {
344  mean = accum / ((float) numOfaccum);
345  variance = (accum2 - mean * mean * ((float) numOfaccum)) / ((float) (numOfaccum - 1));
346 
347  // If zero variance, set rms to a small value
348  if (variance > 0.0)
349  rms = sqrt(variance);
350  else
351  rms = 0.1F;
352 
353  *errRMS = rms / sqrt((float)numOfaccum);
354  photom = mean;
355 
356  // Return relative error per chop
357  if (photom > 0.0)
358  *choppingRMS = rms / photom;
359  }
360 
361  // Exception
362  if (photom <= 0.0 || !numOfaccum)
363  {
364  photom = NOT_A_NUMBER;
365  sprintf (midiMessage, "Cannot compute photometry for channel %3d", X);
366  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
367 
368  // Reject this channel
369  badChannelList[X] |= BSL_DATA_ERROR;
370  }
371 
372  // Release local memory
373  free(results);
374 
375  return (photom);
376 }
377 /*****************************************************************************/
378 
379 
380 
381 
382 /******************************************************************************
383 * European Southern Observatory
384 * VLTI MIDI Data Reduction Software
385 *
386 * Module name: estimatePhotomUndisp
387 * Input/Output: See function arguments to avoid duplication
388 * Description: For UNDISPERSED processing
389 *
390 * History:
391 * 03-Mar-03 (csabet) Cleaned up and Integrated
392 ******************************************************************************/
393 void estimatePhotomUndisp (
394  ImageFormat *format,
395  CompressedData *inData, // In: Compressed photometry data
396  float *errs, // Ou: array of rms error returned (size = numOfRegionsChopped)
397  float *choppingRMS, // Ou: Measure of chop-to-chop rms RELATIVE to full photometry;
398  float *results) // Ou: array of photometric results
399 {
400 
401  /* Local Declarations
402  --------------------*/
403  int region;
404  double *thisdata;
405 
406  /* Algorithm
407  -----------*/
408  for (region = 0; region < format->numOfRegionsToProcess; region++)
409  {
410  if (region == 0)
411  thisdata = inData->iFringe1;
412  else
413  thisdata = inData->iFringe2;
414 
415  results[region] = getChopPhotomUndisp ((double *)thisdata, inData->tarType, errs+region,
416  choppingRMS+region, format->numOfFrames);
417 
418  if (diagnostic > 1)
419  {
420  cpl_msg_info(cpl_func,"Photometric measurement for region %d: %f \n", region+1, results[region]);
421  cpl_msg_info(cpl_func,"Relative chop-to-chop rms: %4.1f%% \n", 100.F*choppingRMS[region]);
422  fprintf (midiReportPtr, "Photometric measurement for region %d: %f \n", region+1, results[region]);
423  fprintf(midiReportPtr, "Relative chop-to-chop rms: %4.1f%% \n", 100.F*choppingRMS[region]);
424  }
425  }
426 
427  return;
428 }
429 /*****************************************************************************/
430 
431 
432 
433 
434 /******************************************************************************
435 * European Southern Observatory
436 * VLTI MIDI Data Reduction Software
437 *
438 * Module name: getChopPhotomDoubleUndisp
439 * Input/Output: See function arguments to avoid duplication
440 * Description:
441 *
442 * History:
443 * 14-Feb-06 (csabet) Created from JM. Removed goto statements and restructured
444 ******************************************************************************/
445 float getChopPhotomUndisp (
446  double *collapsedData, // In: Pointer to linear array of chopping data, sequential with time
447  char *targetType, // In: Pointer to description array. 'S'=offsource, 'T'=on source, 'U'=???
448  float *err, // Ou: rms error returned
449  float *choppingRMS, // Ou: Measure of chop-to-chop rms RELATIVE to full photometry;
450  int numData) // In: Number of data points in the above arrays to use.
451 {
452 
453  // Local Declarations
454  // ------------------
455  const char routine[] = "getChopPhotomUndisp";
456  char lastType;
457  int index, numOfaccum;
458  float accum, accum2, *results, photom, mean, variance, rms;
459 
460  // Algorithm
461  // ---------
462 
463  // Initialise
464  lastType = 'U';
465  accum = 0.F;
466  numOfaccum = 0;
467 
468  // Allocate memory
469  results = (float *) calloc (numData, sizeof (float));
470 
471  // Create an array of photometric results for 'T' only
472  for (index = 0; index < numData; index++)
473  {
474  // If state has changed then compute the average brightness in the previous state
475  if ((targetType[index] != lastType) && numOfaccum)
476  {
477  if (targetType[index] == 'T')
478  {
479  results[index] = accum / ((float) numOfaccum);
480 
481  // Reset parameters
482  numOfaccum = 0;
483  accum = 0.F;
484  }
485  }
486 
487  // Now accumulate
488  if (targetType[index] == 'T')
489  {
490  accum += (float) collapsedData[index];
491  numOfaccum++;
492  }
493 
494  // Save current state
495  lastType = targetType[index];
496  }
497 
498  // Alright, now results[] has a number of non-zero values. Compute statistics
499  accum = 0.F;
500  accum2 = 0.F;
501  numOfaccum = 0;
502  for (index = 0; index < numData; index++)
503  {
504  if (results[index] != 0.F)
505  {
506  accum += results[index];
507  accum2 += results[index] * results[index];
508  numOfaccum++;
509  }
510  }
511 
512  // Compute mean and variance
513  mean = accum / ((float) numOfaccum);
514  variance = (accum2 - mean * mean * ((float) numOfaccum)) / ((float) (numOfaccum - 1));
515 
516  // Compute rms. If zero variance, set rms to a small value
517  if (variance > 0.0)
518  rms = sqrt(variance);
519  else
520  rms = 0.1F;
521 
522  *err = rms / sqrt((float)numOfaccum);
523  photom = mean;
524 
525  // Singularity check
526  if (photom > 0.0)
527  *choppingRMS = rms / photom; // Return relative err per chop.
528  else
529  {
530  /* In dispsersed mode, this will always happen on detector
531  columns with zero weighting. So don't want to get too upset about it */
532  *choppingRMS = NOT_A_NUMBER;
533  sprintf (midiMessage, "Singularity detected. Values in this batch are unreliable");
534  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
535  }
536 
537  // Release local memory
538  free(results);
539 
540  return (photom);
541 }
542 /*****************************************************************************/
543 
544 
545 /******************************************************************************
546 * European Southern Observatory
547 * VLTI MIDI Data Reduction Software
548 *
549 * Module name: computeBinnedPhotom
550 * Input/Output: See function arguments to avoid duplication
551 * Description: This function computes HIGH_SENS combined photometry levels of
552 * regions 1 and 2 at the follwing spectral channels:
553 * 1) Channels: 113 -> 121 (PRISM)
554 * 052 -> 068 (GRISM) i.e. [ArIII] band
555 *
556 * 2) Channels: 088 -> 098 (PRISM)
557 * 116 -> 136 (GRISM) i.e. [SIV] band
558 *
559 * 3) Channels: 036 -> 050 (PRISM)
560 * 217 -> 245 (GRISM) i.e. [NeII] band
561 * History:
562 * 21-Sep-06 (csabet) Created
563 ******************************************************************************/
564 void computeBinnedPhotom (
565  CompressedData *photomA, // In: Compressed data
566  CompressedData *photomB, // In: Compressed data
567  ImageFormat *format, // In: Photometry size
568  float *photomA1, // Ou: Binned photometry
569  float *photomA2, // Ou: Binned photometry
570  float *photomA3, // Ou: Binned photometry
571  float *photomB1, // Ou: Binned photometry
572  float *photomB2, // Ou: Binned photometry
573  float *photomB3, // Ou: Binned photometry
574  int *error) // Ou: Error status
575 {
576 
577  // Local Declarations
578  // ------------------
579  const char routine[] = "computeBinnedPhotom";
580  int i, j;
581 
582  // Algorithm
583  // ---------
584 
585  // Reset parameters
586  *error = 0;
587  *photomA1 = *photomA2 = *photomA3 = 0.0;
588  *photomB1 = *photomB2 = *photomB3 = 0.0;
589 
590  if (strcmp(format->grismId, "PRISM") == 0)
591  {
592  for (i = 36; i < 51; i++)
593  {
594  if (badChannelList[i])
595  continue;
596 
597  for (j = 0; j < format->numOfFrames; j++)
598  {
599  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
600  *photomA3 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
601  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
602  *photomB3 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
603  }
604  }
605  for (i = 88; i < 99; i++)
606  {
607  if (badChannelList[i])
608  continue;
609 
610  for (j = 0; j < format->numOfFrames; j++)
611  {
612  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
613  *photomA2 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
614  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
615  *photomB2 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
616  }
617  }
618  for (i = 113; i < 122; i++)
619  {
620  if (badChannelList[i])
621  continue;
622 
623  for (j = 0; j < format->numOfFrames; j++)
624  {
625  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
626  *photomA1 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
627  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
628  *photomB1 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
629  }
630  }
631  }
632  else if (strcmp(format->grismId, "GRISM") == 0)
633  {
634  for (i = 52; i < 69; i++)
635  {
636  if (badChannelList[i])
637  continue;
638 
639  for (j = 0; j < format->numOfFrames; j++)
640  {
641  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
642  *photomA1 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
643  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
644  *photomB1 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
645  }
646  }
647  for (i = 116; i < 137; i++)
648  {
649  if (badChannelList[i])
650  continue;
651 
652  for (j = 0; j < format->numOfFrames; j++)
653  {
654  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
655  *photomA2 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
656  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
657  *photomB2 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
658  }
659  }
660  for (i = 217; i < 245; i++)
661  {
662  if (badChannelList[i])
663  continue;
664 
665  for (j = 0; j < format->numOfFrames; j++)
666  {
667  if (photomA->tarType[j] == 'T' && !(photomA->rejectList[i][j]))
668  *photomA3 += ( (((photomA->iDispFringe)[0])[i])[j] + (((photomA->iDispFringe)[1])[i])[j] );
669  if (photomB->tarType[j] == 'T' && !(photomB->rejectList[i][j]))
670  *photomB3 += ( (((photomB->iDispFringe)[0])[i])[j] + (((photomB->iDispFringe)[1])[i])[j] );
671  }
672  }
673  }
674  else
675  {
676  sprintf (midiMessage, "Unknown GRISM ID ... %s", format->grismId);
677  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
678  *error = 1;
679  return;
680  }
681 
682  return;
683 }
684 /*****************************************************************************/
685