MIDI Pipeline Reference Manual  2.8.3
procWavCal.c
1 
2 /******************************************************************************
3 *******************************************************************************
4 * European Southern Observatory
5 * VLTI MIDI Maintenance Templates Software
6 *
7 * Module name: procWaveCal.c
8 * Description: Contains routines for processing the templates
9 *
10 * History:
11 * 02-Jun-05 (csabet) created
12 *******************************************************************************
13 ******************************************************************************/
14 
15 /******************************************************************************
16 * Compiler directives
17 ******************************************************************************/
18 
19 /******************************************************************************
20 * Include files
21 ******************************************************************************/
22 #include <math.h>
23 #include <stdio.h>
24 #include <cpl.h>
25 #include <errno.h>
26 #include <string.h>
27 #include "midiGlobal.h"
28 #include "midiLib.h"
29 #include "imageProcessing.h"
30 #include "memoryHandling.h"
31 #include "createProdWavCal.h"
32 #include "procWavCal.h"
33 #include "errorHandling.h"
34 #include "midiFitsUtility.h"
35 #include "fitsAnalysisTec.h"
36 #include "diagnostics.h"
37 #include "statistics.h"
38 #include "cpl_polynomial.h"
39 #include "qfits.h"
40 #include "midi_cplutils.h"
41 #include "midi_cplupgrade.h"
42 
43 /**********************************************************
44 * Constant definitions
45 **********************************************************/
46 
47 /**********************************************************
48 * Global Variables
49 **********************************************************/
50 
51 /*============================ C O D E A R E A ===========================*/
52 
53 
54 /******************************************************************************
55 * European Southern Observatory
56 * VLTI MIDI Maintenance Templates Software
57 *
58 * Module name: procWaveCal
59 * Input/Output: See function arguments to avoid duplication
60 * Description: The main objective is to calibrate the channel against wavelength.
61 * That is to assign the correct wavelength to the detector channels.
62 *
63 * History:
64 * 02-Jun-05 (csabet) Created
65 ******************************************************************************/
66 void procWaveCal (
67  int processing, // In: Correlate = 1, Create = 2
68  MidiFiles *fileNames, // In: Pointer to file names
69  int *error) // Ou: Error status
70 {
71 
72  // Local Declarations
73  // ------------------
74  const char routine[] = "procWaveCal";
75  FILE *signaturePtr=NULL, *filePtr=NULL;
76  int numOfFiles, numOfRecords;
77  ImageFormat *format=NULL;
78  WaveCalibration *waveCal=NULL;
79  char *fileString;
80  float record1, record2, record3, record4;
81 
82  // Algorithm
83  // ---------
84  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
85  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
86 
87  // Write a signature
88  signaturePtr = fopen ("MIDI_sig_wav.log", "w");
89  fclose (signaturePtr);
90 
91  // Reset status
92  *error = 0;
93  numOfFiles = 0;
94 
95  // Allocate memory
96  format = callocImageFormat ();
97 
98  analyseFitsWaveCal (fileNames, format, &numOfFiles, error);
99  if (*error)
100  {
101  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot analyse WAVECAL");
102  freeImageFormat (format);
103  return;
104  }
105 
106  // If correlation is requested, check if database file exists
107  if (processing == 1)
108  {
109  // Check if correct frequency calibration file exists in the calibration database
110  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
111  sprintf (fileString , "%s_%s_%s.dat", fileNames->waveCalibName, format->grismId, format->beamCombiner);
112  if ((filePtr = fopen (fileString, "r")) != NULL) // It is in the database
113  {
114  // Read from file and load into array
115  cpl_msg_info(cpl_func,"\nChecking consistency of Wavelength Calibration file ... %s \n", fileString);
116  fprintf (midiReportPtr, "\nChecking consistency of Wavelength Calibration file ... %s \n", fileString);
117  numOfRecords = 0;
118  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
119  while (fscanf (filePtr, "%f %f %f %f\n", &record1, &record2, &record3, &record4) != EOF) numOfRecords++;
120  else
121  while (fscanf (filePtr, "%f %f\n", &record1, &record2) != EOF) numOfRecords++;
122 
123  fclose (filePtr);
124  if (numOfRecords == format->iXWidth)
125  {
126  *error = 0;
127  cpl_msg_info(cpl_func,"Found a wavelength calibration file %s with %d pairs of floats \n",
128  fileString, numOfRecords);
129  fprintf (midiReportPtr, "Found a wavelength calibration file %s with %d pairs of floats \n",
130  fileString, numOfRecords);
131  }
132  else
133  {
134  *error = 1;
135  sprintf (midiMessage, "Inconsistent calibration data in %s. Nothing to correlate", fileString);
136  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
137  }
138  }
139  else
140  {
141  *error = 1;
142  sprintf (midiMessage, "Cannot find calibration data file ... %s. Nothing to correlate", fileString);
143  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
144  }
145  free (fileString);
146 
147  if (*error)
148  {
149  freeImageFormat (format);
150  return;
151  }
152  }
153 
154  // Get the size of the Wavelength Calibration data
155  numOfRecords = getWlCalib2Spectra (fileNames, error);
156  if (*error)
157  {
158  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot get Wavelength Calibration data");
159  freeImageFormat (format);
160  return;
161  }
162 
163  // Get largest size
164  if (numOfRecords < format->iXWidth) numOfRecords = format->iXWidth;
165 
166  // Main task for wavelength calibration
167  waveCal = callocWaveCal (numOfFiles, numOfRecords, format);
168  computeWaveCal (processing, numOfFiles, fileNames, waveCal, error);
169  if (*error)
170  {
171  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot process WAVECAL");
172  freeWaveCal (format, waveCal);
173  freeImageFormat (format);
174  return;
175  }
176 
177  // Create product files
178  createWaveCalProd (processing, fileNames, format, waveCal, error);
179  if (*error) midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create WAVECAL products");
180 
181  // Release memory
182  freeWaveCal (format, waveCal);
183  freeImageFormat (format);
184 
185 
186  return;
187 }
188 /*****************************************************************************/
189 
190 
191 
192 /******************************************************************************
193 * European Southern Observatory
194 * VLTI MIDI Maintenance Templates Software
195 *
196 * Module name: computeWaveCal
197 * Input/Output: See function arguments to avoid duplication
198 * Description: Performs Wavelength Calibration
199 *
200 * History:
201 * 10-Jun-05 (csabet) Created
202 ******************************************************************************/
203 void computeWaveCal (
204  int processing, // In: Correlate = 1, Create = 2
205  int numOfFiles, // In: Number of data files
206  MidiFiles *fileNames, // In: Pointer to the MIDI file structure
207  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
208  int *error) // Ou: Error status
209 {
210 
211  // Local Declarations
212  // ------------------
213  const char routine[] = "computeWaveCal";
214  char *fileTemp, *classification;
215  FILE *inFitsBatchPtr;
216  ImageFormat *format;
217  int localError, fileNumber, extNumOfImagingDataFile;
218 
219  // Algorithm
220  // ---------
221  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
222  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
223 
224  // Allocate memory
225  classification = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
226  fileTemp = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
227  format = callocImageFormat ();
228 
229  // Reset status
230  *error = 0;
231  localError = 0;
232  fileNumber = 0;
233  waveCal->exists = 0;
234  format->hasData = 0;
235 
236  // Open the list of files
237  if ((inFitsBatchPtr = fopen (fileNames->inFitsBatch, "r")) == NULL)
238  {
239  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__,
240  "Cannot open input FITS file list. No compression has been carried out for this batch");
241  freeImageFormat (format);
242  free (fileTemp);
243  free (classification);
244  *error = 1;
245  return;
246  }
247 
248  // Loop through the files and analyse
249  while (fgets (fileTemp, MAX_STRING_LENGTH, inFitsBatchPtr) != NULL)
250  {
251  sprintf (classification, "%s", "");
252  sscanf (fileTemp, "%s%s", fileNames->inFitsName, classification);
253  if (diagnostic)cpl_msg_info(cpl_func,"\n Processing file %s \n", fileNames->inFitsName);
254  fprintf(midiReportPtr, "\n Processing file %s \n", fileNames->inFitsName);
255 
256  // Get 'extNumOfImagingDataFile' extension number of IMAGING_DATA in input file
257  extNumOfImagingDataFile = findImagingDataExtension (fileNames->inFitsName, TAB_IMAGING_DATA, &localError);
258  if (localError)
259  {
260  *error = 1;
261  break;
262  }
263 
264  // Get Image Format parameters
265  if (extNumOfImagingDataFile > 0)
266  {
267  getImageFormat (fileNames->inFitsName, extNumOfImagingDataFile, format, &localError);
268  if (localError)
269  {
270  *error = 1;
271  break;
272  }
273  }
274  else format->hasData = 0;
275 
276  // Check if the file has data
277  if (format->hasData)
278  {
279  // Check Categ, Tech and Type and then compute the image size
280  if ((strcmp (format->obsCatg, "CALIB") == 0) &&
281  (strcmp (format->obsTech, "SPECTRUM") == 0) &&
282  (strcmp (format->obsType, "WAVE,SPECTEMPL") == 0))
283  {
284  // Increment file number but make sure it is not greater than the allocated
285  fileNumber++;
286  if (fileNumber > numOfFiles)
287  {
288  *error = 1;
289  sprintf (midiMessage, "Inconsistent number of files. Expected %d. Found %d", numOfFiles, fileNumber);
290  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
291  break;
292  }
293 
294  // Save file IDs
295  sprintf (waveCal->shutterId[fileNumber-1], "%s", format->shutterId);
296  sprintf (waveCal->filterName[fileNumber-1], "%s", format->filterName);
297 
298  // Preprocess data
299  compressWaveCal (fileNumber-1, fileNames->inFitsName, extNumOfImagingDataFile, format, waveCal, &localError);
300  if (localError)
301  {
302  *error = 1;
303  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot preprocess");
304  continue;
305  }
306 
307  // Validate data
308  validateWaveCalData (fileNumber-1, fileNames->inFitsName, waveCal, format, &localError);
309  if (localError)
310  {
311  *error = 1;
312  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot validate data");
313  continue;
314  }
315  }
316  else
317  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, "The above file is not suitable for this task");
318  }
319  else
320  {
321  if (diagnostic)
322  {
323  sprintf (midiMessage, "No data tables in %s. Not processed", fileNames->inFitsName);
324  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
325  }
326  }
327  }
328 
329  // Issue an interim error message
330  if ((*error) || (fileNumber != numOfFiles))
331  {
332  sprintf (midiMessage, "Cannot do Wavelength Calibration. error=%d, numOfFiles=%d. Expected %d",
333  *error, fileNumber, numOfFiles);
334  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
335  fclose (inFitsBatchPtr);
336  freeImageFormat (format);
337  free (fileTemp);
338  free (classification);
339  return;
340  }
341 
342  // If so far all is well then carry out with the Calibration
343  waveCal->exists = 1;
344  cpl_msg_info(cpl_func,"\nWavelength Calibration Inventry: \n");
345  cpl_msg_info(cpl_func,"=============================== \n");
346  cpl_msg_info(cpl_func," Expected number of data files = %d\n", numOfFiles);
347  cpl_msg_info(cpl_func," Number of data files processed = %d\n", fileNumber);
348  cpl_msg_info(cpl_func,"\n");
349  fprintf (midiReportPtr, "\nWavelength Calibration Inventry: \n");
350  fprintf (midiReportPtr, "=============================== \n");
351  fprintf (midiReportPtr, " Expected number of data files = %d\n", numOfFiles);
352  fprintf (midiReportPtr, " Number of data files processed = %d\n", fileNumber);
353  fprintf (midiReportPtr, "\n");
354 
355  // Remove dark
356  removeDark (format, waveCal, error);
357 
358  // Perform Wavelength Calibration
359  calibrateWaveChannels (processing, fileNames, waveCal, format, error);
360 
361  // Close the file list
362  fclose (inFitsBatchPtr);
363 
364  // Release memory
365  freeImageFormat (format);
366  free (fileTemp);
367  free (classification);
368 
369  return;
370 }
371 /*****************************************************************************/
372 
373 
374 /******************************************************************************
375 * European Southern Observatory
376 * VLTI MIDI Maintenance Templates Software
377 *
378 * Module name: compressWaveCal
379 * Input/Output: See function arguments to avoid duplication
380 * Description: Compresses Wavelength Calibration raw data
381 *
382 * History:
383 * 10-Jun-05 (csabet) Created
384 ******************************************************************************/
385 void compressWaveCal (
386  int fileNumber, // In: File number
387  char *inFitsName, // In: Name of file to process
388  int extensionNumber,// In: Extension number of the IMAGE_DATA
389  ImageFormat *format, // In: Pointer to the image format
390  WaveCalibration *waveCal, // Ou: Pointer to the wavelength calibration
391  int *error) // Ou: Error status
392 
393 {
394 
395  // Local Declarations
396  // ------------------
397  const char routine[] = "compressWaveCal";
398  qfits_table *pTable=NULL;
399  short int **inData;
400  char *inTarType=NULL, *tempStr, *dataName, lastTT;
401  int i, pixel, *foundData, scalingOffset, *indexData, numOfSkyFrames, numOfFramesUsed,
402  frame, region, indexTarType, foundTarType, transitions, numOfUndefinedFrames,
403  numOfBadFrames, tartypMult;
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  // Reset status
411  *error = 0;
412  foundTarType = 0;
413 
414  /* Signifies that there are 2 (instead of 1!) characters per tartyp
415  value (only first is useful). In future, if the problem producing the MIDI
416  files is solved, can be changed to 1 (only for newer files) or made variable
417  (with some way to determine whether it is an "old" type file). Note: this problem
418  really has nothing to do with Qfits, but with the (unintended) way the files are written */
419  tartypMult = 2;
420 
421  // Allocate memory
422  inData = (short int **) calloc (format->numOfDetectorRegions, sizeof (short int *));
423  foundData = (int *) calloc (format->numOfDetectorRegions, sizeof (int));
424  indexData = (int *) calloc (format->numOfDetectorRegions, sizeof (int));
425  dataName = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
426 
427  // Open IMAGING_DATA = INDEX 2
428  pTable = qfits_table_open (inFitsName, extensionNumber);
429  if (!pTable)
430  {
431  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot load IMAGING_DATA");
432  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
433  free (foundData);
434  free (indexData);
435  free (dataName);
436  *error = 1;
437  return;
438  }
439 
440  // Get data table information
441  for (region = 0; region < format->numOfDetectorRegions; region++)
442  {
443  foundData[region] = 0;
444  indexData[region] = 0;
445  }
446  for (i = 0; i < pTable->nc; i++)
447  {
448  for (region = 0; region < format->numOfDetectorRegions; region++)
449  {
450  sprintf (dataName, "DATA%d", region+1);
451  if (strcmp (pTable->col[i].tlabel, dataName) == 0)
452  {
453  foundData[region] = 1;
454  indexData[region] = i;
455  if (diagnostic)cpl_msg_info(cpl_func,"Found 'DATA%d' at column %d in data file %s \n", region+1, i+1, inFitsName);
456  if (diagnostic) fprintf(midiReportPtr, "Found 'DATA%d' at column %d in data file %s \n", region+1, i+1, inFitsName);
457  }
458  }
459  if (strcmp (pTable->col[i].tlabel, "TARTYP2") == 0) // Now changed to TARTYP2, for all newer files
460  {
461  foundTarType = 1;
462  indexTarType = i;
463  }
464  }
465 
466  // Now issue warnings
467  if (foundTarType == 0)
468  {
469  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot find TARTYP2 in data FITS file");
470  *error = 1;
471  }
472  for (region = 0; region < format->numOfDetectorRegions; region++)
473  {
474  if (foundData[region] == 0)
475  {
476  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot find requested DATA column in data FITS file");
477  *error = 1;
478  }
479  }
480 
481  // Release memory and exit this module if there has been a warning. No point going any further
482  if (*error)
483  {
484  qfits_table_close (pTable);
485  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
486  free (foundData);
487  free (indexData);
488  free (dataName);
489  return;
490  }
491 
492  // Get TARTYP2
493  inTarType = (char *) qfits_query_column (pTable, indexTarType, NULL);
494  for (frame = 0; frame < format->numOfFrames; frame++)
495  waveCal->tarType[frame] = inTarType[frame*tartypMult]; // New way around tartype problem (JM)
496 
497  // Check if the data is chopped
498  transitions = 0;
499  lastTT = waveCal->tarType[0];
500  for (frame = 0; frame < format->numOfFrames; frame++)
501  {
502  if (waveCal->tarType[frame] == lastTT) continue;
503  transitions++; // INCLUDES transitions to U etc.
504  lastTT = waveCal->tarType[frame];
505  }
506  if ((format->chopped = (transitions > 10))) // Apparently is a chopped file
507  {
508  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Wavelength Calibration data is chopped");
509  *error = 1;
510  qfits_table_close (pTable);
511  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
512  free (foundData);
513  free (indexData);
514  free (dataName);
515  return;
516  }
517 
518  // Read all regions from input files
519  for (region = 0; region < format->numOfDetectorRegions; region++)
520  inData[region] = (short int*) qfits_query_column (pTable, indexData[region], NULL);
521 
522  // Get the scaling offset
523  for (i = 14; i < 25; i++)
524  {
525  sprintf (dataName, "TZERO%d", i);
526  tempStr = qfits_query_ext (inFitsName, dataName, extensionNumber);
527  if (tempStr != NULL)
528  {
529  if (diagnostic)cpl_msg_info(cpl_func,"Scaling Offset = %s\n", tempStr);
530  if (diagnostic) fprintf (midiReportPtr, "Scaling Offset = %s\n", tempStr);
531  sscanf (tempStr, "%d", &scalingOffset);
532  break;
533  }
534  }
535  if (tempStr == NULL)
536  {
537  scalingOffset = 0;
538  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot read Scaling Offset. It is set to 0");
539  }
540 
541  // Compression starts here
542  for (region = 0; region < format->numOfDetectorRegions; region++)
543  {
544  for (pixel = 0; pixel < format->subWindowSize; pixel++)
545  {
546  // Along the time axis (frame)
547  numOfUndefinedFrames = 0;
548  numOfBadFrames = 0;
549  numOfFramesUsed = 0;
550  numOfSkyFrames = 0;
551  if (strcmp (waveCal->filterName[fileNumber], "[ArIII]") == 0)
552  (waveCal->ArIII->image)[region][pixel] = 0.0;
553  else if (strcmp (waveCal->filterName[fileNumber], "[NeII]") == 0)
554  (waveCal->NeII->image)[region][pixel] = 0.0;
555  else if (strcmp (waveCal->filterName[fileNumber], "[SIV]") == 0)
556  (waveCal->SIV->image)[region][pixel] = 0.0;
557  else if (strcmp (waveCal->filterName[fileNumber], "WL-CALIB_2") == 0)
558  (waveCal->foil->image)[region][pixel] = 0.0;
559  else if (strcmp (waveCal->filterName[fileNumber], "OPEN") == 0)
560  (waveCal->open->image)[region][pixel] = 0.0;
561  else if (strcmp (waveCal->filterName[fileNumber], "CLOSED") == 0)
562  (waveCal->dark->image)[region][pixel] = 0.0;
563  else
564  {
565  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Unknown Filter ID");
566  *error = 1;
567  qfits_table_close (pTable);
568  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
569  free (foundData);
570  free (indexData);
571  free (dataName);
572  return;
573  }
574 
575  for (frame = 0; frame < format->numOfFrames; frame++)
576  {
577  // Only consider Target, "T" and Sky, "S"
578  if (waveCal->tarType[frame] == 'U')
579  {
580  if (diagnostic && !pixel)
581  {
582  sprintf (midiMessage, "Found undefined, 'U' 'TARTYP2' at frame %d of DATA%d in %s",
583  frame+1, region+1, inFitsName);
584  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
585  }
586  numOfUndefinedFrames++;
587  continue;
588  }
589 
590  // Load each pixel data along the time axis
591  i = frame * format->subWindowSize + pixel;
592  if (isnan (inData[region][i]))
593  {
594  numOfBadFrames++;
595  sprintf (midiMessage, "Found bad pixel %d of DATA%d in %s", i, region, inFitsName);
596  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
597  }
598  else
599  {
600  if (waveCal->tarType[frame] == 'S') numOfSkyFrames++;
601  numOfFramesUsed++;
602 
603  if (strcmp (waveCal->filterName[fileNumber], "[ArIII]") == 0)
604  (waveCal->ArIII->image)[region][pixel] += (float) (inData[region][i]);
605  else if (strcmp (waveCal->filterName[fileNumber], "[NeII]") == 0)
606  (waveCal->NeII->image)[region][pixel] += (float) (inData[region][i]);
607  else if (strcmp (waveCal->filterName[fileNumber], "[SIV]") == 0)
608  (waveCal->SIV->image)[region][pixel] += (float) (inData[region][i]);
609  else if (strcmp (waveCal->filterName[fileNumber], "WL-CALIB_2") == 0)
610  (waveCal->foil->image)[region][pixel] += (float) (inData[region][i]);
611  else if (strcmp (waveCal->filterName[fileNumber], "OPEN") == 0)
612  (waveCal->open->image)[region][pixel] += (float) (inData[region][i]);
613  else if (strcmp (waveCal->filterName[fileNumber], "CLOSED") == 0)
614  (waveCal->dark->image)[region][pixel] += (float) (inData[region][i]);
615  else
616  {
617  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Unknown Filter ID");
618  *error = 1;
619  qfits_table_close (pTable);
620  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
621  free (foundData);
622  free (indexData);
623  free (dataName);
624  return;
625  }
626  }
627  }
628 
629  // Compute average image
630  if (diagnostic && !pixel)
631  {
632  cpl_msg_info(cpl_func,"\nData Statistics \n");
633  cpl_msg_info(cpl_func,"--------------- \n");
634  cpl_msg_info(cpl_func,"Number of frames used in DATA%d = %d \n", region+1, numOfFramesUsed);
635  cpl_msg_info(cpl_func,"Number of Sky frames in DATA%d = %d \n", region+1, numOfSkyFrames);
636  cpl_msg_info(cpl_func,"Number of Bad frames in DATA%d = %d \n", region+1, numOfBadFrames);
637  cpl_msg_info(cpl_func,"Number of Undefined frames in DATA%d = %d \n", region+1, numOfUndefinedFrames);
638  fprintf (midiReportPtr, "\nData Statistics \n");
639  fprintf (midiReportPtr, "--------------- \n");
640  fprintf (midiReportPtr, "Number of frames used in DATA%d = %d \n", region+1, numOfFramesUsed);
641  fprintf (midiReportPtr, "Number of Sky frames in DATA%d = %d \n", region+1, numOfSkyFrames);
642  fprintf (midiReportPtr, "Number of Bad frames in DATA%d = %d \n", region+1, numOfBadFrames);
643  fprintf (midiReportPtr, "Number of Undefined frames in DATA%d = %d \n", region+1, numOfUndefinedFrames);
644  }
645  if (numOfFramesUsed)
646  {
647  if (strcmp (waveCal->filterName[fileNumber], "[ArIII]") == 0)
648  {
649  (waveCal->ArIII->image)[region][pixel] /= numOfFramesUsed;
650  (waveCal->ArIII->image)[region][pixel] += scalingOffset;
651  }
652  else if (strcmp (waveCal->filterName[fileNumber], "[NeII]") == 0)
653  {
654  (waveCal->NeII->image)[region][pixel] /= numOfFramesUsed;
655  (waveCal->NeII->image)[region][pixel] += scalingOffset;
656  }
657  else if (strcmp (waveCal->filterName[fileNumber], "[SIV]") == 0)
658  {
659  (waveCal->SIV->image)[region][pixel] /= numOfFramesUsed;
660  (waveCal->SIV->image)[region][pixel] += scalingOffset;
661  }
662  else if (strcmp (waveCal->filterName[fileNumber], "WL-CALIB_2") == 0)
663  {
664  (waveCal->foil->image)[region][pixel] /= numOfFramesUsed;
665  (waveCal->foil->image)[region][pixel] += scalingOffset;
666  }
667  else if (strcmp (waveCal->filterName[fileNumber], "OPEN") == 0)
668  {
669  (waveCal->open->image)[region][pixel] /= numOfFramesUsed;
670  (waveCal->open->image)[region][pixel] += scalingOffset;
671  }
672  else if (strcmp (waveCal->filterName[fileNumber], "CLOSED") == 0)
673  {
674  (waveCal->dark->image)[region][pixel] /= numOfFramesUsed;
675  (waveCal->dark->image)[region][pixel] += scalingOffset;
676  }
677  else
678  {
679  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Unknown Filter ID");
680  *error = 1;
681  qfits_table_close (pTable);
682  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
683  free (foundData);
684  free (indexData);
685  free (dataName);
686  return;
687  }
688  }
689  }
690  }
691 
692  // Clean up now:
693  for (region = 0; region < format->numOfDetectorRegions; region++) free (inData[region]);
694  if (pTable) qfits_table_close (pTable);
695  if (inTarType) free(inTarType);
696  free (inData);
697  free (foundData);
698  free (indexData);
699  free (dataName);
700 
701  return;
702 }
703 /*****************************************************************************/
704 
705 
706 /******************************************************************************
707 * European Southern Observatory
708 * VLTI MIDI Maintenance Templates Software
709 *
710 * Module name: validateWaveCalData
711 * Input/Output: See function arguments to avoid duplication
712 * Description: Validates the input data
713 *
714 * History:
715 * 13-Jun-05 (csabet) Created
716 ******************************************************************************/
717 void validateWaveCalData (
718  int fileNumber, // In: File number
719  char *fileName, // In: Input FITS name
720  WaveCalibration *compressed, // In: Compressed data
721  ImageFormat *format, // In: File format
722  int *error) // Ou: Error status
723 
724 {
725 
726  // Local Declarations
727  // ------------------
728  const char routine[] = "validateWaveCalData";
729  int region;
730  char *title=NULL, *fileString=NULL;
731 
732  // Algorithm
733  // ---------
734  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
735  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
736 
737  // Reset status
738  *error = 0;
739 
740  // Allocate memory
741  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
742  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
743 
744  // Analyse Raw Images
745  if (strcmp (compressed->filterName[fileNumber], "[ArIII]") == 0)
746  {
747  // Save file name
748  sprintf (compressed->ArIII->fileName, "%s", fileName);
749 
750  for (region = 0; region < format->numOfDetectorRegions; region++)
751  {
752 
753  // Create Raw Image FITS files
754  if (diagnostic)
755  {
756  sprintf (fileString , "region %d", region+1);
757  sprintf (title , "AveRawImgArIIIDATA%d", region+1);
758  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
759  (compressed->ArIII->image)[region]);
760 
761  if (plotFile)
762  {
763  sprintf (fileString, "3dAveRawImgArIIIDATA%d", region+1);
764  sprintf (title, "[ArIII] Raw, averaged along time, Region %d", region+1);
765  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
766  (compressed->ArIII->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
767  }
768  }
769  }
770  }
771  else if (strcmp (compressed->filterName[fileNumber], "[NeII]") == 0)
772  {
773  // Save file name
774  sprintf (compressed->NeII->fileName, "%s", fileName);
775 
776  for (region = 0; region < format->numOfDetectorRegions; region++)
777  {
778  // Create Raw Image FITS files
779  if (diagnostic)
780  {
781  sprintf (fileString , "region %d", region+1);
782  sprintf (title , "AveRawImgNeIIDATA%d", region+1);
783  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
784  (compressed->NeII->image)[region]);
785 
786  if (plotFile)
787  {
788  sprintf (fileString, "3dAveRawImgNeIIDATA%d", region+1);
789  sprintf (title, "[NeII] Raw, averaged along time, Region %d", region+1);
790  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
791  (compressed->NeII->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
792  }
793  }
794  }
795  }
796  else if (strcmp (compressed->filterName[fileNumber], "[SIV]") == 0)
797  {
798  // Save file name
799  sprintf (compressed->SIV->fileName, "%s", fileName);
800 
801  for (region = 0; region < format->numOfDetectorRegions; region++)
802  {
803  // Create Raw Image FITS files
804  if (diagnostic)
805  {
806  sprintf (fileString , "region %d", region+1);
807  sprintf (title , "AveRawImgSIVDATA%d", region+1);
808  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
809  (compressed->SIV->image)[region]);
810 
811  if (plotFile)
812  {
813  sprintf (fileString, "3dAveRawImgSIVDATA%d", region+1);
814  sprintf (title, "[SIV] Raw, averaged along time, Region %d", region+1);
815  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
816  (compressed->SIV->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
817  }
818  }
819  }
820  }
821  else if (strcmp (compressed->filterName[fileNumber], "WL-CALIB_2") == 0)
822  {
823  // Save file name
824  sprintf (compressed->foil->fileName, "%s", fileName);
825 
826  for (region = 0; region < format->numOfDetectorRegions; region++)
827  {
828  // Create Raw Image FITS files
829  if (diagnostic)
830  {
831  sprintf (fileString , "region %d", region+1);
832  sprintf (title , "AveRawImgFoilDATA%d", region+1);
833  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
834  (compressed->foil->image)[region]);
835 
836  if (plotFile)
837  {
838  sprintf (fileString, "3dAveRawImgFoilDATA%d", region+1);
839  sprintf (title, "Foil Raw, averaged along time, Region %d", region+1);
840  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
841  (compressed->foil->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
842  }
843  }
844  }
845  }
846  else if (strcmp (compressed->filterName[fileNumber], "OPEN") == 0)
847  {
848  // Save file name
849  sprintf (compressed->open->fileName, "%s", fileName);
850 
851  for (region = 0; region < format->numOfDetectorRegions; region++)
852  {
853  // Create Raw Image FITS files
854  if (diagnostic)
855  {
856  sprintf (fileString , "region %d", region+1);
857  sprintf (title , "AveRawImgOpenDATA%d", region+1);
858  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
859  (compressed->open->image)[region]);
860 
861  if (plotFile)
862  {
863  sprintf (fileString, "3dAveRawImgOpenDATA%d", region+1);
864  sprintf (title, "Open Raw, averaged along, Region %d", region+1);
865  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
866  (compressed->open->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
867  }
868  }
869  }
870  }
871  else if (strcmp (compressed->filterName[fileNumber], "CLOSED") == 0)
872  {
873  // Save file name
874  sprintf (compressed->dark->fileName, "%s", fileName);
875 
876  for (region = 0; region < format->numOfDetectorRegions; region++)
877  {
878  // Create Raw Image FITS files
879  if (diagnostic)
880  {
881  sprintf (fileString , "region %d", region+1);
882  sprintf (title , "AveRawImgDarkDATA%d", region+1);
883  createFitsImage (fileString, title, fileName, format->iXWidth, format->iYWidth,
884  (compressed->dark->image)[region]);
885 
886  if (plotFile)
887  {
888  sprintf (fileString, "3dAveRawImgDarkDATA%d", region+1);
889  sprintf (title, "Dark Raw, averaged along time, Region %d", region+1);
890  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
891  (compressed->dark->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
892  }
893  }
894  }
895  }
896  else
897  {
898  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Unknown Filter ID");
899  *error = 1;
900  free (title);
901  free (fileString);
902  return;
903  }
904 
905 
906  // Release memory
907  free (title);
908  free (fileString);
909 
910  return;
911 }
912 /*****************************************************************************/
913 
914 
915 /******************************************************************************
916 * European Southern Observatory
917 * VLTI MIDI Maintenance Templates Software
918 *
919 * Module name: getWlCalib2Spectra
920 * Input/Output: See function arguments to avoid duplication
921 * Description: Get WL-CALIB_2 spectra. Returns -1 if error
922 *
923 * History:
924 * 20-Jun-05 (csabet) Created
925 ******************************************************************************/
926 int getWlCalib2Spectra (
927  MidiFiles *fileNames, // In: Pointer to file names
928  int *error) // Ou: Error status
929 
930 {
931 
932  // Local Declarations
933  // ------------------
934  const char routine[] = "getWlCalib2Spectra";
935  FILE *wlFilePtr=NULL;
936  int numOfRecords;
937  char *filePath, *tempString;
938  float elem1, elem2;
939 
940  // Algorithm
941  // ---------
942  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
943  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
944 
945  // Reset status
946  *error = 0;
947  numOfRecords = 0;
948 
949  // Allocate memory
950  filePath = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
951  tempString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
952 
953  // Check the tracing record for WL-CALIB_2 foil
954  // --------------------------------------------
955  sprintf (filePath, "%swl-calib_2.dat", fileNames->calibDbDir);
956  if ((wlFilePtr = fopen (filePath, "r")) == NULL)
957  {
958  sprintf (midiMessage, "Cannot Open %s", filePath);
959  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
960  free (filePath);
961  free (tempString);
962  *error = 1;
963  return (-1);
964  }
965  // Ignore first record which gives the title of the data file
966  fgets (tempString, MAX_STRING_LENGTH, wlFilePtr);
967  sprintf (midiMessage, "Counting elements in %s", tempString);
968  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
969  while (fscanf (wlFilePtr, "%f %f\n", &elem1, &elem2) != EOF)
970  numOfRecords++;
971  sprintf (midiMessage, "WL-CALIB_2 has %d pairs of 'float'(s)", numOfRecords);
972  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
973  fclose (wlFilePtr);
974 
975  // Release memory
976  free (filePath);
977  free (tempString);
978 
979  return (numOfRecords);
980 }
981 /*****************************************************************************/
982 
983 
984 
985 /******************************************************************************
986 * European Southern Observatory
987 * VLTI MIDI Maintenance Templates Software
988 *
989 * Module name: removeDark
990 * Input/Output: See function arguments to avoid duplication
991 * Description: Extracts all the necessary resources for calibration
992 *
993 * History:
994 * 14-June-05 (csabet) Created
995 ******************************************************************************/
996 void removeDark (
997  ImageFormat *format, // In: File format
998  WaveCalibration *waveCal, // In: Compressed data
999  int *error) // Ou: Error status
1000 
1001 {
1002 
1003  // Local Declarations
1004  // ------------------
1005  const char routine[] = "removeDark";
1006  int region, pixel;
1007  char *title=NULL, *fileString=NULL;
1008 
1009  // Algorithm
1010  // ---------
1011  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1012  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1013 
1014  // Reset status
1015  *error = 0;
1016 
1017  // Allocate memory
1018  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1019  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1020 
1021  // Get images with dark subtracted
1022  for (region = 0; region < format->numOfDetectorRegions; region++)
1023  {
1024  for (pixel = 0; pixel < format->subWindowSize; pixel++)
1025  {
1026  (waveCal->ArIII->image)[region][pixel] -= (waveCal->dark->image)[region][pixel];
1027  (waveCal->NeII->image)[region][pixel] -= (waveCal->dark->image)[region][pixel];
1028  (waveCal->SIV->image)[region][pixel] -= (waveCal->dark->image)[region][pixel];
1029  (waveCal->foil->image)[region][pixel] -= (waveCal->dark->image)[region][pixel];
1030  (waveCal->open->image)[region][pixel] -= (waveCal->dark->image)[region][pixel];
1031  }
1032  }
1033 
1034  // Create Image FITS files
1035  for (region = 0; region < format->numOfDetectorRegions; region++)
1036  {
1037  sprintf (fileString , "region %d", region+1);
1038  sprintf (title , "AveImgArIIIDATA%d", region+1);
1039  createFitsImage (fileString, title, waveCal->ArIII->fileName, format->iXWidth, format->iYWidth,
1040  (waveCal->ArIII->image)[region]);
1041  }
1042 
1043  for (region = 0; region < format->numOfDetectorRegions; region++)
1044  {
1045  sprintf (fileString , "region %d", region+1);
1046  sprintf (title , "AveImgNeIIDATA%d", region+1);
1047  createFitsImage (fileString, title, waveCal->NeII->fileName, format->iXWidth, format->iYWidth,
1048  (waveCal->NeII->image)[region]);
1049  }
1050 
1051  for (region = 0; region < format->numOfDetectorRegions; region++)
1052  {
1053  sprintf (fileString , "region %d", region+1);
1054  sprintf (title , "AveImgSIVDATA%d", region+1);
1055  createFitsImage (fileString, title, waveCal->SIV->fileName, format->iXWidth, format->iYWidth,
1056  (waveCal->SIV->image)[region]);
1057  }
1058 
1059  for (region = 0; region < format->numOfDetectorRegions; region++)
1060  {
1061  sprintf (fileString , "region %d", region+1);
1062  sprintf (title , "AveImgFoilDATA%d", region+1);
1063  createFitsImage (fileString, title, waveCal->foil->fileName, format->iXWidth, format->iYWidth,
1064  (waveCal->foil->image)[region]);
1065  }
1066 
1067  for (region = 0; region < format->numOfDetectorRegions; region++)
1068  {
1069  sprintf (fileString , "region %d", region+1);
1070  sprintf (title , "AveImgOpenDATA%d", region+1);
1071  createFitsImage (fileString, title, waveCal->open->fileName, format->iXWidth, format->iYWidth,
1072  (waveCal->open->image)[region]);
1073  }
1074 
1075  // Create 3D plots
1076  if (plotFile)
1077  {
1078  for (region = 0; region < format->numOfDetectorRegions; region++)
1079  {
1080  sprintf (fileString, "3dAveImgArIIIDATA%d", region+1);
1081  sprintf (title, "[ArIII] Dark removed, averaged along time, Region %d", region+1);
1082  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
1083  (waveCal->ArIII->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
1084  }
1085 
1086  for (region = 0; region < format->numOfDetectorRegions; region++)
1087  {
1088  sprintf (fileString, "3dAveImgNeIIDATA%d", region+1);
1089  sprintf (title, "[NeII] Dark removed, averaged along time, Region %d", region+1);
1090  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
1091  (waveCal->NeII->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
1092  }
1093 
1094  for (region = 0; region < format->numOfDetectorRegions; region++)
1095  {
1096  sprintf (fileString, "3dAveImgSIVDATA%d", region+1);
1097  sprintf (title, "[SIV] Dark removed, averaged along time, Region %d", region+1);
1098  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
1099  (waveCal->SIV->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
1100  }
1101 
1102  for (region = 0; region < format->numOfDetectorRegions; region++)
1103  {
1104  sprintf (fileString, "3dAveImgFoilDATA%d", region+1);
1105  sprintf (title, "Foil Dark removed, averaged along time, Region %d", region+1);
1106  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
1107  (waveCal->foil->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
1108  }
1109 
1110  for (region = 0; region < format->numOfDetectorRegions; region++)
1111  {
1112  sprintf (fileString, "3dAveImgOpenDATA%d", region+1);
1113  sprintf (title, "Open Dark removed, averaged along time, Region %d", region+1);
1114  midiCreatePlotFile3D (fileString, title, "X", "Y", "Flux", 0,
1115  (waveCal->open->image)[region], format->iXWidth, format->iYWidth, "lines", "3");
1116  }
1117  }
1118 
1119  // Release memory
1120  free (title);
1121  free (fileString);
1122 
1123  return;
1124 }
1125 /*****************************************************************************/
1126 
1127 
1128 
1129 /******************************************************************************
1130 * European Southern Observatory
1131 * VLTI MIDI Maintenance Templates Software
1132 *
1133 * Module name: calibrateWaveChannels
1134 * Input/Output: See function arguments to avoid duplication
1135 * Description: Perform the final wavelength calibration.
1136 * 1. From the three filter files get three wavelengths for three channels.
1137 * A linear fit gives the function (table) Wavelength [X], X = 0, N
1138 * where N is the number of channels
1139 *
1140 * Filter Pk Freq. Pk Wavelength
1141 * ======================================
1142 * NeII 2.34297e+13 Hz 12.7955 micron
1143 * SIV 2.85818e+13 Hz 10.489 micron
1144 * ArIII 3.33005e+13 Hz 9.00272 micron
1145 *
1146 * 2. From the polycarbonate foil template, get the function (table)
1147 * Flux [x], x = 0, N, where N is the number of channels.
1148 *
1149 * 3. From the manufacturer's table get the function (table)
1150 * Flux [l], l = 0, W, where W is the number of wavelength positions
1151 *
1152 * History:
1153 * 14-June-05 (csabet)
1154 ******************************************************************************/
1155 void calibrateWaveChannels (
1156  int processing, // In: Correlate = 1, Create = 2
1157  MidiFiles *fileNames, // In: Pointer to file names
1158  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
1159  ImageFormat *format, // In: Pointer to the image format
1160  int *error) // Ou: Error status
1161 
1162 {
1163 
1164  // Local Declarations
1165  // ------------------
1166  const char routine[] = "calibrateWaveChannels";
1167 
1168  // Algorithm
1169  // ---------
1170  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1171  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1172 
1173  // Reset status
1174  *error = 0;
1175 
1176  // Fitting of Filter Spectra
1177  fitFilterSpectra (waveCal, format, error);
1178 
1179  // Get approximate channel assignment
1180  calibrateWaveFromNBF (waveCal, format, error);
1181  if (*error) return;
1182 
1183  // Fitting of Foil Spectra frequency
1184  fitFoilSpectra (fileNames, waveCal, format, error);
1185 
1186  // Fitting of Open Spectra
1187  fitOpenSpectra (error);
1188 
1189  // Create frequency calibration database
1190  if (processing == 2) createWaveCalibDB (fileNames, waveCal, format, error);
1191  else correlateWaveCalibDB (fileNames, waveCal, format, error);
1192 
1193  return;
1194 }
1195 /*****************************************************************************/
1196 
1197 
1198 /******************************************************************************
1199 * European Southern Observatory
1200 * VLTI MIDI Maintenance Templates Software
1201 *
1202 * Module name: calibrateWaveFromNBF
1203 * Input/Output: See function arguments to avoid duplication
1204 * Description: Creates an approximate wavelength calibration file based on the
1205 * Narrow Band Filter (NBF) spectra only
1206 *
1207 * History:
1208 * 08-Sep-05 (csabet)
1209 ******************************************************************************/
1210 void calibrateWaveFromNBF (
1211  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
1212  ImageFormat *format, // In: Pointer to the image format
1213  int *error) // Ou: Error status
1214 
1215 {
1216 
1217  // Local Declarations
1218  // ------------------
1219  const char routine[] = "calibrateWaveFromNBF";
1220  int region, *channel, chA, chN, chS, numOfNBF, order;
1221  float *wave, *chFloat;
1222  char *fileString, *title;
1223 
1224  // Algorithm
1225  // ---------
1226  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1227  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1228 
1229  // Reset status
1230  *error = 0;
1231  numOfNBF = 3;
1232 
1233  // Allocate memory
1234  channel = (int *) calloc (numOfNBF, sizeof (int));
1235  wave = (float *) calloc (numOfNBF, sizeof (float));
1236 
1237  for (region = 0; region < format->numOfDetectorRegions; region++)
1238  {
1239  // Sort channels
1240  channel[0] = (waveCal->ArIII->xCoord)[region];
1241  channel[1] = (waveCal->NeII->xCoord)[region];
1242  channel[2] = (waveCal->SIV->xCoord)[region];
1243  chA = (waveCal->ArIII->xCoord)[region];
1244  chN = (waveCal->NeII->xCoord)[region];
1245  chS = (waveCal->SIV->xCoord)[region];
1246  signalSortInt (channel, 0, numOfNBF);
1247 
1248  // Correct alignment
1249  if (channel[0] == chA) wave[0] = (waveCal->ArIII->wavelength)[region];
1250  else if (channel[0] == chN) wave[0] = (waveCal->NeII->wavelength)[region];
1251  else wave[0] = (waveCal->SIV->wavelength)[region];
1252 
1253  if (channel[1] == chA) wave[1] = (waveCal->ArIII->wavelength)[region];
1254  else if (channel[1] == chN) wave[1] = (waveCal->NeII->wavelength)[region];
1255  else wave[1] = (waveCal->SIV->wavelength)[region];
1256 
1257  if (channel[2] == chA) wave[2] = (waveCal->ArIII->wavelength)[region];
1258  else if (channel[2] == chN) wave[2] = (waveCal->NeII->wavelength)[region];
1259  else wave[2] = (waveCal->SIV->wavelength)[region];
1260 
1261  if (plotFile)
1262  {
1263  chFloat = (float *) calloc (3, sizeof (float));
1264  chFloat[0] = (float) channel[0];
1265  chFloat[1] = (float) channel[1];
1266  chFloat[2] = (float) channel[2];
1267  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1268  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1269  sprintf (fileString , "NarrowBandFilterSectionalProfileDATA%d", region+1);
1270  sprintf (title , "Narrow Band Filter Sectional Profile Region %d", region+1);
1271  midiCreatePlotFile2D2P (fileString, title, "Detector Channel", "Wavelength in micron", 0, chFloat, wave, 0, 3, 1);
1272  free (fileString);
1273  free (title);
1274  free (chFloat);
1275  }
1276 
1277  // Calibrate using a polynomial fit of order
1278  cpl_msg_info(cpl_func,"\nCalibrating wavelength for region %d \n", region+1);
1279  cpl_msg_info(cpl_func,"--------------------------------- \n");
1280  fprintf (midiReportPtr, "\nCalibrating wavelength for region %d \n", region+1);
1281  fprintf (midiReportPtr, "--------------------------------- \n");
1282  order = 22;
1283  midiPolyFit (order, channel, wave, numOfNBF, format->iXWidth, waveCal->calibratedWave[region], error);
1284  if (*error)
1285  {
1286  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot Calibrate");
1287  free (channel);
1288  free (wave);
1289  return;
1290  }
1291 
1292  if (plotFile)
1293  {
1294  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1295  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1296  sprintf (fileString , "CalibrationUsingPoly%dFitDATA%d", order/10, region+1);
1297  sprintf (title , "Calibration using a Polynomial fit of order %d for Region %d", order/10, region+1);
1298  midiCreatePlotFile2D (fileString, title, "Detector Channel", "Wavelength in micron",
1299  0, waveCal->calibratedWave[region], 0, format->iXWidth, 1, 0);
1300  free (fileString);
1301  free (title);
1302  }
1303  }
1304 
1305  // Release memory
1306  free (channel);
1307  free (wave);
1308 
1309  return;
1310 }
1311 /*****************************************************************************/
1312 
1313 
1314 
1315 
1316 /******************************************************************************
1317 * European Southern Observatory
1318 * VLTI MIDI Maintenance Templates Software
1319 *
1320 * Module name: midiPolyFit
1321 * Input/Output: See function arguments to avoid duplication
1322 * Description: A polynomial fit of various orders. We use two simple (fast)
1323 * but specific routines together with two general methods as follows:
1324 * 10 Simple and fast first order (for diagnostics only)
1325 * 20 Simple and fast 2nd order deterministic (for diagnostics only)
1326 * 11 First order based on minimising chi-squared. Returns full set of statistics
1327 * 22 Second order returning Mean Squared Error only
1328 *
1329 * History:
1330 * 14-June-05 (csabet)
1331 ******************************************************************************/
1332 void midiPolyFit (
1333  int order, // In: Order (see above)
1334  int *xCoord, // In: Array of elements along X
1335  float *yCoord, // In: array of elements along Y
1336  int numOfIn, // In: Number of input points
1337  int numOfOut, // In: Number of output points
1338  float *yOut, // Ou: Pointer to the output result
1339  int *error) // Ou: Error status
1340 
1341 {
1342 
1343  // Local Declarations
1344  // ------------------
1345  const char routine[] = "midiPolyFit";
1346  float x1, x1s, x2, x2s, x3, x3s, y1, y2, y3, d, d1, d2, d3,
1347  coeff1, coeff2, coeff3, q, chi2, siga, sigb, sigc, sigData;
1348  cpl_polynomial *coeffPoly;
1349  cpl_vector *xPoly, *yPoly;
1350  int i, degPoly, sigDataAvailable;
1351  cpl_size power=0;
1352  double *valuePloy, *positionPoly, mse;
1353 
1354 
1355  // Algorithm
1356  // ---------
1357  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1358  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1359 
1360  // Reset status
1361  *error = 0;
1362  coeff1=coeff2=coeff3=0.0;
1363  siga=sigb=sigc=chi2=q=mse=-1;
1364 
1365  // Exception
1366  if (order == 10)
1367  {
1368  cpl_msg_info(cpl_func,"Fitting %d points to %d points using Fast-Simple 1st order polynomial \n", numOfIn, numOfOut);
1369  fprintf (midiReportPtr, "Fitting %d points to %d points using Fast-Simple 1st order polynomial \n", numOfIn, numOfOut);
1370 
1371  // Assign short form
1372  x1 = xCoord[0];
1373  x2 = xCoord[1];
1374  x3 = xCoord[2];
1375  y1 = yCoord[0];
1376  y2 = yCoord[1];
1377  y3 = yCoord[2];
1378 
1379  // Coefficients for a line going through extreme points are
1380  coeff1 = y1 - x1 * ((y3 - y1) / (x3 - x1));
1381  coeff2 = (y3 - y1) / (x3 - x1);
1382  if (diagnostic)cpl_msg_info(cpl_func,"Initial coefficients are: %f %f \n", coeff1, coeff2);
1383  if (diagnostic) fprintf (midiReportPtr, "Initial coefficients are: %f %f \n", coeff1, coeff2);
1384 
1385  // Distance of middle point is
1386  d = fabs ((coeff2 * x2 - y2 + coeff1) / sqrt (coeff2 * coeff2 + 1));
1387 
1388  // Update coeff1 for half the distance
1389  coeff1 = 0.5 * d * sqrt(coeff2 * coeff2 + 1) - coeff2 * x2 + y2;
1390  }
1391  else if (order == 20)
1392  {
1393  cpl_msg_info(cpl_func,"Fitting %d points to %d points using Fast-Simple 2nd order polynomial \n", numOfIn, numOfOut);
1394  fprintf (midiReportPtr, "Fitting %d points to %d points using Fast-Simple 2nd order polynomial \n", numOfIn, numOfOut);
1395 
1396  // Assign short form
1397  x1 = xCoord[0];
1398  x2 = xCoord[1];
1399  x3 = xCoord[2];
1400  x1s = xCoord[0] * xCoord[0];
1401  x2s = xCoord[1] * xCoord[1];
1402  x3s = xCoord[2] * xCoord[2];
1403  y1 = yCoord[0];
1404  y2 = yCoord[1];
1405  y3 = yCoord[2];
1406 
1407  d = (x2 * x3s - x2s * x3) - x1 * (x3s - x2s) + x1s * (x3 - x2);
1408  d1 = y1 * (x2 * x3s - x2s * x3) - x1 * (y2 * x3s - x2s * y3) + x1s * (y2 * x3 - x2 * y3);
1409  d2 = (y2 * x3s - x2s * y3) - y1 * (x3s - x2s) + x1s * (y3 - y2);
1410  d3 = (x2 * y3 - y2 * x3) - x1 * (y3 - y2) + y1 * (x3 - x2);
1411 
1412  coeff1 = d1/d;
1413  coeff2 = d2/d;
1414  coeff3 = d3/d;
1415  }
1416  else if (order == 11)
1417  {
1418  cpl_msg_info(cpl_func,"Fitting %d points to %d points using 1st order polynomial \n", numOfIn, numOfOut);
1419  fprintf (midiReportPtr, "Fitting %d points to %d points using 1st order polynomial \n", numOfIn, numOfOut);
1420 
1421  // Load input data
1422  valuePloy = (double *) calloc (numOfIn, sizeof (double));
1423  positionPoly = (double *) calloc (numOfIn, sizeof (double));
1424  for (i = 0; i < numOfIn; i++)
1425  {
1426  positionPoly[i] = (double) (xCoord[i]);
1427  valuePloy[i] = (double) (yCoord[i]);
1428  }
1429 
1430  // We assume no knowledge of standard deviation on input data
1431  sigData = 0.0;
1432  sigDataAvailable = 0;
1433  midiGetLinearFit (positionPoly, valuePloy, numOfIn, sigData, sigDataAvailable,
1434  &coeff1, &coeff2, &siga, &sigb, &chi2, &q, error);
1435  free (positionPoly);
1436  free (valuePloy);
1437  if (*error)
1438  {
1439  sprintf (midiMessage, "Cannot compute linear fit in routine '%s'", routine);
1440  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
1441  return;
1442  }
1443  }
1444  else if (order == 22)
1445  {
1446  cpl_msg_info(cpl_func,"Fitting %d points to %d points using 2nd order polynomial \n", numOfIn, numOfOut);
1447  fprintf (midiReportPtr, "Fitting %d points to %d points using 2nd order polynomial \n", numOfIn, numOfOut);
1448 
1449  // Load input data
1450  valuePloy = (double *) calloc (numOfIn, sizeof (double));
1451  positionPoly = (double *) calloc (numOfIn, sizeof (double));
1452  for (i = 0; i < numOfIn; i++)
1453  {
1454  positionPoly[i] = (double) (xCoord[i]);
1455  valuePloy[i] = (double) (yCoord[i]);
1456  }
1457 
1458  degPoly = 2;
1459  xPoly = cpl_vector_wrap (numOfIn, positionPoly);
1460  yPoly = cpl_vector_wrap (numOfIn, valuePloy);
1461  coeffPoly = cpl_polynomial_fit_1d_create (xPoly, yPoly, degPoly, &mse);
1462  power = 0;
1463  coeff1 = cpl_polynomial_get_coeff (coeffPoly, &power);
1464  power = 1;
1465  coeff2 = cpl_polynomial_get_coeff (coeffPoly, &power);
1466  power = 2;
1467  coeff3 = cpl_polynomial_get_coeff (coeffPoly, &power);
1468 
1469  // Release memory
1470  cpl_vector_unwrap (xPoly);
1471  cpl_vector_unwrap (yPoly);
1472  cpl_polynomial_delete (coeffPoly);
1473  free (positionPoly);
1474  free (valuePloy);
1475  }
1476  else
1477  {
1478  *error = 1;
1479  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Invalid polynomial order");
1480  return;
1481  }
1482 
1483  cpl_msg_info(cpl_func,"Coeffient 1, Uncertainty = (%f, %f) \n", coeff1, siga);
1484  cpl_msg_info(cpl_func,"Coeffient 2, Uncertainty = (%f, %f) \n", coeff2, sigb);
1485  cpl_msg_info(cpl_func,"Coeffient 3, Uncertainty = (%f, %f) \n", coeff3, sigc);
1486  cpl_msg_info(cpl_func,"Mean Squared Error = %g \n", mse);
1487  cpl_msg_info(cpl_func,"Chi-squared = %f \n", chi2);
1488  cpl_msg_info(cpl_func,"Goodness-of-fit = %f \n", q);
1489  fprintf (midiReportPtr, "Coeffient 1, Uncertainty = (%f, %f) \n", coeff1, siga);
1490  fprintf (midiReportPtr, "Coeffient 2, Uncertainty = (%f, %f) \n", coeff2, sigb);
1491  fprintf (midiReportPtr, "Coeffient 3, Uncertainty = (%f, %f) \n", coeff3, sigc);
1492  fprintf (midiReportPtr, "Mean Squared Error = %g \n", mse);
1493  fprintf (midiReportPtr, "Chi-squared = %f \n", chi2);
1494  fprintf (midiReportPtr, "Goodness-of-fit = %f \n", q);
1495 
1496  cpl_msg_info(cpl_func,"NB. negative values for the statistics indicate unavailability \n");
1497  fprintf (midiReportPtr, "NB. negative values for the statistics indicate unavailability \n");
1498 
1499 
1500  // Fill in the output array using
1501  for (i = 0; i < numOfOut; i++)
1502  yOut[i] = (coeff1) + (coeff2 * i) + (coeff3 * i * i);
1503 
1504  return;
1505 }
1506 /*****************************************************************************/
1507 
1508 
1509 
1510 /******************************************************************************
1511 * European Southern Observatory
1512 * VLTI MIDI Maintenance Templates Software
1513 *
1514 * Module name: correlateWaveCalibDB
1515 * Input/Output: See function arguments to avoid duplication
1516 * Description: Correlates the real-time template with that in the database
1517 *
1518 * History:
1519 * 08-Sep-05 (csabet)
1520 ******************************************************************************/
1521 void correlateWaveCalibDB (
1522  MidiFiles *fileNames, // In: Pointer to file names
1523  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
1524  ImageFormat *format, // In: Pointer to the image format
1525  int *error) // Ou: Error status
1526 
1527 {
1528 
1529  // Local Declarations
1530  // ------------------
1531  const char routine[] = "correlateWaveCalibDB";
1532  int i, region;
1533  float *arrayError, **waveTable, standDev;
1534  char *fileString, *title, *fileName;
1535  FILE *filePtr=NULL;
1536 
1537  // Algorithm
1538  // ---------
1539  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1540  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1541 
1542  // Reset status
1543  *error = 0;
1544 
1545  cpl_msg_info(cpl_func,"\nCorrelating template with the database \n");
1546  cpl_msg_info(cpl_func,"-------------------------------------- \n");
1547  fprintf (midiReportPtr, "\nCorrelating template with the database \n");
1548  fprintf (midiReportPtr, "-------------------------------------- \n");
1549 
1550  // Allocate memory
1551  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1552  arrayError = (float *) calloc (format->iXWidth, sizeof (float));
1553  waveTable = (float **) calloc (format->numOfDetectorRegions, sizeof (float *));
1554  for (region = 0; region < format->numOfDetectorRegions; region++)
1555  waveTable[region] = calloc (format->iXWidth, sizeof (float));
1556 
1557  // We know that this file exists in the calibration database and it's consistent
1558  sprintf (fileString , "%s_%s_%s.dat", fileNames->waveCalibName, format->grismId, format->beamCombiner);
1559  if ((filePtr = fopen (fileString, "r")) != NULL) // It is in the database
1560  {
1561  // Read from file and load into array
1562  cpl_msg_info(cpl_func,"Reading Wavelength Calibration file ... %s \n", fileString);
1563  fprintf (midiReportPtr, "Reading Wavelength Calibration file ... %s \n", fileString);
1564  i = 0;
1565  // Read calibrated frequency from the database in THz
1566  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
1567  {
1568  while (fscanf (filePtr, "%f %f %f %f\n", &(waveTable[0][i]), &(waveTable[1][i]),
1569  &(waveTable[2][i]), &(waveTable[3][i])) != EOF) i++;
1570  }
1571  else
1572  {
1573  while (fscanf (filePtr, "%f %f \n", &(waveTable[0][i]), &(waveTable[1][i])) != EOF) i++;
1574  }
1575 
1576  fclose (filePtr);
1577  cpl_msg_info(cpl_func,"Read %d wavelength values in micron \n", i*format->numOfDetectorRegions);
1578  fprintf (midiReportPtr, "Read %d pairs of wavelengths in micron \n", i);
1579 
1580  // Do correlation
1581  for (region = 0; region < format->numOfDetectorRegions; region++)
1582  {
1583  // Compute error series
1584  for (i = 0; i < format->iXWidth; i++)
1585  arrayError[i] = waveCal->calibratedWave[region][i] - waveTable[region][i];
1586 
1587  if (plotFile)
1588  {
1589  fileName = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1590  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1591 
1592  sprintf (fileName , "WavelengthCalibDataBaseDATA%d", region+1);
1593  sprintf (title , "Wavelength Calibration from Database, Region %d", region+1);
1594  midiCreatePlotFile2D (fileName, title, "Channel", "Wavelength in micro", 0,
1595  waveTable[region], 0, format->iXWidth, 1, 0);
1596 
1597  sprintf (fileName , "WavelengthCalibCurrentTemplateDATA%d", region+1);
1598  sprintf (title , "Wavelength Calibration for Current template, Region %d", region+1);
1599  midiCreatePlotFile2D (fileName, title, "Channel", "Wavelength in micron", 0,
1600  waveCal->calibratedWave[region], 0, format->iXWidth, 1, 0);
1601 
1602  sprintf (fileName , "CorrelationErrorDATA%d", region+1);
1603  sprintf (title , "Correlation Error of Region %d", region+1);
1604  midiCreatePlotFile2D (fileName, title, "Channel", "Wavelength in micron", 0,
1605  arrayError, 0, format->iXWidth, 1, 0);
1606  free (fileName);
1607  free (title);
1608  }
1609 
1610  // Compute variance
1611  waveCal->variance[region] = signalVariance (arrayError, 0, format->iXWidth, &standDev);
1612  cpl_msg_info(cpl_func,"Error Variance for region %d = %f \n", region+1, waveCal->variance[region]);
1613  fprintf (midiReportPtr, "Error Variance for region %d = %f \n", region+1, waveCal->variance[region]);
1614  }
1615  }
1616  else
1617  {
1618  *error = 1;
1619  sprintf (midiMessage, "Cannot find calibration data file ... %s. Nothing to correlate", fileString);
1620  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
1621  }
1622 
1623  // Release memory
1624  free (fileString);
1625  free (arrayError);
1626  for (region = 0; region < format->numOfDetectorRegions; region++) free (waveTable[region]);
1627  free (waveTable);
1628 
1629  return;
1630 }
1631 /*****************************************************************************/
1632 
1633 
1634 /******************************************************************************
1635 * European Southern Observatory
1636 * VLTI MIDI Maintenance Templates Software
1637 *
1638 * Module name: createWaveCalibDB
1639 * Input/Output: See function arguments to avoid duplication
1640 * Description: Creates an approximate wavelength calibration file based on the
1641 * Narrow band filter spectra only
1642 *
1643 * History:
1644 * 08-Sep-05 (csabet)
1645 ******************************************************************************/
1646 void createWaveCalibDB (
1647  MidiFiles *fileNames, // In: Pointer to file names
1648  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
1649  ImageFormat *format, // In: Pointer to the image format
1650  int *error) // Ou: Error status
1651 
1652 {
1653 
1654  // Local Declarations
1655  // ------------------
1656  const char routine[] = "createWaveCalibDB";
1657  char *fileString, *title;
1658  FILE *filePtr=NULL;
1659  int i, region;
1660 
1661  // Algorithm
1662  // ---------
1663  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1664  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1665 
1666  // Reset status
1667  *error = 0;
1668 
1669  // Plot for diagnostic
1670  if (plotFile && diagnostic)
1671  {
1672  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1673  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1674  for (region = 0; region < format->numOfDetectorRegions; region++)
1675  {
1676  sprintf (fileString , "WavelengthCalib_%s_%sDATA%d", format->grismId, format->beamCombiner, region+1);
1677  sprintf (title , "Wavelength Calibration for %s %s, Region %d", format->grismId, format->beamCombiner, region+1);
1678  midiCreatePlotFile2D (fileString, title, "Channel", "Wavelength in micron", 0,
1679  waveCal->calibratedWave[region], 0, format->iXWidth, 1, 0);
1680  }
1681  free (fileString);
1682  free (title);
1683  }
1684 
1685  // Create database file
1686  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1687  sprintf (fileString , "%s_%s_%s.dat", fileNames->waveCalibName, format->grismId, format->beamCombiner);
1688  if ((filePtr = fopen (fileString, "w")) == NULL)
1689  {
1690  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "Cannot create wavelength calibration file");
1691  *error = 1;
1692  free (fileString);
1693  return;
1694  }
1695 
1696  // Write the wavelength data into file
1697  for (i = 0; i < format->iXWidth; i++)
1698  {
1699  for (region = 0; region < format->numOfDetectorRegions; region++)
1700  fprintf (filePtr, "%3.10f ", waveCal->calibratedWave[region][i]);
1701  fprintf (filePtr, "\n");
1702  }
1703 
1704  cpl_msg_info(cpl_func,"\nCreated wavelength calibration file ... %s \n", fileString);
1705  fprintf (midiReportPtr, "\nCreated wavelength calibration file ... %s \n", fileString);
1706 
1707  // Close files and release memory
1708  free (fileString);
1709  fclose (filePtr);
1710 
1711  return;
1712 }
1713 /*****************************************************************************/
1714 
1715 
1716 /******************************************************************************
1717 * European Southern Observatory
1718 * VLTI MIDI Maintenance Templates Software
1719 *
1720 * Module name: fitFilterSpectra
1721 * Input/Output: See function arguments to avoid duplication
1722 * Description: Fitting of filter spectra. The peaks of the filters are:
1723 *
1724 * Filter Pk Freq. Pk Wavelength
1725 * ======================================
1726 * NeII 2.34297e+13 Hz 12.7955 micron
1727 * SIV 2.85818e+13 Hz 10.489 micron
1728 * ArIII 3.33005e+13 Hz 9.00272 micron
1729 *
1730 * Use corresponding image for each filter and, using the Gaussian Fit
1731 * method, find the positions of the centre-pinholes (there should be
1732 * 3 for each filter image). From these computed positions and the above
1733 * given peak values, one can assign wavelength to the detector channels.
1734 * This facilitates a partial detector calibration.
1735 *
1736 * History:
1737 * 14-June-05 (csabet) Created
1738 ******************************************************************************/
1739 void fitFilterSpectra (
1740  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
1741  ImageFormat *format, // In: Pointer to the image format
1742  int *error) // Ou: Error status
1743 
1744 {
1745 
1746  // Local Declarations
1747  // ------------------
1748  const char routine[] = "fitFilterSpectra";
1749  int region;
1750 
1751  // Algorithm
1752  // ---------
1753  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1754  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1755 
1756  // Reset status
1757  *error = 0;
1758 
1759  // Get the spectra for the NeII filter
1760  for (region = 0; region < format->numOfDetectorRegions; region++)
1761  getFilterSpectra (region, "NeII", (waveCal->NeII->image)[region], format,
1762  &(waveCal->NeII->xCoord[region]), &(waveCal->NeII->yCoord[region]), error);
1763 
1764  // Get the spectra for the SIV filter
1765  for (region = 0; region < format->numOfDetectorRegions; region++)
1766  getFilterSpectra (region, "SIV", (waveCal->SIV->image)[region], format,
1767  &(waveCal->SIV->xCoord[region]), &(waveCal->SIV->yCoord[region]), error);
1768 
1769  // Get the spectra for the ArIII filter
1770  for (region = 0; region < format->numOfDetectorRegions; region++)
1771  getFilterSpectra (region, "ArIII", (waveCal->ArIII->image)[region], format,
1772  &(waveCal->ArIII->xCoord[region]), &(waveCal->ArIII->yCoord[region]), error);
1773 
1774  // Computed centre pinholes
1775  for (region = 0; region < format->numOfDetectorRegions; region++)
1776  {
1777  cpl_msg_info(cpl_func,"\nComputed Centre Pinholes for region %d: \n", region+1);
1778  cpl_msg_info(cpl_func,"----------------------------------- \n");
1779  cpl_msg_info(cpl_func,"NeII Centre Pinhole = (%f, %f) \n", (waveCal->NeII->xCoord)[region], (waveCal->NeII->yCoord)[region]);
1780  cpl_msg_info(cpl_func,"SIV Centre Pinhole = (%f, %f) \n", (waveCal->SIV->xCoord)[region], (waveCal->SIV->yCoord)[region]);
1781  cpl_msg_info(cpl_func,"ArIII Centre Pinhole = (%f, %f) \n", (waveCal->ArIII->xCoord)[region], (waveCal->ArIII->yCoord)[region]);
1782 
1783  fprintf (midiReportPtr, "\nComputed Centre Pinholes for region %d: \n", region+1);
1784  fprintf (midiReportPtr, "----------------------------------- \n");
1785  fprintf (midiReportPtr, "NeII Centre Pinhole = (%f, %f) \n",
1786  (waveCal->NeII->xCoord)[region], (waveCal->NeII->yCoord)[region]);
1787  fprintf (midiReportPtr, "SIV Centre Pinhole = (%f, %f) \n",
1788  (waveCal->SIV->xCoord)[region], (waveCal->SIV->yCoord)[region]);
1789  fprintf (midiReportPtr, "ArIII Centre Pinhole = (%f, %f) \n",
1790  (waveCal->ArIII->xCoord)[region], (waveCal->ArIII->yCoord)[region]);
1791  }
1792 
1793  // Assign computed peak values to the peak values given by the manufacturer
1794  for (region = 0; region < format->numOfDetectorRegions; region++)
1795  {
1796  cpl_msg_info(cpl_func,"\nDetector Channel Assignment for region %d: \n", region+1);
1797  cpl_msg_info(cpl_func,"-------------------------------------- \n");
1798  cpl_msg_info(cpl_func,"Channel %3d = %f THz %f micron \n", (int) ((waveCal->NeII->xCoord)[region]),
1799  FREQ_PEAK_NeII, WAVELENGTH_PEAK_NeII);
1800  cpl_msg_info(cpl_func,"Channel %3d = %f THz %f micron \n", (int) ((waveCal->SIV->xCoord)[region]),
1801  FREQ_PEAK_SIV, WAVELENGTH_PEAK_SIV);
1802  cpl_msg_info(cpl_func,"Channel %3d = %f THz %f micron \n", (int) ((waveCal->ArIII->xCoord)[region]),
1803  FREQ_PEAK_ArIII, WAVELENGTH_PEAK_ArIII);
1804 
1805  fprintf (midiReportPtr, "\nDetector Channel Assignment for region %d: \n", region+1);
1806  fprintf (midiReportPtr, "-------------------------------------- \n");
1807  fprintf (midiReportPtr, "Channel %3d = %f THz %f micron \n", (int) ((waveCal->NeII->xCoord)[region]),
1808  FREQ_PEAK_NeII, WAVELENGTH_PEAK_NeII);
1809  fprintf (midiReportPtr, "Channel %3d = %f THz %f micron \n", (int) ((waveCal->SIV->xCoord)[region]),
1810  FREQ_PEAK_SIV, WAVELENGTH_PEAK_SIV);
1811  fprintf (midiReportPtr, "Channel %3d = %f THz %f micron \n", (int) ((waveCal->ArIII->xCoord)[region]),
1812  FREQ_PEAK_ArIII, WAVELENGTH_PEAK_ArIII);
1813 
1814  (waveCal->NeII->wavelength)[region] = WAVELENGTH_PEAK_NeII;
1815  (waveCal->SIV->wavelength)[region] = WAVELENGTH_PEAK_SIV;
1816  (waveCal->ArIII->wavelength)[region] = WAVELENGTH_PEAK_ArIII;
1817  }
1818 
1819  return;
1820 }
1821 /*****************************************************************************/
1822 
1823 
1824 /******************************************************************************
1825 * European Southern Observatory
1826 * VLTI MIDI Maintenance Templates Software
1827 *
1828 * Module name: getFilterSpectra
1829 * Input/Output: See function arguments to avoid duplication
1830 * Description: Determines the position of the centre-pinhole in the given image
1831 *
1832 * History:
1833 * 30-Aug-05 (csabet)
1834 ******************************************************************************/
1835 void getFilterSpectra (
1836  int region, // In: Region of the image
1837  const char *filter, // In: Name of the filter
1838  float *image, // Ou: Pointer to the Wavelength Calibration data structure
1839  ImageFormat *format, // In: Pointer to the image format
1840  float *xCPH, // Ou: X coordinate of the centre pinhole
1841  float *yCPH, // Ou: Y coordinate of the centre pinhole
1842  int *error) // Ou: Error status
1843 
1844 {
1845 
1846  // Local Declarations
1847  // ------------------
1848  const char routine[] = "getFilterSpectra";
1849  int i, j, frame, span, quartSpan;
1850  float *array, *arrayPeak, maxFlux, peak, fluxMax;
1851  char *fileString, *title;
1852 
1853  // Algorithm
1854  // ---------
1855  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
1856  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
1857 
1858  // Reset status
1859  *error = 0;
1860  *xCPH = 0.0;
1861  *yCPH = 0.0;
1862  span = EXPECTED_PINHOLE_WIDTH;
1863  quartSpan = span / 4;
1864 
1865 
1866  cpl_msg_info(cpl_func,"\nComputing Coordinates for %s filter region %d \n", filter, region+1);
1867  cpl_msg_info(cpl_func,"-------------------------------------------- \n");
1868  fprintf (midiReportPtr, "\nComputing Coordinates for %s filter region %d\n", filter, region+1);
1869  fprintf (midiReportPtr, "-------------------------------------------- \n");
1870 
1871  //================================================
1872  // This section computes the approximate X coordinate of the centre pinhole
1873 
1874  // Allocate memory
1875  array = (float *) calloc (format->iXWidth, sizeof (float));
1876 
1877  // Compress spectrum in the Y direction
1878  for (i = 0; i < format->iYWidth; i++)
1879  {
1880  frame = i * format->iXWidth;
1881  for (j = 0; j < format->iXWidth; j++)
1882  array[j] += image[frame + j];
1883  }
1884 
1885  // Normalize array for a better correlation
1886  fluxMax = array[0];
1887  for (i = 0; i < format->iXWidth; i++)
1888  if (array[i] > fluxMax) fluxMax = array[i];
1889  for (i = 0; i < format->iXWidth; i++)
1890  array[i] /= fluxMax;
1891 
1892  if (plotFile && diagnostic)
1893  {
1894  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1895  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1896 
1897  sprintf (fileString , "%sSpectraAveAlongYDATA%d", filter, region+1);
1898  sprintf (title , "%s Spectra averaged along Y region %d", filter, region+1);
1899  midiCreatePlotFile2D (fileString, title, "Channel", "Flux", 0, array, 0, format->iXWidth, 1, 0);
1900  free (fileString);
1901  free (title);
1902  }
1903 
1904  // The peak of the above spectra gives the approximate x-coordinate of the centre-pinhole
1905  maxFlux = 0.0;
1906  peak = 0;
1907  for (i = 0; i < format->iXWidth; i++)
1908  {
1909  if (array[i] > maxFlux)
1910  {
1911  maxFlux = array[i];
1912  peak = i;
1913  }
1914  }
1915 
1916  // Now smooth the array around the peak
1917  *xCPH = midiGaussianSmooth (array, format->iXWidth, peak, span, error);
1918  cpl_msg_info(cpl_func,"Found apprximate X at %f \n", *xCPH);
1919  fprintf (midiReportPtr, "Found apprximate X at %f \n", *xCPH);
1920 
1921  // Release memory
1922  free (array);
1923  //================================================
1924 
1925 
1926 
1927  //================================================
1928  // This section computes the exact Y coordinate of the centre pinhole
1929 
1930  // Allocate memory
1931  array = (float *) calloc (format->iYWidth, sizeof (float));
1932  arrayPeak = (float *) calloc (3, sizeof (float));
1933 
1934  // Compress spectrum in the X direction
1935  for (i = 0; i < format->iYWidth; i++)
1936  {
1937  frame = i * format->iXWidth;
1938  for (j = 0; j < format->iXWidth; j++)
1939  array[i] += image[frame + j];
1940  }
1941 
1942  // Normalize array for a better correlation
1943  fluxMax = array[0];
1944  for (i = 0; i < format->iYWidth; i++)
1945  if (array[i] > fluxMax) fluxMax = array[i];
1946  for (i = 0; i < format->iYWidth; i++)
1947  array[i] /= fluxMax;
1948 
1949  if (plotFile && diagnostic)
1950  {
1951  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1952  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
1953 
1954  sprintf (fileString , "%sSpectraAveAlongXDATA%d", filter, region+1);
1955  sprintf (title , "%s Spectra averaged along X region %d", filter, region+1);
1956  midiCreatePlotFile2D (fileString, title, "Sub-frame", "Flux", 0, array, 0, format->iYWidth, 1, 0);
1957  free (fileString);
1958  free (title);
1959  }
1960 
1961  // Here we expect three peaks
1962  // Find the strongest peak
1963  maxFlux = 0.0;
1964  arrayPeak[0] = 0;
1965  for (i = 0; i < format->iYWidth; i++)
1966  {
1967  if (array[i] > maxFlux)
1968  {
1969  maxFlux = array[i];
1970  arrayPeak[0] = i;
1971  }
1972  }
1973  cpl_msg_info(cpl_func,"Found first Y at %f \n", arrayPeak[0]);
1974  fprintf (midiReportPtr, "Found first Y at %f \n", arrayPeak[0]);
1975 
1976  // Find the second strongest peak
1977  maxFlux = 0.0;
1978  arrayPeak[1] = 0;
1979  for (i = 0; i < format->iYWidth; i++)
1980  {
1981  if ( !((i > arrayPeak[0]-quartSpan) && (i < arrayPeak[0]+quartSpan)) )
1982  {
1983  if (array[i] > maxFlux)
1984  {
1985  maxFlux = array[i];
1986  arrayPeak[1] = i;
1987  }
1988  }
1989  }
1990  cpl_msg_info(cpl_func,"Found second Y at %f \n", arrayPeak[1]);
1991  fprintf (midiReportPtr, "Found second Y at %f \n", arrayPeak[1]);
1992 
1993  // Find the third strongest peak
1994  maxFlux = 0.0;
1995  arrayPeak[2] = 0;
1996  for (i = 0; i < format->iYWidth; i++)
1997  {
1998  if ( !((i > arrayPeak[0]-quartSpan) && (i < arrayPeak[0]+quartSpan)) &&
1999  !((i > arrayPeak[1]-quartSpan) && (i < arrayPeak[1]+quartSpan)) )
2000  {
2001  if (array[i] > maxFlux)
2002  {
2003  maxFlux = array[i];
2004  arrayPeak[2] = i;
2005  }
2006  }
2007  }
2008  cpl_msg_info(cpl_func,"Found third Y at %f \n", arrayPeak[2]);
2009  fprintf (midiReportPtr, "Found third Y at %f \n", arrayPeak[2]);
2010 
2011  // Find the median of the above three peaks
2012  peak = signalMedian (arrayPeak, 0, 3);
2013  free (arrayPeak);
2014  cpl_msg_info(cpl_func,"Found median Y at %f \n", peak);
2015  fprintf (midiReportPtr, "Found median Y at %f \n", peak);
2016 
2017  // Normalise around median
2018  if (peak == 0)
2019  {
2020  *error = 1;
2021  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, "Cannot find median");
2022  free (array);
2023  return;
2024  }
2025  fluxMax = array[0];
2026  if (quartSpan > peak)
2027  quartSpan = peak;
2028 
2029  for (i = peak-quartSpan; i <= peak+quartSpan; i++)
2030  if (array[i] > fluxMax) fluxMax = array[i];
2031  for (i = peak-quartSpan; i <= peak+quartSpan; i++)
2032  array[i] /= fluxMax;
2033 
2034  if (plotFile && diagnostic)
2035  {
2036  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2037  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2038 
2039  sprintf (fileString , "%sCentrePinholeAlongYDATA%d", filter, region+1);
2040  sprintf (title , "%s Centre Pinhole along Y region %d", filter, region+1);
2041  midiCreatePlotFile2D (fileString, title, "Sub-frame", "Flux", 0, array, peak-quartSpan, peak+quartSpan+1, 1, 0);
2042  free (fileString);
2043  free (title);
2044  }
2045 
2046  // Now smooth the array around the median and find the exact Y coordinate
2047  *yCPH = midiGaussianSmooth (array, format->iYWidth, peak, quartSpan, error);
2048  cpl_msg_info(cpl_func,"Found exact Y at %f \n", *yCPH);
2049  fprintf (midiReportPtr, "Found exact Y at %f \n", *yCPH);
2050  free (array);
2051  //================================================
2052 
2053 
2054 
2055  //================================================
2056  // This section computes the exact X coordinate of the centre pinhole
2057 
2058  // Allocate memory
2059  array = (float *) calloc (format->iXWidth, sizeof (float));
2060 
2061  // Compress spectrum in the Y direction around the exact Y coordinate
2062  for (i = *yCPH-quartSpan; i < *yCPH+quartSpan; i++)
2063  {
2064  frame = i * format->iXWidth;
2065  for (j = 0; j < format->iXWidth; j++)
2066  array[j] += image[frame + j];
2067  }
2068 
2069  // Normalize array for a better correlation
2070  fluxMax = array[0];
2071  for (i = 0; i < format->iXWidth; i++)
2072  if (array[i] > fluxMax) fluxMax = array[i];
2073  for (i = 0; i < format->iXWidth; i++)
2074  array[i] /= fluxMax;
2075 
2076  if (plotFile && diagnostic)
2077  {
2078  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2079  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2080 
2081  sprintf (fileString , "%sCentrePinholeAveAlongYDATA%d", filter, region+1);
2082  sprintf (title , "%s Centre pinhole averaged along Y region %d", filter, region+1);
2083  midiCreatePlotFile2D (fileString, title, "Channel", "Flux", 0, array, 0, format->iXWidth, 1, 0);
2084  free (fileString);
2085  free (title);
2086  }
2087 
2088  // The peak of the above spectra gives the approximate x-coordinate of the centre-pinhole
2089  maxFlux = 0.0;
2090  peak = 0;
2091  for (i = 0; i < format->iXWidth; i++)
2092  {
2093  if (array[i] > maxFlux)
2094  {
2095  maxFlux = array[i];
2096  peak = i;
2097  }
2098  }
2099 
2100  // Now smooth the array around the peak
2101  *xCPH = midiGaussianSmooth (array, format->iXWidth, peak, span, error);
2102  cpl_msg_info(cpl_func,"Found exact X at %f \n", *xCPH);
2103  fprintf (midiReportPtr, "Found exact X at %f \n", *xCPH);
2104  //================================================
2105 
2106  // Release memory
2107  free (array);
2108  //================================================
2109 
2110  return;
2111 }
2112 /*****************************************************************************/
2113 
2114 
2115 /******************************************************************************
2116 * European Southern Observatory
2117 * VLTI MIDI Maintenance Templates Software
2118 *
2119 * Module name: fitFoilSpectra
2120 * Input/Output: See function arguments to avoid duplication
2121 * Description: Fitting of Foil spectra
2122 *
2123 * History:
2124 * 14-June-05 (csabet)
2125 ******************************************************************************/
2126 void fitFoilSpectra (
2127  MidiFiles *fileNames, // In: Pointer to file names
2128  WaveCalibration *waveCal, // Ou: Pointer to the Wavelength Calibration data structure
2129  ImageFormat *format, // In: Pointer to the image format
2130  int *error) // Ou: Error status
2131 
2132 {
2133 
2134  // Local Declarations
2135  // ------------------
2136  const char routine[] = "fitFoilSpectra";
2137  float **foilSpectra, **openSpectra, fluxMax;
2138  int i, region, length;
2139  char *fileString, *title;
2140  FILE *wlFilePtr=NULL;
2141 
2142  // Algorithm
2143  // ---------
2144  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
2145  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
2146 
2147  // Reset status
2148  *error = 0;
2149 
2150  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire code to be designed");
2151 
2152  // Allocate memory
2153  foilSpectra = (float **) calloc (format->numOfDetectorRegions, sizeof (float *));
2154  openSpectra = (float **) calloc (format->numOfDetectorRegions, sizeof (float *));
2155  for (region = 0; region < format->numOfDetectorRegions; region++)
2156  {
2157  foilSpectra[region] = (float *) calloc (format->iXWidth, sizeof (float));
2158  openSpectra[region] = (float *) calloc (format->iXWidth, sizeof (float));
2159  }
2160 
2161  // For each region get foil spectra
2162  for (region = 0; region < format->numOfDetectorRegions; region++)
2163  getFoilSpectra (region, "Foil", waveCal->foil->image[region], format, foilSpectra[region], error);
2164 
2165  // For each region get OPEN spectra
2166  for (region = 0; region < format->numOfDetectorRegions; region++)
2167  getFoilSpectra (region, "Open", waveCal->open->image[region], format, openSpectra[region], error);
2168 
2169  // Divide foilSpectra by openSpectra
2170  for (region = 0; region < format->numOfDetectorRegions; region++)
2171  {
2172  for (i = 0; i < format->iXWidth; i++)
2173  foilSpectra[region][i] /= openSpectra[region][i];
2174 
2175  // Normalize array for a better correlation
2176  fluxMax = foilSpectra[region][0];
2177  for (i = 0; i < format->iXWidth; i++)
2178  if (foilSpectra[region][i] > fluxMax) fluxMax = foilSpectra[region][i];
2179  for (i = 0; i < format->iXWidth; i++)
2180  foilSpectra[region][i] /= fluxMax;
2181 
2182  // Plot it
2183  if (plotFile && diagnostic)
2184  {
2185  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2186  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2187  sprintf (fileString , "FoilDivideOpenAveAlongYDATA%d", region+1);
2188  sprintf (title , "Foil divided by Open Averaged along Y region %d", region+1);
2189  midiCreatePlotFile2D (fileString, title, "Channel", "Flux", 0, foilSpectra[region], 0, format->iXWidth, 1, 0);
2190  free (fileString);
2191  free (title);
2192  }
2193  }
2194 
2195  // Compare with published spectra. Load the WL-CALIB_2 spectra
2196  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2197  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2198  sprintf (fileString, "%swl-calib_2.dat", fileNames->calibDbDir);
2199  if ((wlFilePtr = fopen (fileString, "r")) == NULL)
2200  {
2201  sprintf (midiMessage, "Cannot Open %s", fileString);
2202  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
2203  free (fileString);
2204  free (title);
2205  *error = 1;
2206  return;
2207  }
2208 
2209  // Ignore first record which gives the title of the data file
2210  fgets (title, MAX_STRING_LENGTH, wlFilePtr);
2211  length = 0;
2212  // First column in the file is the wavenumber and the second is transmission
2213  while (fscanf (wlFilePtr, "%f %f\n", &(waveCal->foil->actualWavelength[length]),
2214  &(waveCal->foil->actualTransmission[length])) != EOF) length++;
2215 
2216  // Convert to microns
2217  for (i = 0; i < length; i++)
2218  waveCal->foil->actualWavelength[i] = 10000.0 * (1.0 / waveCal->foil->actualWavelength[i]);
2219 
2220  sprintf (midiMessage, "Read %d pairs of 'float'(s) from %s", length, fileString);
2221  midiReportInfo (midiReportPtr, routine, __FILE__, __LINE__, midiMessage);
2222  fclose (wlFilePtr);
2223  free (fileString);
2224  free (title);
2225 
2226  // Plot manufacturer's Foil transmission
2227  midiCreatePlotFile2D2P ("FoilTransmission", "Foil Transmission Versus Wavelength",
2228  "Wavelength in micron", "Transmission", 0, waveCal->foil->actualWavelength, waveCal->foil->actualTransmission, 0, length, 1);
2229 
2230  // Release memory
2231  for (region = 0; region < format->numOfDetectorRegions; region++)
2232  {
2233  free (foilSpectra[region]);
2234  free (openSpectra[region]);
2235  }
2236  free (foilSpectra);
2237  free (openSpectra);
2238 
2239  return;
2240 }
2241 /*****************************************************************************/
2242 
2243 
2244 /******************************************************************************
2245 * European Southern Observatory
2246 * VLTI MIDI Maintenance Templates Software
2247 *
2248 * Module name: getFoilSpectra
2249 * Input/Output: See function arguments to avoid duplication
2250 * Description: Processing of the foil spectra
2251 *
2252 * History:
2253 * 02-Sep-05 (csabet)
2254 ******************************************************************************/
2255 void getFoilSpectra (
2256  int region, // In: Region of the image
2257  const char *filter, // In: Name of the filter
2258  float *image, // In: pointer to the image
2259  ImageFormat *format, // In: Pointer to the image format
2260  float *spectra, // Ou: pointer to the resulting spectra
2261  int *error) // Ou: Error status
2262 
2263 {
2264 
2265  // Local Declarations
2266  // ------------------
2267  const char routine[] = "getFoilSpectra";
2268  char *fileString, *title;
2269  int i, j, frame;
2270  float fluxMax;
2271 
2272  // Algorithm
2273  // ---------
2274  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
2275  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
2276 
2277  // Reset status
2278  *error = 0;
2279 
2280  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire code to be designed");
2281 
2282  cpl_msg_info(cpl_func,"\nObtaining %s Spectra for region %d \n", filter, region+1);
2283  cpl_msg_info(cpl_func,"------------------------------- \n");
2284  fprintf (midiReportPtr, "\nObtaining %s Spectra for region %d \n", filter, region+1);
2285  fprintf (midiReportPtr, "------------------------------- \n");
2286 
2287  // Compress spectrum in the Y direction
2288  for (i = 0; i < format->iYWidth; i++)
2289  {
2290  frame = i * format->iXWidth;
2291  for (j = 0; j < format->iXWidth; j++)
2292  spectra[j] += image[frame + j];
2293  }
2294 
2295  // Normalize array for a better correlation
2296  fluxMax = spectra[0];
2297  for (i = 0; i < format->iXWidth; i++)
2298  if (spectra[i] > fluxMax) fluxMax = spectra[i];
2299  for (i = 0; i < format->iXWidth; i++)
2300  spectra[i] /= fluxMax;
2301 
2302  // Plot it
2303  if (plotFile && diagnostic)
2304  {
2305  fileString = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2306  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
2307 
2308  sprintf (fileString , "%sSpectraAveAlongYDATA%d", filter, region+1);
2309  sprintf (title , "%s Spectra Averaged along Y region %d", filter, region+1);
2310  midiCreatePlotFile2D (fileString, title, "Channel", "Flux", 0, spectra, 0, format->iXWidth, 1, 0);
2311  free (fileString);
2312  free (title);
2313  }
2314 
2315  return;
2316 }
2317 /*****************************************************************************/
2318 
2319 
2320 /******************************************************************************
2321 * European Southern Observatory
2322 * VLTI MIDI Maintenance Templates Software
2323 *
2324 * Module name: fitOpenSpectra
2325 * Input/Output: See function arguments to avoid duplication
2326 * Description: Fitting of Open spectra
2327 *
2328 * History:
2329 * 14-June-05 (csabet)
2330 ******************************************************************************/
2331 void fitOpenSpectra (
2332  int *error) // Ou: Error status
2333 
2334 {
2335 
2336  // Local Declarations
2337  // ------------------
2338  const char routine[] = "fitOpenSpectra";
2339 
2340  // Algorithm
2341  // ---------
2342  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s' \n", routine);
2343  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s' \n", routine);
2344 
2345  // Reset status
2346  *error = 0;
2347 
2348  midiReportTbd (midiReportPtr, routine, __FILE__, __LINE__, "Entire code to be designed");
2349 
2350  return;
2351 }
2352 /*****************************************************************************/