MIDI Pipeline Reference Manual  2.8.3
calibration.c
1 /******************************************************************************
2 *******************************************************************************
3 * European Southern Observatory
4 * VLTI MIDI Data Reduction Software
5 *
6 * Module name: calibration.c
7 * Description: Contains routines for all calibration preparation routines
8 *
9 * History:
10 * 21-Jul-03 (csabet) Created
11 *******************************************************************************
12 ******************************************************************************/
13 
14 /******************************************************************************
15 * Compiler directives
16 ******************************************************************************/
17 
18 /******************************************************************************
19 * Include files
20 ******************************************************************************/
21 #include <stdlib.h>
22 #include <math.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <unistd.h>
26 #include <stdio.h>
27 #include <cpl.h>
28 #include <string.h>
29 #include "midiGlobal.h"
30 #include "midiLib.h"
31 #include "memoryHandling.h"
32 #include "calibration.h"
33 #include "diagnostics.h"
34 #include "errorHandling.h"
35 #include "statistics.h"
36 #include "midiFitsUtility.h"
37 #include "qfits_table.h"
38 
39 /**********************************************************
40 * Global Variables
41 **********************************************************/
42 
43 /*============================ C O D E A R E A ===========================*/
44 
45 
46 
47 /******************************************************************************
48 * European Southern Observatory
49 * VLTI MIDI Data Reduction Software
50 *
51 * Module name: getCalibratedChWave
52 * Input/Output: See function arguments to avoid duplication
53 * Description: Retrieves the table of channel frequencies, either from the database
54 * or from the current directory. Format for the database is simply
55 * a table of pairs of floats. The one in the current directory has
56 * the following format:
57 *
58 * Record 1 Grism ID
59 * Record 2 Beam Combiner
60 * Record 3 Number of records
61 * Record 4 Value1 value2
62 * .
63 * .
64 * Record n value1 value2
65 *
66 * History:
67 * 09-Sep-05 (csabet) Created
68 ******************************************************************************/
69 void getCalibratedChWave (
70  MidiFiles *fileNames, // In: Pointer to MIDI file structure
71  ImageFormat *format, // In: Image format
72  float **waveCal, // Ou: Wavelength calibration
73  int *error) // Ou: Error status
74 
75 {
76 
77  // Local Declarations
78  // ------------------
79  const char routine[] = "getCalibratedChWave";
80  char *fileString, *givenGrismId, *givenBeamCombiner;
81  FILE *filePtr=NULL;
82  int i, numOfRecords;
83 
84  // Algorithm
85  // ---------
86  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
87  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
88 
89  // Reset status
90  *error = 1;
91 
92  // Check if correct wavelength calibration file exists in the calibration database
93  // If calibration is not in the database then get it from the current directory
94  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
95  sprintf (fileString , "%s_%s_%s.dat", fileNames->waveCalibName, format->grismId, format->beamCombiner);
96  if ((filePtr = fopen (fileString, "r")) != NULL) // It is in the database
97  {
98  // Read from file and load into array
99  if (diagnostic)cpl_msg_info(cpl_func,"Trying to extract Wavelength Calibration from %s \n", fileString);
100  fprintf (midiReportPtr, "Trying to extract Wavelength Calibration from %s \n", fileString);
101  numOfRecords = 0;
102 
103  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
104  while (fscanf (filePtr, "%f %f %f %f\n",
105  &(waveCal[0][numOfRecords]), &(waveCal[1][numOfRecords]),
106  &(waveCal[2][numOfRecords]), &(waveCal[3][numOfRecords])) != EOF) numOfRecords++;
107  else
108  while (fscanf (filePtr, "%f %f\n",
109  &(waveCal[0][numOfRecords]), &(waveCal[1][numOfRecords])) != EOF) numOfRecords++;
110 
111  fclose (filePtr);
112  if (numOfRecords == format->iXWidth)
113  {
114  *error = 0;
115  if (diagnostic)cpl_msg_info(cpl_func,"Found a wavelength calibration file %s with %d rows of floats \n",
116  fileString, numOfRecords);
117  fprintf (midiReportPtr, "Found a wavelength calibration file %s with %d rows of floats \n",
118  fileString, numOfRecords);
119  }
120  else
121  {
122  *error = 1;
123  sprintf (midiMessage, "Inconsistent calibration data in %s. Data ignored", fileString);
124  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
125  }
126  }
127  else
128  {
129  *error = 1;
130  sprintf (midiMessage, "Cannot find calibration data file ... %s", fileString);
131  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
132  }
133  free (fileString);
134 
135  if (*error)
136  {
137  // Allocate memory
138  *error = 0;
139  givenGrismId = (char *) calloc (MIN_STRING_LENGTH, sizeof (char));
140  givenBeamCombiner = (char *) calloc (MIN_STRING_LENGTH, sizeof (char));
141 
142  // Check if wavelength calibration is available. Try to open the file for reading
143  if (diagnostic)cpl_msg_info(cpl_func,"Trying to extract Wavelength Calibration from %s \n", fileNames->wclNameRead);
144  fprintf (midiReportPtr, "Trying to extract Wavelength Calibration from %s \n", fileNames->wclNameRead);
145  if ((filePtr = fopen (fileNames->wclNameRead, "r")) == NULL)
146  {
147  *error = 1;
148  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
149  "Cannot find the Wavelength Calibration file\n Data will be computed from the interferometry file");
150  }
151  else *error = 0; // File exists
152 
153  // Read Grism ID
154  if (!(*error))
155  {
156  if (fscanf (filePtr, "%s \n", givenGrismId) == EOF)
157  {
158  *error = 1;
159  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
160  "Cannot read Grism ID from\n Data will be computed from the interferometry file");
161  fclose (filePtr);
162  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
163  }
164  else
165  {
166  // Check if the given Grism ID is the same as that of the current batch
167  if (strcmp (format->grismId, givenGrismId) != 0)
168  {
169  *error = 1;
170  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
171  "Inconsistent Grism ID\n Data will be computed from the interferometry file");
172  fclose (filePtr);
173  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
174  }
175  }
176  cpl_msg_info(cpl_func,"Given grism ID = %s. Expected %s \n", givenGrismId, format->grismId);
177  fprintf (midiReportPtr, "Given grism ID = %s. Expected %s \n", givenGrismId, format->grismId);
178  }
179 
180  // Read Beam Combiner
181  if (!(*error))
182  {
183  if (fscanf (filePtr, "%s \n", givenBeamCombiner) == EOF)
184  {
185  *error = 1;
186  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
187  "Cannot read Beam Combiner from\n Data will be computed from the interferometry file");
188  fclose (filePtr);
189  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
190  }
191  else
192  {
193  // Check if the given Beam Combiner is the same as that of the current batch
194  if (strcmp (format->beamCombiner, givenBeamCombiner) != 0)
195  {
196  *error = 1;
197  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
198  "Inconsistent Beam Combiner\n Data will be computed from the interferometry file");
199  fclose (filePtr);
200  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
201  }
202  }
203  cpl_msg_info(cpl_func,"Given Beam Combiner = %s. Expected %s \n", givenBeamCombiner, format->beamCombiner);
204  fprintf (midiReportPtr, "Given Beam Combiner = %s. Expected %s \n", givenBeamCombiner, format->beamCombiner);
205  }
206 
207  // If so far so good then get the number of records
208  if (!(*error))
209  {
210  if (fscanf (filePtr, "%d\n", &numOfRecords) == EOF)
211  {
212  *error = 1;
213  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
214  "Cannot read Number of Records\n Data will be computed from the interferometry file");
215  if (filePtr) fclose (filePtr);
216  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
217  }
218  else
219  {
220  // Check if number of records is consistent
221  if (numOfRecords != format->iXWidth)
222  {
223  *error = 1;
224  sprintf (midiMessage, "Inconsistent Number of Records from %s. Expected %d \n",
225  fileNames->wclNameRead, format->iXWidth);
226  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
227  if (filePtr) fclose (filePtr);
228  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
229  }
230  }
231  cpl_msg_info(cpl_func,"Given Number of Records = %d. Expected %d \n", numOfRecords, format->iXWidth);
232  fprintf (midiReportPtr, "Given Number of Records = %d. Expected %d \n", numOfRecords, format->iXWidth);
233  }
234 
235  // If all is well then try to load the data into the array
236  if (!(*error))
237  {
238  for (i = 0; i < format->iXWidth; i++)
239  {
240  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
241  {
242  if (fscanf (filePtr, "%f %f %f %f \n", &(waveCal[0][i]), &(waveCal[1][i]),
243  &(waveCal[2][i]), &(waveCal[3][i])) == EOF)
244  {
245  *error = 1;
246  sprintf (midiMessage, "Read %d rows of wavelength values from %s. Expected %d \n",
247  i, fileNames->wclNameRead, format->iXWidth);
248  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
249  break;
250  }
251  if (diagnostic)cpl_msg_info(cpl_func,"Channel %3d %7.4f %7.4f %7.4f %7.4f \n",
252  i, waveCal[0][i], waveCal[1][i], waveCal[2][i], waveCal[3][i]);
253  fprintf (midiReportPtr, "Channel %3d %7.4f %7.4f %7.4f %7.4f \n",
254  i, waveCal[0][i], waveCal[1][i], waveCal[2][i], waveCal[3][i]);
255  }
256  else
257  {
258  if (fscanf (filePtr, "%f %f \n", &(waveCal[0][i]), &(waveCal[1][i])) == EOF)
259  {
260  *error = 1;
261  sprintf (midiMessage, "Read %d rows of wavelength values from %s. Expected %d \n",
262  i, fileNames->wclNameRead, format->iXWidth);
263  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
264  break;
265  }
266  if (diagnostic)cpl_msg_info(cpl_func,"Channel %3d %7.4f %7.4f \n", i, waveCal[0][i], waveCal[1][i]);
267  fprintf (midiReportPtr, "Channel %3d %7.4f %7.4f \n", i, waveCal[0][i], waveCal[1][i]);
268  }
269  }
270  cpl_msg_info(cpl_func,"\nRead %d rows of wavelength values from %s \n", format->iXWidth, fileNames->wclNameRead);
271  fprintf (midiReportPtr, "\nRead %d rows of wavelength values from %s \n", format->iXWidth, fileNames->wclNameRead);
272  fclose (filePtr);
273  if (strcmp (format->obsCatg, "SCIENCE") == 0) remove (fileNames->wclNameRead);
274  }
275  free (givenGrismId);
276  free (givenBeamCombiner);
277  }
278 
279  return;
280 }
281 /*****************************************************************************/
282 
283 
284 /******************************************************************************
285 * European Southern Observatory
286 * VLTI MIDI Data Reduction Software
287 *
288 * Module name: calibrateWaveUsingPolynom
289 * Input/Output: See function arguments to avoid duplication
290 * Description: Wavelength calibration. Checks if calibration file exists. If not
291 * It creates a file using hardcoded polynomial method
292 *
293 * History:
294 * 03-Feb-05 (csabet) Created
295 ******************************************************************************/
296 void calibrateWaveUsingPolynom (
297  MidiFiles *fileNames, // In: Pointer to MIDI file structure
298  ImageFormat *format) // In: Image format
299 
300 {
301 
302  // Local Declarations
303  // ------------------
304  const char routine[] = "calibrateWaveUsingPolynom";
305  int error, numOfRecords;
306  FILE *waveCalPtr=NULL;
307  char *fileString;
308  float record1, record2, record3, record4;
309 
310  // Algorithm
311  // ---------
312  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
313  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
314 
315  // Reset status
316  error = 0;
317 
318  cpl_msg_info(cpl_func,"\nWavelength calibration for batch %d \n", batchNumber);
319  cpl_msg_info(cpl_func,"-------------------------------- \n");
320  fprintf (midiReportPtr, "\nWavelength calibration for batch %d \n", batchNumber);
321  fprintf (midiReportPtr, "-------------------------------- \n");
322 
323  // Check if correct wavelength calibration file exists in the calibration database
324  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
325  sprintf (fileString , "%s_%s_%s.dat", fileNames->waveCalibName, format->grismId, format->beamCombiner);
326  if ((waveCalPtr = fopen (fileString, "r")) != NULL)
327  {
328  if (diagnostic)cpl_msg_info(cpl_func,"\nTrying to extract Wavelength Calibration from %s \n", fileString);
329  fprintf (midiReportPtr, "\nTrying to extract Wavelength Calibration from %s \n", fileString);
330  numOfRecords = 0;
331  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
332  while (fscanf (waveCalPtr, "%f %f %f %f\n", &record1, &record2, &record3, &record4) != EOF) numOfRecords++;
333  else
334  while (fscanf (waveCalPtr, "%f %f\n", &record1, &record2) != EOF) numOfRecords++;
335  fclose (waveCalPtr);
336  if (numOfRecords == format->iXWidth)
337  {
338  if (diagnostic)cpl_msg_info(cpl_func,"\nFound a wavelength calibration file %s with %d pairs of floats \n",
339  fileString, numOfRecords);
340  fprintf (midiReportPtr, "\nFound a wavelength calibration file %s with %d pairs of floats \n",
341  fileString, numOfRecords);
342  }
343  else
344  {
345  error = 1;
346  sprintf (midiMessage, "Inconsistent calibration data in %s. Data ignored", fileString);
347  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
348  }
349  }
350  else
351  {
352  error = 1;
353  sprintf (midiMessage, "Cannot find calibration data file ... %s", fileString);
354  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
355  }
356  free (fileString);
357 
358  if (error)
359  {
360  getWaveCalPoly (fileNames, format, &error);
361  if (error) midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create wavelength calibration");
362  }
363 
364  return;
365 }
366 /*****************************************************************************/
367 
368 
369 
370 /******************************************************************************
371 * European Southern Observatory
372 * VLTI MIDI Data Reduction Software
373 *
374 * Module name: getWaveCalPoly
375 * Input/Output: See function arguments to avoid duplication
376 * Description: Supplies the a priori waveCal[][] from a CALIB sources.
377 * The contents are filled in by a calibration polynomial.
378 * The format of the output file is as shown below:
379 * Record 1 Grism ID
380 * Record 2 Beam Combiner
381 * Record 3 Number of records
382 * Record 4 Value1 value2
383 * .
384 * .
385 * Record n value1 value2
386 *
387 * History:
388 * 17-Jan-05 (jmeisner) Created
389 * 26-Jan-05 (csabet) Cleaned up, created database and integrated
390 ******************************************************************************/
391 void getWaveCalPoly (
392  MidiFiles *fileNames, // IO: Pointer to midi files structure
393  ImageFormat *imageFormat,
394  int *error) // Ou: Error status
395 {
396 
397  /* Local Declarations
398  --------------------*/
399  const char routine[] = "getWaveCalPoly";
400  float A[2], B[2], C[2], D[2], x, **waveCal=NULL;
401  int i, j, regions, useGrism;
402  FILE *waveCalPtr;
403  struct stat buf;
404 
405  /* Algorithm
406  -----------*/
407  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
408  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
409 
410  cpl_msg_info(cpl_func,"\nComputing wavelength calibration using Calibration Polynomial \n");
411  fprintf (midiReportPtr, "\nComputing wavelength calibration using Calibration Polynomial \n");
412 
413  // Reset status. Check if wavelength calibration file exist. If so delete it
414  if (stat (fileNames->wclNameWrite, &buf) == 0) remove (fileNames->wclNameWrite);
415  *error = 0;
416  regions = 2;
417  useGrism = 0;
418 
419  // Allocate memory
420  waveCal = callocWaveCalibration (regions, imageFormat);
421 
422  // Open the wavelength calibration file for writing
423  if ((waveCalPtr = fopen (fileNames->wclNameWrite, "w")) == NULL)
424  {
425  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot open file to store wavelength calibrations");
426  freeWaveCalibration (regions, waveCal);
427  *error = 1;
428  return;
429  }
430 
431  // Check Grism ID
432  if (strcmp (imageFormat->grismId, "GRISM") == 0) useGrism = 1;
433 
434  // Now here are some numbers obtained from Jeff, to use for the time being......
435  if (useGrism) // for the grism
436  {
437  A[0] = 1.9837227e-08;
438  A[1] = 3.0043738e-08;
439  B[0] = -7.7775886e-06;
440  B[1] = -1.2241891e-05;
441  C[0] = 0.023746001;
442  C[1] = 0.024323120;
443  D[0] = 7.6040181;
444  D[1] = 7.5892995;
445  for (i = 0; i < imageFormat->iXWidth; i++)
446  {
447  for (j = 0; j < regions; j++)
448  {
449  x = (float) i;
450  waveCal[j][i] = 299.8F/(A[j]*x*x*x + B[j]*x*x + C[j]*x + D[j]);
451  }
452  }
453  }
454 
455  if (!useGrism) // for the Prism:
456  {
457  A[0] = -6.1780766e-07;
458  A[1] = -6.8179155e-07;
459  B[0] = -1.6145018e-06;
460  B[1] = 2.1291316e-05;
461  C[0] = -0.037844515;
462  C[1] = -0.040598183;
463  D[0] = 14.576070;
464  D[1] = 14.652558;
465  for (i = 0; i < imageFormat->iXWidth; i++)
466  {
467  for (j = 0; j < regions; j++)
468  {
469  x = (float) i;
470  waveCal[j][i] = 299.8F/(A[j]*x*x*x + B[j]*x*x + C[j]*x + D[j]);
471  }
472  }
473  }
474 
475  // Convert to wavelength
476  for (j = 0; j < regions; j++)
477  {
478  for (i = 0; i < imageFormat->iXWidth; i++) waveCal[j][i] = SPEED_OF_LIGHT / waveCal[j][i];
479  }
480 
481  // Report
482  if (diagnostic)cpl_msg_info(cpl_func,"\nWavelength Calibration \n");
483  fprintf (midiReportPtr, "\nWavelength Calibration \n");
484  for (i = 0; i < imageFormat->iXWidth; i++)
485  {
486  if (strcmp (imageFormat->beamCombiner, "SCI_PHOT") == 0)
487  {
488  if (diagnostic)cpl_msg_info(cpl_func,"%3d %7.4f %7.4f %7.4f %7.4f \n", i,
489  waveCal[0][i], waveCal[0][i], waveCal[1][i], waveCal[0][i]);
490  fprintf (midiReportPtr, "%3d %7.4f %7.4f %7.4f %7.4f \n", i,
491  waveCal[0][i], waveCal[0][i], waveCal[1][i], waveCal[0][i]);
492  }
493  else
494  {
495  if (diagnostic)cpl_msg_info(cpl_func,"%3d %7.4f %7.4f \n", i, waveCal[0][i], waveCal[1][i]);
496  fprintf (midiReportPtr, "%3d %7.4f %7.4f \n", i, waveCal[0][i], waveCal[1][i]);
497  }
498  }
499  if (diagnostic)cpl_msg_info(cpl_func,"\n");
500  fprintf (midiReportPtr, "\n");
501 
502  // Write into the Wavelength Calibration file
503  fprintf (waveCalPtr, "%s \n", imageFormat->grismId); // Record 1
504  fprintf (waveCalPtr, "%s \n", imageFormat->beamCombiner); // Record 2
505  fprintf (waveCalPtr, "%d \n", imageFormat->iXWidth); // Record 3
506  if (strcmp (imageFormat->beamCombiner, "SCI_PHOT") == 0)
507  {
508  for (i = 0; i < imageFormat->iXWidth; i++)
509  fprintf (waveCalPtr, "%f %f %f %f \n", waveCal[0][i], waveCal[0][i],
510  waveCal[1][i], waveCal[0][i]);
511  }
512  else
513  {
514  for (i = 0; i < imageFormat->iXWidth; i++)
515  fprintf (waveCalPtr, "%f %f \n", waveCal[0][i], waveCal[1][i]);
516  }
517 
518  fclose (waveCalPtr);
519 
520  cpl_msg_info(cpl_func,"Created the wavelength calibration file ... %s \n", fileNames->wclNameWrite);
521  fprintf (midiReportPtr, "Created the wavelength calibration file ... %s \n", fileNames->wclNameWrite);
522 
523  // Release memory
524  freeWaveCalibration (regions, waveCal);
525 
526  return;
527 }
528 /******************************************************************************/
529 
530 
531 /******************************************************************************
532 * European Southern Observatory
533 * VLTI MIDI Data Reduction Software
534 *
535 * Module name: checkDelayLineJumps
536 * Input/Output: See function arguments to avoid duplication
537 * Description: Check the Big delay line and the Piezo for illegal DL jumps (within one scan):
538 *
539 * History:
540 * 03-Feb-06 (csabet) Aapted from Jeff Meisner for SCI_PHOT
541 ******************************************************************************/
542 void checkDelayLineJumps (
543  const char *dataKey, // In: Whether Interferometry or Photometry etc.
544  ImageFormat *format,
545  CompressedData *compressed)
546 {
547 
548  // Local Declarations
549  // ------------------
550  const char routine[] = "checkDelayLineJumps";
551  int i, x, numSummed = 0;
552  float lastDL, diff, avg, rms, threshold, lastPiezo,
553  sum=0.0, sumsqr=0.0;
554 
555  // Algorithm
556  // ---------
557  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
558  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
559 
560  cpl_msg_info(cpl_func,"\nChecking Delay Line Jumps within scans for %s \n", dataKey);
561  cpl_msg_info(cpl_func,"-------------------------------------------- \n");
562  fprintf (midiReportPtr, "\nChecking Delay Line Jumps within scans for %s \n", dataKey);
563  fprintf (midiReportPtr, "-------------------------------------------- \n");
564 
565  for (i = 0; i < format->numOfFrames; i++)
566  {
567  if ((i % format->framesPerScan) == 0) // If the first sample of a scan
568  lastDL = compressed->bigDL[i];
569  else if (lastDL != compressed->bigDL[i])
570  {
571  cpl_msg_info(cpl_func,"<<Warning>>: Delay Line jump at scan %d, from %f to %f \n",
572  i/format->framesPerScan, lastDL, compressed->bigDL[i]);
573  fprintf (midiReportPtr, "<<Warning>>: Delay Line jump at scan %d, from %f to %f \n",
574  i, lastDL, compressed->bigDL[i]);
575  compressed->badScanList[i/format->framesPerScan] |= BSL_DLJ_ERROR; // Indicates DL jump within scan
576  lastDL = (compressed->bigDL)[i];
577  }
578  }
579 
580  // Now look at the Piezo, and try to set the optical freq cal:
581  for (i = 0; i < format->numOfFrames; i++)
582  {
583  if ((i % format->framesPerScan) == 0) // If the first sample of a scan
584  lastPiezo = (compressed->localOPD)[i];
585  else
586  {
587  // If this was NOT just after a flyback, good values and good scan
588  if (!(isnan (compressed->localOPD[i])) &&
589  !(isnan (lastPiezo)) &&
590  !(compressed->badScanList[i/format->framesPerScan])) // All regions and channels are affected
591  {
592  diff = compressed->localOPD[i] - lastPiezo; // compressed->localOPD[i-1]
593  sum += diff;
594  sumsqr += diff * diff;
595  numSummed++;
596  lastPiezo = compressed->localOPD[i]; // for next pass through loop
597  }
598  }
599  }
600 
601  avg = sum/((float) numSummed);
602  rms = sqrtp(sumsqr/((float) numSummed) - avg * avg);
603  if ( rms < (0.02 * fabs(avg))) rms = 0.02F * fabs(avg);
604 
605  // Now for a second pass, not using the outliers (but marking them!!):
606  threshold = 5.F * rms; // Set at 5 sigma
607  for (i = 0; i < format->numOfFrames; i++)
608  {
609  if ((i % format->framesPerScan) == 0) // If the first sample of a scan
610  lastPiezo = compressed->localOPD[i];
611  else
612  { // If this was NOT just after a flyback, good values and good scan
613  if (!(isnan (compressed->localOPD[i])) &&
614  !(isnan (lastPiezo)) &&
615  !(compressed->badScanList[i/format->framesPerScan])) // All regions and channels are affected
616  {
617  diff = compressed->localOPD[i] - lastPiezo; // compressed->localOPD[i-1]
618  if (fabs(diff-avg) > threshold)
619  {
620  cpl_msg_info(cpl_func,"<<Warning>>: PIEZO jump at scan %d, of %f microns. Expected %f \n",
621  i/format->framesPerScan, 1000000.F*diff, 1000000.F * avg);
622  fprintf (midiReportPtr, "<<Warning>>: PIEZO jump at scan %d, of %f microns. Expected %f \n",
623  i/format->framesPerScan, 1000000.F*diff, 1000000.F * avg);
624  compressed->badScanList[i/format->framesPerScan] |= BSL_DLJ_ERROR; // Indicates piezo jump within scan.
625  lastPiezo += avg; // <<<< Fake it!
626  }
627  else // Normally:
628  {
629  sum += diff;
630  numSummed++;
631  lastPiezo = compressed->localOPD[i]; // for next pass thru loop
632  }
633  }
634  }
635  }
636  avg = sum/((float) numSummed);
637  if (diagnostic)cpl_msg_info(cpl_func,"Average piezo step = %5.3f microns \n", 1000000.F*avg);
638  fprintf(midiReportPtr, "Average piezo step = %5.3f microns \n", 1000000.F*avg);
639 
640  format->optFreqCal = 1.F/(3335.F*fabs(avg)); // NOW SET HERE!!!;
641 
642  if (diagnostic)cpl_msg_info(cpl_func,"Setting optical wavelength calibration for this observation: %5.3f micron\n",
643  format->optFreqCal);
644  fprintf(midiReportPtr, "Setting optical wavelength calibration for this observation: %5.3f micron\n",
645  format->optFreqCal);
646 
647  // Transfer badScanList to rejectList for DISPERSED processing
648  for (x = 0; x < format->iXWidth; x++)
649  {
650  for (i = 0; i < format->numOfFrames; i++)
651  compressed->rejectList[x][i] |= compressed->badScanList[i/format->framesPerScan];
652  }
653 
654  return;
655 }
656 /******************************************************************************/
657 
658 
659 
660 /******************************************************************************
661 * European Southern Observatory
662 * VLTI MIDI Data Reduction Software
663 *
664 * Module name: checkDelayLineConsistencies
665 * Input/Output: See function arguments to avoid duplication
666 * Description: Checks delay line to see if it is reasonable
667 *
668 * History:
669 * 03-Feb-06 (csabet) Adapted from Jeff Meisner for SCI_PHOT
670 ******************************************************************************/
671 void checkDelayLineConsistencies (
672  const char *dataKey1, // In: Whether Interferometry or Photometry etc.
673  const char *dataKey2, // In: Whether Interferometry or Photometry etc.
674  CompressedData *compressedInterf, // In: Compressed Interferometry data
675  CompressedData *compressedPhotom, // In: Compressed photometry data
676  ImageFormat *formatInterf, // In: Interferompetry data size
677  ImageFormat *formatPhotom, // In: Photometry data size
678  int *error) // Ou: Error status
679 
680 {
681 
682  // Local Declarations
683  // ------------------
684  const char routine[] = "checkDelayLineConsistencies";
685  int j, type, numOfFrames, startFrame, toBeCounted;
686  CompressedData *thisData=NULL;
687  float frameTime100[ARB_NUM_OF_FRAMETIME]; // Number of frametime between 100 frames
688  float mean[3], rms;
689 
690 
691  // Algorithm
692  // ---------
693  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
694  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
695 
696  cpl_msg_info(cpl_func,"\nChecking Delay Line Consistencies between %s and %s \n", dataKey1, dataKey2);
697  cpl_msg_info(cpl_func,"------------------------------------------- \n");
698  fprintf (midiReportPtr, "\nChecking Delay Line Consistencies between %s and %s \n", dataKey1, dataKey2);
699  fprintf (midiReportPtr, "------------------------------------------- \n");
700 
701  // Reset status
702  *error = 0;
703 
704  // Look at the DL data and the TIME data. Perhaps check to see if reasonable
705  for (type = 0; type < 2; type++)
706  {
707  if (type == 0) thisData = compressedInterf; // Interferometry
708  if (type == 1) thisData = compressedPhotom; // Photometry
709  if (type == 0) numOfFrames = formatInterf->numOfFrames; // Interferometry
710  if (type == 1) numOfFrames = formatPhotom->numOfFrames; // Photometry
711  if (numOfFrames < (ARB_NUM_OF_FRAMETIME + 101)) continue;
712  toBeCounted = 0; // In case of bad value (csabet, 02-Mar-05)
713  for (j = 0; j < ARB_NUM_OF_FRAMETIME; j++)
714  {
715  startFrame = j * ((numOfFrames-101)/ARB_NUM_OF_FRAMETIME);
716  if (!isnan (thisData->time[startFrame+100]) && !isnan (thisData->time[startFrame]))
717  {
718  // Now in milliseconds
719  frameTime100[j] = (thisData->time[startFrame+100] - thisData->time[startFrame]) * 864000.0;
720  toBeCounted++;
721  }
722  }
723  makeStats (frameTime100, toBeCounted, mean+type, &rms);
724  if (diagnostic)cpl_msg_info(cpl_func,"Found FRAME TIME for dataset %d = %7.2f ms (apparent rms = %f) \n",
725  type, mean[type], rms*10.0);
726  fprintf (midiReportPtr, "Found FRAME TIME for dataset %d = %7.2f ms (apparent rms = %f) \n",
727  type, mean[type], rms*10.0);
728  if (rms > (0.01 * mean[type])) midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
729  "Apparently an inconsistent FRAME TIME");
730  }
731 
732  if (fabs(mean[1] - mean[0]) > (0.01 * mean[0]))
733  {
734  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
735  "Found inconsistent FRAME TIME between Interferometry & Photometry files");
736  *error = 1;
737  }
738 
739  return;
740 }
741 /*****************************************************************************/
742 
743 
744 
745 /******************************************************************************
746 * European Southern Observatory
747 * VLTI MIDI Data Reduction Software
748 *
749 * Module name: createMaskFile
750 * Input/Output: See function arguments to avoid duplication
751 * Description:
752 *
753 * History:
754 * 21-Jul-03 (csabet) Created
755 ******************************************************************************/
756 void createMaskFile (
757  MidiFiles *fileNames, // IO: Pointer to midi files structure
758  int *error) // Ou: Error status
759 {
760 
761  // Local Declarations
762  // ------------------
763  const char routine[] = "createMaskFile";
764  FILE *inFitsBatchPtr = NULL;
765  ImageFormat *param;
766  int imagingDataExtension;
767  char *stringTemp, *classification, *maskPath;
768  struct stat buf;
769 
770  // Algorithm
771  // ---------
772  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
773  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
774 
775  cpl_msg_info(cpl_func,"\nCreating a mask file for batch %d \n", batchNumber);
776  cpl_msg_info(cpl_func,"------------------------------ \n");
777  fprintf (midiReportPtr, "\nCreating a mask file for batch %d \n", batchNumber);
778  fprintf (midiReportPtr, "------------------------------ \n");
779 
780  // Reset status
781  *error = 0;
782 
783  // Allocate memory
784  param = callocImageFormat ();
785  maskPath = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
786  stringTemp = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
787  classification = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
788 
789  // Open the list of files
790  if ((inFitsBatchPtr = fopen (fileNames->inFitsBatch, "r")) == NULL)
791  {
792  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
793  "Cannot open input FITS file list\n This batch has been ignored");
794  freeImageFormat (param);
795  free (classification);
796  free (stringTemp);
797  *error = 1;
798  return;
799  }
800 
801  // Loop through the file list
802  while (fgets (stringTemp, MAX_STRING_LENGTH, inFitsBatchPtr) != NULL)
803  {
804  sprintf (classification, "%s", "");
805  sscanf (stringTemp, "%s%s", fileNames->inFitsName, classification);
806  if (diagnostic)cpl_msg_info(cpl_func,"Processing file %s \n", fileNames->inFitsName);
807  fprintf(midiReportPtr, "Processing file %s \n", fileNames->inFitsName);
808 
809  // Get extension number of IMAGING_DATA in input file
810  imagingDataExtension = findImagingDataExtension (fileNames->inFitsName, TAB_IMAGING_DATA, error);
811  if (*error) break;
812 
813  // Get Image Format
814  if (imagingDataExtension > 0)
815  {
816  getImageFormat (fileNames->inFitsName, imagingDataExtension, param, error);
817  if (*error) break;
818  }
819  else param->hasData = 0;
820 
821  // Check if the file has data
822  if (param->hasData)
823  {
824  // If mask file is not available then create it
825  sprintf (fileNames->maskFileName, "Mask_ONLINE_%s_%s.fits", param->grismId, param->beamCombiner);
826  sprintf (maskPath, "%s%s", outFileDir, fileNames->maskFileName);
827  if ((stat (maskPath, &buf)) != 0)
828  {
829  // Check if Categ, Tech, Type is suitable for this task
830  if (((strcmp (param->obsCatg, "CALIB") == 0) ||
831  (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
832  (strcmp (param->obsTech, "IMAGE,WINDOW,CHOPNOD") == 0) &&
833  (strcmp (param->obsType, "PHOTOMETRY,OBJECT") == 0))
834  {
835  preparePhotomAperMask (fileNames->inFitsName, maskPath, error);
836  if (*error) midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create mask file from");
837  }
838  else if ((strcmp (param->beamCombiner, "SCI_PHOT") == 0))
839  {
840  // Use only one file
841  createMaskSP (fileNames->inFitsName, maskPath, error);
842  if (*error) midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create mask file from");
843  break;
844  }
845  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
846  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
847  prepareSpectroPhotomAperMask ();
848  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
849  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
850  prepareMasterFlat ();
851  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
852  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
853  prepareMasterDark ();
854  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
855  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
856  prepareDispersionRelation ();
857  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
858  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
859  prepareZeroPoint ();
860  else if (((strcmp (param->obsCatg, "CALIB") == 0) || (strcmp (param->obsCatg, "SCIENCE") == 0)) &&
861  (strcmp (param->obsTech, "UNKNOWN_TECH") == 0) && (strcmp (param->obsType, "UNKNOWN_TYPE") == 0))
862  prepareSpectralSensitivity ();
863  else
864  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, "The above file is not suitable for this task");
865  }
866  else
867  {
868  if (diagnostic)cpl_msg_info(cpl_func,"Found mask FITS file %s \n", maskPath);
869  fprintf (midiReportPtr, "Found mask FITS file %s \n", maskPath);
870  break;
871  }
872  }
873  else
874  {
875  if (diagnostic)
876  {
877  sprintf (midiMessage, "No data tables in %s. Not processed", fileNames->inFitsName);
878  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
879  }
880  }
881  }
882 
883  // Release memory and close files
884  fclose (inFitsBatchPtr);
885  freeImageFormat (param);
886  free (classification);
887  free (stringTemp);
888  free (maskPath);
889 
890  return;
891 }
892 /*****************************************************************************/
893 
894 /******************************************************************************
895 * European Southern Observatory
896 * VLTI MIDI Data Reduction Software
897 *
898 * Module name: prepareMasterFlat
899 * Input/Output: See function arguments to avoid duplication
900 * Description:
901 *
902 * History:
903 * 21-Jul-03 (csabet) Created
904 ******************************************************************************/
905 void prepareMasterFlat (void)
906 {
907 
908  /* Local Declarations
909  --------------------*/
910  const char routine[] = "prepareMasterFlat";
911 
912  /* Algorithm
913  -----------*/
914  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
915  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
916 
917  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
918 
919  return;
920 }
921 /*****************************************************************************/
922 
923 
924 /******************************************************************************
925 * European Southern Observatory
926 * VLTI MIDI Data Reduction Software
927 *
928 * Module name: prepareMasterDark
929 * Input/Output: See function arguments to avoid duplication
930 * Description:
931 *
932 *
933 * History:
934 * 21-Jul-03 (csabet) Created
935 ******************************************************************************/
936 void prepareMasterDark (void)
937 {
938 
939  /* Local Declarations
940  --------------------*/
941  const char routine[] = "prepareMasterDark";
942 
943  /* Algorithm
944  -----------*/
945  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
946  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
947 
948  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
949 
950  return;
951 }
952 /*****************************************************************************/
953 
954 
955 /******************************************************************************
956 * European Southern Observatory
957 * VLTI MIDI Data Reduction Software
958 *
959 * Module name: prepareDispersiveRelation
960 * Input/Output: See function arguments to avoid duplication
961 * Description:
962 *
963 *
964 * History:
965 * 21-Jul-03 (csabet) Created
966 ******************************************************************************/
967 void prepareDispersionRelation (void)
968 {
969 
970  /* Local Declarations
971  --------------------*/
972  const char routine[] = "prepareDispersiveRelation";
973 
974  /* Algorithm
975  -----------*/
976  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
977  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
978 
979  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
980 
981  return;
982 }
983 /*****************************************************************************/
984 
985 
986 /******************************************************************************
987 * European Southern Observatory
988 * VLTI MIDI Data Reduction Software
989 *
990 * Module name: prepareSpectroPhotomAperMask
991 * Input/Output: See function arguments to avoid duplication
992 * Description:
993 *
994 *
995 * History:
996 * 21-Jul-03 (csabet) Created
997 ******************************************************************************/
998 void prepareSpectroPhotomAperMask (void)
999 {
1000 
1001  /* Local Declarations
1002  --------------------*/
1003  const char routine[] = "prepareSpectroPhotomAperMask";
1004 
1005  /* Algorithm
1006  -----------*/
1007  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1008  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
1009 
1010  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
1011 
1012  return;
1013 }
1014 /*****************************************************************************/
1015 
1016 
1017 /******************************************************************************
1018 * European Southern Observatory
1019 * VLTI MIDI Data Reduction Software
1020 *
1021 * Module name: createMaskSP
1022 * Input/Output: See function arguments to avoid duplication
1023 * Description:
1024 *
1025 *
1026 * History:
1027 * 07-Mar-06 (csabet) Created
1028 ******************************************************************************/
1029 void createMaskSP (
1030  char *inFitsName, // In: Name of the input data file
1031  char *maskFitsName, // In: Name of the mask file
1032  int *error) // Ou: Error status
1033 {
1034 
1035  // Local Declarations
1036  // ------------------
1037  const char routine[] = "createMaskSP";
1038  ImageFormat *format;
1039  int i, x, y, extNumOfImagingData, subWindowSize, tableWidth, numOfColumns,
1040  edgeLX, edgeRX, edgeFY, edgeBY, numOfRows;
1041  qfits_header *primHeadMask, *imagDataHeader;
1042  char *dateTime, *tdim1, *tdim2, *tdim3, *tdim4;
1043  FILE *maskFitsPtr;
1044  qfits_table *maskTable;
1045  float **array, *data1, *data2, *data3, *data4;
1046  qfits_col *col;
1047 
1048  // Algorithm
1049  // ---------
1050  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1051  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
1052 
1053  // Reset status
1054  *error = 0;
1055  numOfRows = 1;
1056  numOfColumns = 4;
1057  tableWidth = - 1;
1058 
1059  cpl_msg_info(cpl_func,"Creating mask FITS file %s \n", maskFitsName);
1060  fprintf (midiReportPtr, "Creating mask FITS file %s \n", maskFitsName);
1061 
1062  // Get 'extNumOfImagingDataFile' extension number of IMAGING_DATA in input file
1063  extNumOfImagingData = findImagingDataExtension (inFitsName, TAB_IMAGING_DATA, error);
1064 
1065  // Get Image Format parameters and allocate memory for the data1 and data2 */
1066  format = callocImageFormat ();
1067  getImageFormat (inFitsName, extNumOfImagingData, format, error);
1068  subWindowSize = format->iXWidth * format->iYWidth;
1069 
1070  // Extract Primary Header from the input file
1071  if (diagnostic)cpl_msg_info(cpl_func,"Extracting primary header from input FITS file %s \n", inFitsName);
1072  if (diagnostic) fprintf(midiReportPtr, "Extracting primary header from input FITS file %s \n", inFitsName);
1073  primHeadMask = qfits_header_read (inFitsName);
1074  if (primHeadMask == NULL)
1075  {
1076  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot extract primary header from input FITS file");
1077  cpl_msg_info(cpl_func,"\nCannot Create mask FITS file for batch %d \n", batchNumber);
1078  fprintf (midiReportPtr, "\nCannot Create mask FITS file for batch %d \n", batchNumber);
1079  freeImageFormat (format);
1080  *error = 1;
1081  return;
1082  }
1083 
1084  // Update primary header for the Mask file
1085  dateTime = qfits_get_datetime_iso8601 ();
1086  qfits_header_mod (primHeadMask, "DATE", dateTime, "Date and time this file was written");
1087  qfits_header_mod (primHeadMask, "INSTRUME", "MIDI", "MIDI Mask created by DRS pipeline" );
1088  qfits_header_add (primHeadMask, "EXTNAME", "Primary", "MIDI Mask primary header", "" );
1089 
1090  // Create the mask file and dump the primary header and close the file
1091  maskFitsPtr = fopen (maskFitsName, "w");
1092  qfits_header_dump (primHeadMask, maskFitsPtr);
1093  qfits_header_destroy (primHeadMask);
1094  fclose (maskFitsPtr);
1095 
1096  // Allocate memory for data
1097  data1 = (float *) calloc (subWindowSize, sizeof (float));
1098  data2 = (float *) calloc (subWindowSize, sizeof (float));
1099  data3 = (float *) calloc (subWindowSize, sizeof (float));
1100  data4 = (float *) calloc (subWindowSize, sizeof (float));
1101  tdim1 = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1102  tdim2 = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1103  tdim3 = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1104  tdim4 = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1105 
1106  // Load data
1107  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "This is a temporary rectangular mask");
1108  edgeFY = 0.30 * format->iYWidth;
1109  edgeBY = 0.50 * format->iYWidth;
1110  edgeLX = 0.20 * format->iXWidth;
1111  edgeRX = 0.20 * format->iXWidth;
1112  for (y = edgeFY; y < format->iYWidth-edgeBY; y++)
1113  {
1114  for (x = edgeLX; x < format->iXWidth-edgeRX; x++)
1115  {
1116  i = x + y * format->iXWidth;
1117  data1[i] = 1.0;
1118  data2[i] = 1.0;
1119  data3[i] = 1.0;
1120  data4[i] = 1.0;
1121  }
1122  }
1123 
1124  // Open the mask file for writing
1125  maskFitsPtr = fopen (maskFitsName, "a");
1126  if (maskFitsPtr == NULL)
1127  {
1128  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot open mask file");
1129  *error = 1;
1130  free (tdim1);
1131  free (tdim2);
1132  free (tdim3);
1133  free (tdim4);
1134  free (data1);
1135  free (data2);
1136  free (data3);
1137  free (data4);
1138  freeImageFormat (format);
1139  return;
1140  }
1141 
1142  // Create a new table
1143  maskTable = qfits_table_new (maskFitsName, QFITS_BINTABLE, tableWidth, numOfColumns, numOfRows);
1144  if (!maskTable)
1145  {
1146  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create table");
1147  *error = 1;
1148  free (tdim1);
1149  free (tdim2);
1150  free (tdim3);
1151  free (tdim4);
1152  free (data1);
1153  free (data2);
1154  free (data3);
1155  free (data4);
1156  freeImageFormat (format);
1157  fclose (maskFitsPtr);
1158  return;
1159  }
1160 
1161  // Fill in the column information
1162  col = maskTable->col;
1163  qfits_col_fill (col, subWindowSize, 2, sizeof(float), TFITS_BIN_TYPE_E, "DATA1", " ", " ", " ",
1164  0, 0.0, 0, 1.0, 0);
1165  col++;
1166  qfits_col_fill (col, subWindowSize, 2, sizeof(float), TFITS_BIN_TYPE_E, "DATA2", " ", " ", " ",
1167  0, 0.0, 0, 1.0, 0);
1168  col++;
1169  qfits_col_fill (col, subWindowSize, 2, sizeof(float), TFITS_BIN_TYPE_E, "DATA3", " ", " ", " ",
1170  0, 0.0, 0, 1.0, 0);
1171  col++;
1172  qfits_col_fill (col, subWindowSize, 2, sizeof(float), TFITS_BIN_TYPE_E, "DATA4", " ", " ", " ",
1173  0, 0.0, 0, 1.0, subWindowSize* sizeof(float));
1174 
1175  // Create the imaging data header
1176  imagDataHeader = qfits_table_ext_header_default(maskTable);
1177  qfits_header_add (imagDataHeader, "EXTNAME", "IMAGING_DATA", "MIDI Mask Extension name", "" );
1178 
1179 
1180  // Add dimensionality to the extension header
1181  sprintf (tdim1, "'(%d,%d)'", format->iXWidth, format->iYWidth);
1182  sprintf (tdim2, "'(%d,%d)'", format->iXWidth, format->iYWidth);
1183  sprintf (tdim3, "'(%d,%d)'", format->iXWidth, format->iYWidth);
1184  sprintf (tdim4, "'(%d,%d)'", format->iXWidth, format->iYWidth);
1185  qfits_header_add (imagDataHeader, "TDIM1", tdim1, "Column dimensionality", "" );
1186  qfits_header_add (imagDataHeader, "TDIM2", tdim2, "Column dimensionality", "" );
1187  qfits_header_add (imagDataHeader, "TDIM3", tdim2, "Column dimensionality", "" );
1188  qfits_header_add (imagDataHeader, "TDIM4", tdim2, "Column dimensionality", "" );
1189 
1190  // Allocate space for the array of data
1191  array = (float **) calloc (numOfColumns, sizeof(float *));
1192  array[0] = data1;
1193  array[1] = data2;
1194  array[2] = data3;
1195  array[3] = data4;
1196 
1197  if (qfits_table_append_xtension_hdr (maskFitsPtr, maskTable, (const void **)array, imagDataHeader) == -1)
1198  *error = 1;
1199 
1200  qfits_header_destroy (imagDataHeader);
1201  qfits_table_close (maskTable);
1202 
1203  if (!(*error))
1204  {
1205  cpl_msg_info(cpl_func,"Created Mask FITS file: %s \n", maskFitsName);
1206  fprintf (midiReportPtr, "Created Mask FITS file: %s \n", maskFitsName);
1207  }
1208 
1209  // Release memory
1210  free (array);
1211  fclose (maskFitsPtr);
1212  free (tdim1);
1213  free (tdim2);
1214  free (tdim3);
1215  free (tdim4);
1216  free (data1);
1217  free (data2);
1218  free (data3);
1219  free (data4);
1220  freeImageFormat (format);
1221 
1222  return;
1223 }
1224 /*****************************************************************************/
1225 
1226 
1227 /******************************************************************************
1228 * European Southern Observatory
1229 * VLTI MIDI Data Reduction Software
1230 *
1231 * Module name: preparePhotomAperMask
1232 * Input/Output: See function arguments to avoid duplication
1233 * Description:
1234 *
1235 *
1236 * History:
1237 * 21-Jul-03 (csabet) Created
1238 ******************************************************************************/
1239 void preparePhotomAperMask (
1240  char *inFileName, // In: Name of the input data file
1241  char *maskFileName, // In: Name of the mask file
1242  int *error) // Ou: Error status
1243 {
1244 
1245  /* Local Declarations
1246  --------------------*/
1247  const char routine[] = "preparePhotomAperMask";
1248  static short int *aveData_1, *aveData_2;
1249  short int *inData_1, *inData_2;
1250  ImageFormat *format;
1251  int i, j, extNumOfImagingData, numOfElemets,
1252  scalingOffset, indexData1, indexData2, subWindowSize, pixel;
1253  static int aprioriNumOfElemets = 0, numOfFiles = 0;
1254  qfits_table *imagDataTable;
1255  char *tempStr, *dataName;
1256  int foundData1 = 0, foundData2 = 0;
1257 
1258  /* Algorithm
1259  -----------*/
1260  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1261  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
1262 
1263  /* Reset status */
1264  *error = 0;
1265  numOfFiles++;
1266 
1267  /* Get 'extNumOfImagingDataFile' extension number of IMAGING_DATA in input file */
1268  extNumOfImagingData = findImagingDataExtension (inFileName, TAB_IMAGING_DATA, error);
1269 
1270  /* Get Image Format parameters and allocate memory for the data1 and data2 */
1271  format = callocImageFormat ();
1272  getImageFormat (inFileName, extNumOfImagingData, format, error);
1273  subWindowSize = format->iXWidth * format->iYWidth;
1274  numOfElemets = subWindowSize * format->numOfFrames;
1275 
1276  /* Allocate memory in the first call */
1277  if (numOfFiles == 1)
1278  {
1279  aprioriNumOfElemets = numOfElemets;
1280  aveData_1 = (short int *) calloc (numOfElemets, sizeof (short int));
1281  aveData_2 = (short int *) calloc (numOfElemets, sizeof (short int));
1282  }
1283 
1284  if (aprioriNumOfElemets != numOfElemets)
1285  {
1286  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Inconsistent photometry files");
1287  *error = 1;
1288  freeImageFormat (format);
1289  free (aveData_1);
1290  free (aveData_2);
1291  return;
1292  }
1293 
1294  /* Open IMAGING_DATA */
1295  imagDataTable = qfits_table_open (inFileName, extNumOfImagingData);
1296  if (!imagDataTable)
1297  {
1298  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot load IMAGING_DATA");
1299  *error = 1;
1300  freeImageFormat (format);
1301  free (aveData_1);
1302  free (aveData_2);
1303  return;
1304  }
1305 
1306  dataName = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1307  // Get the scaling offset
1308  for (i = 14; i < 25; i++)
1309  {
1310  sprintf (dataName, "TZERO%d", i);
1311  tempStr = qfits_query_ext (inFileName, dataName, extNumOfImagingData);
1312  if (tempStr != NULL)
1313  {
1314  if (diagnostic)cpl_msg_info(cpl_func,"Scaling Offset = %s\n", tempStr);
1315  fprintf( midiReportPtr, "Scaling Offset = %s\n", tempStr);
1316  sscanf (tempStr, "%d", &scalingOffset);
1317  break;
1318  }
1319  }
1320  if (tempStr == NULL)
1321  {
1322  scalingOffset = 0;
1323  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot read Scaling Offset. It is set to 0");
1324  }
1325  free (dataName);
1326 
1327  /* Get data table information */
1328  indexData1 = 0;
1329  indexData2 = 0;
1330  for (i = 0; i < imagDataTable->nc; i++)
1331  {
1332  if (strcmp (imagDataTable->col[i].tlabel, "DATA1") == 0)
1333  {
1334  foundData1 = 1;
1335  indexData1 = i;
1336  }
1337  if (strcmp (imagDataTable->col[i].tlabel, "DATA2") == 0)
1338  {
1339  foundData2 = 1;
1340  indexData2 = i;
1341  }
1342  }
1343  if (foundData1 == 0 || foundData2 == 0)
1344  {
1345  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot find requested columns in date FITS file");
1346  *error = 1;
1347  qfits_table_close (imagDataTable);
1348  free (aveData_1);
1349  freeImageFormat (format);
1350  free (aveData_2);
1351  return;
1352  }
1353 
1354  /* Load data */
1355  inData_1 = (short int *) (qfits_query_column (imagDataTable, indexData1, NULL));
1356  inData_2 = (short int *) (qfits_query_column (imagDataTable, indexData2, NULL));
1357 
1358  /* Cumulate data */
1359  for (j = 0; j < format->numOfFrames; j++)
1360  {
1361  for (pixel = 0; pixel < subWindowSize; pixel++)
1362  {
1363  i = j * subWindowSize + pixel;
1364  if (isnan (inData_1[i]) || isnan (inData_2[i]))
1365  {
1366  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Corrupted DATA1 or DATA2");
1367  qfits_table_close (imagDataTable);
1368  free (inData_1);
1369  free (inData_2);
1370  freeImageFormat (format);
1371  *error = 1;
1372  return;
1373  }
1374  aveData_1[i] += (inData_1[i] + scalingOffset);
1375  aveData_2[i] += (inData_2[i] + scalingOffset);
1376  }
1377  }
1378  free (inData_1);
1379  free (inData_2);
1380 
1381  /* Create the mask file */
1382  if (numOfFiles == 2)
1383  {
1384  for (i = 0; i < numOfElemets; i++)
1385  {
1386  aveData_1[i] *= 0.5;
1387  aveData_2[i] *= 0.5;
1388  }
1389  createMidiMaskFile(format->iXWidth, format->iYWidth, inFileName, (short int *)(aveData_1), (short int *)(aveData_2),
1390  format->numOfFrames, subWindowSize, maskFileName, error);
1391  if (*error)
1392  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create mask file");
1393 
1394  /* Reset counter for other batches */
1395  numOfFiles = 0;
1396 
1397  /* Release memory */
1398  free (aveData_1);
1399  free (aveData_2);
1400  }
1401 
1402  /* Release memory */
1403  freeImageFormat (format);
1404 
1405  qfits_table_close (imagDataTable);
1406 
1407  return;
1408 }
1409 /*****************************************************************************/
1410 
1411 
1412 
1413 /******************************************************************************
1414 * European Southern Observatory
1415 * VLTI MIDI Data Reduction Software
1416 *
1417 * Module name: prepareZeroPoint
1418 * Input/Output: See function arguments to avoid duplication
1419 * Description:
1420 *
1421 *
1422 * History:
1423 * 21-Jul-03 (csabet) Created
1424 ******************************************************************************/
1425 void prepareZeroPoint (void)
1426 {
1427 
1428  /* Local Declarations
1429  --------------------*/
1430  const char routine[] = "prepareZeroPoint";
1431 
1432  /* Algorithm
1433  -----------*/
1434  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1435  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
1436 
1437  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
1438 
1439  return;
1440 }
1441 /*****************************************************************************/
1442 
1443 
1444 /******************************************************************************
1445 * European Southern Observatory
1446 * VLTI MIDI Data Reduction Software
1447 *
1448 * Module name: prepareSpectralSensitivity
1449 * Input/Output: See function arguments to avoid duplication
1450 * Description:
1451 *
1452 *
1453 * History:
1454 * 21-Jul-03 (csabet) Created
1455 ******************************************************************************/
1456 void prepareSpectralSensitivity (void)
1457 {
1458 
1459  /* Local Declarations
1460  --------------------*/
1461  const char routine[] = "prepareSpectralSensitivity";
1462 
1463  /* Algorithm
1464  -----------*/
1465  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1466  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s' \n", routine);
1467 
1468  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire routine to be written");
1469 
1470  return;
1471 }
1472 /*****************************************************************************/