MIDI Pipeline Reference Manual  2.8.3
estimationFrg.c
1 /******************************************************************************
2 *******************************************************************************
3 * European Southern Observatory
4 * VLTI MIDI Data Reduction Software
5 *
6 * Module name: estimationFrg.c
7 * Description: Contains routines for all data preprocessing algorithms
8 *
9 * History:
10 * 12-Jul-03 (csabet) Created. Derived from (jmeisner 03-Feb-03)
11 *******************************************************************************
12 ******************************************************************************/
13 
14 /******************************************************************************
15 * Compiler directives
16 ******************************************************************************/
17 
18 /******************************************************************************
19 * Include files
20 ******************************************************************************/
21 #include <stdio.h>
22 #include <cpl.h>
23 #include <stdlib.h>
24 #include <math.h>
25 #include <string.h>
26 #include "midiGlobal.h"
27 #include "fft.h"
28 #include "complex_midi.h"
29 #include "statistics.h"
30 #include "diagnostics.h"
31 #include "memoryHandling.h"
32 #include "errorHandling.h"
33 #include "midiLib.h"
34 #include "estimationFrg.h"
35 #include "photometry.h"
36 #include "visibility.h"
37 #include "calibration.h"
38 
39 /**********************************************************
40 * Constant definitions
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: estimateFringe
52 * Input/Output: See function arguments to avoid duplication
53 * Description: Computes DISPERSED fringe and Unnormalized visibility
54 *
55 *
56 * History:
57 * 16-Jul-04 (csabet) Added Interface specification. Code and further
58 * decomposion shall be carried out by Jeff
59 * 17-Feb-04 (csabet) Created template
60 * 22-Jan-05 (csabet) Cleaned up and modified data structures
61 ******************************************************************************/
62 void estimateFringe (
63  MidiFiles *fileNames, // In: Pointer to file names
64  FilterData *filterInfo, // In: Filter information
65  CompressedData *compressed, // In: Compressed interferometry data
66  ImageFormat *format, // In: Points to the image format
67  float *freqCal, // IO: If (freqCal[0][0] == 1.0F) then it still needs to be filled in by this function
68  float *dispRawVis, // Ou: Raw unnormalized visibility
69  float *dispRawVisErr, // Ou: Error of Raw unnormalized visibility
70  int *error)
71 {
72 
73  /* Local Declarations
74  --------------------*/
75  const char routine[] = "estimateFringe";
76  double accum = 0.0;
77  int region, frame, X, n;
78 
79  /* Algorithm
80  -----------*/
81  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s'\n", routine);
82  if (diagnostic > 4) fprintf (midiReportPtr, "Invoking routine '%s'\n", routine);
83 
84  cpl_msg_info(cpl_func,"\nComputing Raw visibilities from batch %d \n", batchNumber);
85  cpl_msg_info(cpl_func,"------------------------------------- \n");
86  fprintf(midiReportPtr, "\nComputing Raw visibilities from batch %d \n", batchNumber);
87  fprintf(midiReportPtr, "------------------------------------- \n");
88 
89  // Reset
90  *error = 0;
91 
92  // Obtain the visibilities^2, and plot the spectra for each freq channel:
93  ProcessSpectrumEachChannel (fileNames, filterInfo, compressed, format, dispRawVis,
94  dispRawVisErr, freqCal, error);
95  if (*error) return;
96 
97  if (plotFile && diagnostic)
98  {
99  midiCreatePlotFile2D ("RawVisCombined", "Combined Raw Uncalibrated Visibility",
100  "Channel", "Visibility", 0, dispRawVis, 0, format->iXWidth, 1, 0);
101 
102  midiCreatePlotFile2D ("RawVisErrCombined", "Combined Raw Uncalibrated Visibility Error",
103  "Channel", "Visibility Error", 0, dispRawVisErr, 0, format->iXWidth, 1, 0);
104  }
105 
106  // Print results
107  cpl_msg_info(cpl_func,"\nAverage values of DISPERSED Fringe \n"
108  "---------------------------------- \n"
109  "Region Average values \n");
110  fprintf (midiReportPtr, "\nAverage values of DISPERSED Fringe \n"
111  "---------------------------------- \n"
112  "Region Average values \n");
113 
114  for (region = 0; region < format->numOfRegionsToProcess; region++)
115  {
116  accum=0.0;
117  n = 0;
118  for (frame = 0; frame < format->numOfFrames; frame++)
119  {
120  for (X = 0; X < format->iXWidth; X++)
121  {
122  if (badChannelList[X])
123  continue;
124 
125  accum += (((compressed->iDispFringe)[region])[X])[frame];
126  n++;
127  }
128  }
129 
130  accum /= n;
131  cpl_msg_info(cpl_func,"%2d %12.2f \n", region, accum);
132  fprintf (midiReportPtr, "%2d %12.2f \n", region, accum);
133  }
134 
135  return;
136 }
137 /*****************************************************************************/
138 
139 
140 
141 
142 /******************************************************************************
143 * European Southern Observatory
144 * VLTI MIDI Data Reduction Software
145 *
146 * Module name: ProcessSpectrumEachChannel
147 * Input/Output: See function arguments to avoid duplication
148 * Description:
149 *
150 *
151 * History:
152 * 16-Jul-04 (JM) provided the code
153 * 20-Jan-05 (csabet) Cleaned up and integrated
154 ******************************************************************************/
155 void ProcessSpectrumEachChannel (
156  MidiFiles *fileNames, // In: Pointer to file names
157  FilterData *filterInfo, // In: Filter information
158  CompressedData *compressed, // In: Compressed interferometry data
159  ImageFormat *format, // In: Points to the image format
160  float *dispRawVis, // Ou:
161  float *dispRawVisErr, // Ou:
162  float *freqCal, // Ou: Frequency calibration
163  int *error)
164 {
165 
166  // Local Declarations
167  // ------------------
168  const char routine[] = "ProcessSpectrumEachChannel";
169  int i, j, X, lowFreqIndex, highFreqIndex, loF, hiF,
170  freqCalExists, localError, numOfSpectrums;
171  float *spectrum, peakval, peakch;
172  float calib, **waveCal=NULL;
173  char *string, *title, *dataFilePath, *cmdFileName, *argument;
174  FILE *cmdFilePtr=NULL, *dataFilePtr=NULL;
175  float zero=0.0;
176  FILE *wclHistoryPtr=NULL;
177  float **PeakMatrix;
178  int scan, index;
179  float *PeakVectorMean;
180  char *fileNamePeak, *titlePeak;
181 
182  // Algorithm
183  // ---------
184  if (diagnostic > 4)cpl_msg_info(cpl_func,"Invoking routine '%s'\n", routine);
185  if (diagnostic > 4) fprintf(midiReportPtr, "Invoking routine '%s'\n", routine);
186 
187  cpl_msg_info(cpl_func,"\nProcessing each Channel Spectrum from batch %d \n", batchNumber);
188  cpl_msg_info(cpl_func,"------------------------------------------- \n");
189  fprintf(midiReportPtr, "\nProcessing each Channel Spectrum from batch %d \n", batchNumber);
190  fprintf(midiReportPtr, "------------------------------------------- \n");
191 
192  // Initialize
193  *error = 0;
194  freqCalExists = 0;
195 
196  // Recalculate FFT size and the frequency indices
197  if (diagnostic)cpl_msg_info(cpl_func,"FFT size was = %d \n", format->fftsize);
198  fprintf (midiReportPtr, "FFT size was = %d \n", format->fftsize);
199  SetFFTsize (format->fftsize);
200  if (diagnostic)cpl_msg_info(cpl_func,"FFT size is now = %d \n", format->fftsize);
201  fprintf (midiReportPtr, "FFT size is now = %d \n", format->fftsize);
202  calib = format->optFreqCal / ((float) format->fftsize);
203  lowFreqIndex = (int) (filterInfo->optFreqLo / calib); // Only look at the relevant frequencies
204  highFreqIndex = (int) (filterInfo->optFreqHi / calib); // Only look at the relevant frequencies
205  if (highFreqIndex > (format->fftsize/2)) highFreqIndex = (format->fftsize/2);
206 
207  // Get calibrated channel frequencies
208  waveCal = callocWaveCalibration (format->numOfDetectorRegions, format);
209  getCalibratedChWave (fileNames, format, waveCal, error);
210  if (!(*error))
211  {
212  freqCalExists = 1;
213 
214  // Open a file for wavelength calibration history
215  wclHistoryPtr = fopen (fileNames->wclHistoryName, "a");
216  fprintf (wclHistoryPtr, "Wavelength Calibration \n");
217  fprintf (wclHistoryPtr, "Grism ID = %s \n", format->grismId);
218  fprintf (wclHistoryPtr, "Number of Records = %d \n", format->iXWidth);
219  fprintf (wclHistoryPtr, "--------------------------------------- \n");
220 
221  if (strcmp (format->beamCombiner, "SCI_PHOT") == 0)
222  {
223  for (X = 0; X < format->iXWidth; X++) fprintf (wclHistoryPtr, "%f %f %f %f\n",
224  waveCal[0][X], waveCal[1][X], waveCal[2][X], waveCal[3][X]);
225  fclose (wclHistoryPtr);
226 
227  // Combine channels. Only regions 2 and 3 (Interferometry is used)
228  for (i = 0; i < format->iXWidth; i++)
229  freqCal[i] = (waveCal[1][i] + waveCal[2][i]) * 0.5F; // Average them
230  }
231  else
232  {
233  for (X = 0; X < format->iXWidth; X++) fprintf (wclHistoryPtr, "%f %f\n",
234  waveCal[0][X], waveCal[1][X]);
235  fclose (wclHistoryPtr);
236 
237  // Combine channels
238  for (i = 0; i < format->iXWidth; i++)
239  freqCal[i] = (waveCal[0][i] + waveCal[1][i]) * 0.5F; // Average them
240  }
241 
242  // Create plot
243  if (plotFile) midiCreatePlotFile2D ("WaveCalibCombined", "Combined Wavelength Claibration",
244  "Channel", "Wavelength (micron)", 0, freqCal, 0, format->iXWidth, 1, 0);
245  }
246  else
247  {
248  // Readjust
249  *error = 0;
250  if (!(highFreqIndex - lowFreqIndex))
251  {
252  *error = 1;
253  midiReportWarning (midiReportPtr, routine, __FILE__, __LINE__, "No channels to process");
254  return;
255  }
256  }
257  freeWaveCalibration (format->numOfDetectorRegions, waveCal);
258 
259  if (diagnostic)cpl_msg_info(cpl_func,"\nOptical frequency calibration = %6.2f THz, calibration per FFT resolution = %6.2f THz \n",
260  format->optFreqCal, calib);
261  if (diagnostic)cpl_msg_info(cpl_func,"Low frequency index (for %f THz) = %d \n", filterInfo->optFreqLo, lowFreqIndex);
262  if (diagnostic)cpl_msg_info(cpl_func,"High frequency index (for %f THz) = %d \n", filterInfo->optFreqHi, highFreqIndex);
263  if (diagnostic)cpl_msg_info(cpl_func,"With %d frames, and %d frames / scan \n", format->numOfFrames, format->framesPerScan);
264  if (diagnostic)cpl_msg_info(cpl_func,"\nProcessing Combined visibility for each channel \n");
265 
266  fprintf (midiReportPtr, "\nOptical frequency calibration = %6.2f THz, calibration per fft resolution = %6.2f THz QCLOG \n",
267  format->optFreqCal, calib);
268  fprintf (midiReportPtr, "Low frequency index (for %f THz) = %d QCLOG \n", filterInfo->optFreqLo, lowFreqIndex);
269  fprintf (midiReportPtr, "High frequency index (for %f THz) = %d QCLOG \n", filterInfo->optFreqHi, highFreqIndex);
270  fprintf (midiReportPtr, "With %d frames, and %d frames / scan QCLOG \n", format->numOfFrames, format->framesPerScan);
271  fprintf (midiReportPtr, "\nProcessing Combined visibility for each channel QCLOG \n");
272 
273  cpl_msg_info(cpl_func,"We now carry out Frame, Scan and Channel rejection based on Signal/Noise \n\n");
274  fprintf(midiReportPtr, "We now carry out Frame, Scan and Channel rejection based on Signal/Noise \n\n");
275 
276  if (diagnostic)
277  cpl_msg_info(cpl_func,"\nIncoherent visibility results:\n\nChannel Wavelength (micron) Log slope Offset White noise Raw vis Raw vis Error\n");
278  fprintf (midiReportPtr,
279  "\nIncoherent visibility results:\n\nChannel Wavelength (micron) Log slope Offset White noise Raw vis Raw vis Error QCLOG\n");
280 
281  // Prepare header for plots
282  if (plotFile)
283  {
284  // Allocate memory
285  dataFilePath = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
286  cmdFileName = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
287  argument = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
288  string = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
289  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
290 
291  // Create the plot file
292  sprintf (string, "3dPowerSpectrumCombinedInterf");
293  sprintf (title, "Combined Interferometry Power Spectrum");
294  sprintf (dataFilePath, "%s%s.%s.plt", outFileDir, outRootName, string);
295  dataFilePtr = fopen (dataFilePath, "w");
296  }
297 
298  // Allocate memory
299  spectrum = (float *) calloc (format->fftsize/2, sizeof(float));
300 
301  //Allocate memory for PeakMatrix:
302 
303  PeakMatrix=calloc( format->iXWidth,sizeof (float*) );
304  for(i=0;i<format->iXWidth;i++){
305  PeakMatrix[i]=calloc(format->numOfScans,sizeof(float));
306  }
307 
308 
309  // Process valid channels only
310  for (X = 0; X < format->iXWidth; X++)
311  {
312  localError = 0;
313  if (diagnostic)cpl_msg_info(cpl_func,"%3d", X);
314  fprintf (midiReportPtr, "%3d", X);
315 
316  if (badChannelList[X])
317  {
318  if (diagnostic)cpl_msg_info(cpl_func," %5.2f <-- %s --> \n", freqCal[X], UNAV);
319  fprintf (midiReportPtr, " %5.2f <-- %s --> QCLOG \n", freqCal[X], UNAV);
320 
321  if (plotFile)
322  {
323  // Fill in the empty values
324  for (j = 0; j < format->fftsize/2; j++)
325  fprintf (dataFilePtr, "%f ", zero);
326  fprintf (dataFilePtr, "\n");
327  }
328  continue;
329  }
330 
331  // Reset mmory
332  memset (spectrum, 0, (sizeof(float)) * format->fftsize/2);
333 
334  // Set low and high frequancy index for this channel
335  if (!freqCalExists)
336  {
337  loF = lowFreqIndex - 10; // Not sure about this yet. But it's not a likely situation
338  hiF = highFreqIndex;
339  }
340  else
341  {
342  loF = (int) (((SPEED_OF_LIGHT / freqCal[X])/calib) - 10);
343  hiF = (int) (((SPEED_OF_LIGHT / freqCal[X])/calib) + 10);
344  }
345  if (loF < 0) loF = 0;
346  if (hiF > format->fftsize/2) hiF = format->fftsize/2;
347 
348 
349 
350  // Get number of spectrums
351  numOfSpectrums = getChannelSpectrum (X, loF, hiF, compressed->rejectList[X],
352  (((compressed->iDispFringe)[0])[X]), (((compressed->iDispFringe)[1])[X]), format, spectrum, PeakMatrix[X]);
353 
354 
355 
356 
357  // Check if any spectrums
358  if (!numOfSpectrums)
359  {
360  badChannelList[X] |= BSL_DATA_ERROR;
361  if (plotFile)
362  {
363  for (j = 0; j < format->fftsize/2; j++)
364  fprintf (dataFilePtr, "%f ", zero);
365  fprintf (dataFilePtr, "\n");
366  }
367  if (diagnostic)cpl_msg_info(cpl_func," %5.2f <-- %s --> \n", freqCal[X], UNAV);
368  fprintf (midiReportPtr, " %5.2f <-- %s --> QCLOG \n", freqCal[X], UNAV);
369  continue;
370  }
371 
372  // Reject bad spectrums
373  localError = 0;
374  for (j = 0; j < format->fftsize/2; j++)
375  {
376  if (isnan (spectrum[j]))
377  {
378  localError = 1;
379  badChannelList[X] |= BSL_DATA_ERROR;
380  break;
381  }
382  }
383  if (localError)
384  {
385  if (plotFile)
386  {
387  for (j = 0; j < format->fftsize/2; j++)
388  fprintf (dataFilePtr, "%f ", zero);
389  fprintf (dataFilePtr, "\n");
390  }
391  if (diagnostic)cpl_msg_info(cpl_func," %5.2f <-- %s --> \n", freqCal[X], UNAV);
392  fprintf (midiReportPtr, " %5.2f <-- %s --> QCLOG \n", freqCal[X], UNAV);
393  continue;
394  }
395 
396  // Write into the plot file
397  if (plotFile)
398  {
399  for (j = 0; j < format->fftsize/2; j++)
400  fprintf (dataFilePtr, "%f ", spectrum[j]);
401  fprintf (dataFilePtr, "\n");
402  }
403 
404  if (!freqCalExists)
405  {
406  findSpectralPeak (spectrum, lowFreqIndex, highFreqIndex, &peakch, &peakval);
407  freqCal[X] = peakch*calib;
408  }
409  else
410  {
411  if (freqCal[X] == 0.0) peakch = 0.0;
412  else peakch = (SPEED_OF_LIGHT / freqCal[X])/calib; // lookup from table inputted to this function
413  peakval = spectrum[(int)(peakch+0.5F)]; // Read out the peak value directly (was for plotting. Not used);
414  }
415 
416  if (diagnostic)cpl_msg_info(cpl_func," %5.2f ", freqCal[X]);
417  fprintf (midiReportPtr, " %5.2f ", freqCal[X]);
418 
419  // Compute unnormalized visibility estimate from spectrum
420  if (peakch)
421  dispRawVis[X] = analyseSpectrum (format, peakch, spectrum, calib, &(dispRawVisErr[X]));
422  else
423  {
424  dispRawVis[X] = 0.F;
425  dispRawVisErr[X] = 0.F;
426  }
427 
428  if (diagnostic)cpl_msg_info(cpl_func," %11.4f", dispRawVis[X]);
429  if (diagnostic)cpl_msg_info(cpl_func," %9.4f", dispRawVisErr[X]);
430  fprintf (midiReportPtr, " %11.4f", dispRawVis[X]);
431  fprintf (midiReportPtr, " %9.4f", dispRawVisErr[X]);
432 
433  if (diagnostic)cpl_msg_info(cpl_func,"\n");
434  fprintf (midiReportPtr, " QCLOG\n");
435  }
436  // Release memory
437  free (spectrum);
438 
439 
440  //Calculate the mean values of the PeakMatrix
441 
442  PeakVectorMean=calloc(format->numOfScans,sizeof (float) );
443 
444 
445  for (scan = 0; scan < format->numOfScans; scan++)
446  {
447  index=0;
448  for (X = 0; X < format->iXWidth; X++)
449  {
450  if(PeakMatrix[X][scan]>0){
451  PeakVectorMean[scan]+=PeakMatrix[X][scan];
452  index++;
453  }
454  }
455  PeakVectorMean[scan]=PeakVectorMean[scan]/(float)index;
456 /* cpl_msg_info(cpl_func,"PeakVectorMean: %f",PeakVectorMean[scan]); */
457 /* cpl_msg_info(cpl_func,"from %d Chanels\n",index); */
458  }
459 
460  //Write the mean values (averaged over the channel) in a file
461  fileNamePeak = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
462  titlePeak = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
463  sprintf (fileNamePeak, "PeakScanChannelaveraged");
464  sprintf (titlePeak, "PeakScanChannelaveraged");
465 
466  midiCreatePlotFile2D (fileNamePeak, titlePeak, "Scan", "Peak", 0, PeakVectorMean, 0, format->numOfScans, 1, 0);
467  free (fileNamePeak);
468  free (titlePeak);
469 
470 
471  //Free memory
472 
473  free(PeakVectorMean);
474 
475  for(i=0;i<format->iXWidth;i++){
476  free (PeakMatrix[i]);
477  }
478  free (PeakMatrix);
479 
480 
481  // Fill in the empty values and close dataFilePtr
482  if (plotFile)
483  fclose (dataFilePtr);
484 
485  // Display plot file
486  if (plotFile > 1)
487  {
488  // Create the command file
489  sprintf (cmdFileName, "plotCmdFile.grb");
490  cmdFilePtr = fopen (cmdFileName, "w");
491  fprintf (cmdFilePtr, "set title \'%s\' \n", title);
492  fprintf (cmdFilePtr, "set xlabel 'Frequency Bin' \n");
493  fprintf (cmdFilePtr, "set ylabel 'Channel' \n");
494  fprintf (cmdFilePtr, "set zlabel 'Power Spectrum' \n");
495  fprintf (cmdFilePtr, "set xrange [0:%d] \n", format->fftsize/2);
496  fprintf (cmdFilePtr, "set yrange [0:%d] \n", format->iXWidth);
497  fprintf (cmdFilePtr, "set ticslevel 0 \n");
498  fprintf (cmdFilePtr, "splot \'%s\' matrix with lines 0 \n", dataFilePath);
499  if (plotDuration == -1)
500  {
501  cpl_msg_info(cpl_func,"\n");
502  fprintf (cmdFilePtr, "pause %d \" ***** Hit Return to continue *****\" \n", plotDuration);
503  }
504  else
505  fprintf (cmdFilePtr, "pause %d \n", plotDuration);
506 
507  fclose (cmdFilePtr);
508 
509  // Run the command file
510  sprintf (argument, "gnuplot -title \"MIDI DRS\" -geometry 900x900+0+0 %s", cmdFileName);
511  system (argument);
512 
513  // Remove temporary files
514  remove (cmdFileName);
515  }
516 
517  if (plotFile)
518  {
519  if (plotFile == 3) remove (dataFilePath);
520 
521  // Release memory
522  free (dataFilePath);
523  free (cmdFileName);
524  free (argument);
525  free (string);
526  free (title);
527  }
528 
529  // Report
530  if (!freqCalExists)
531  {
532  cpl_msg_info(cpl_func,"\nWavelength Calibration Calculated from Interferometry data \n");
533  cpl_msg_info(cpl_func,"---------------------------------------------------------- \n");
534  fprintf (midiReportPtr, "\nWavelength Calibration Calculated from Interferometry data \n");
535  fprintf (midiReportPtr, "---------------------------------------------------------- \n");
536  for (X = 0; X < format->iXWidth; X++)
537  {
538  if (freqCal[X] == 0.0)
539  {
540  cpl_msg_info(cpl_func,"%3d %7.4f \n", X, zero);
541  fprintf (midiReportPtr, "%3d %7.4f \n", X, zero);
542  }
543  else
544  {
545  freqCal[X] = SPEED_OF_LIGHT/freqCal[X];
546  cpl_msg_info(cpl_func,"%3d %7.4f \n", X, freqCal[X]);
547  fprintf (midiReportPtr, "%3d %7.4f \n", X, freqCal[X]);
548  }
549  }
550  cpl_msg_info(cpl_func,"\n");
551  fprintf (midiReportPtr, "\n");
552 
553  // Open a file for wavelength calibration history
554  wclHistoryPtr = fopen (fileNames->wclHistoryName, "a");
555  fprintf (wclHistoryPtr, "Wavelength Calibration from Interferometry data \n");
556  fprintf (wclHistoryPtr, "Grism ID = %s \n", format->grismId);
557  fprintf (wclHistoryPtr, "Number of Records = %d \n", format->iXWidth);
558  fprintf (wclHistoryPtr, "--------------------------------------- \n");
559  for (X = 0; X < format->iXWidth; X++) fprintf (wclHistoryPtr, "%f \n", freqCal[X]);
560  fclose (wclHistoryPtr);
561 
562  // Create plot
563  if (plotFile) midiCreatePlotFile2D ("WaveCalibInterfData", "Wavelength Claibration from Interferometry data",
564  "Channel", "Wavelength (micron)", 0, freqCal, 0, format->iXWidth, 1, 0);
565 
566  // Readjust valid channels
567  for (X = 0; X < format->iXWidth; X++)
568  {
569  if (freqCal[X] <= 0.F)
570  badChannelList[X] |= BSL_DATA_ERROR;
571  }
572  }
573 
574  return;
575 }
576 /*****************************************************************************/
577 
578 
579 
580 /******************************************************************************
581 * European Southern Observatory
582 * VLTI MIDI Data Reduction Software
583 *
584 * Module name: getChannelSpectrum
585 * Input/Output: See function arguments to avoid duplication
586 * Description: This function ALLOCATES fftsize/2 elements for a PS, and returns a
587 * pointer to it
588 *
589 * History:
590 * 16-Jul-04 (JM) provided the initial idea
591 * 20-Jan-05 (csabet) Cleaned up and extensively modified
592 ******************************************************************************/
593 int getChannelSpectrum (
594  int X, // In: Channel number
595  int lowFreqIndex, // In: First index to consider
596  int highFreqIndex, // In: Last index to consider + 1
597  int *rejectList, // In: Pointer to the begining of the bad Frame List for one channel
598  float *inData1, // In: Pointer to position of frame 0
599  float *inData2, // In: Pointer to position of frame 0 of SECOND region. Null if not used
600  ImageFormat *format, // In: Points to the image format.
601  float *output, // Ou: Output spectrum
602  float *Peakvector) // Ou: Output spectrum
603 
604 {
605 
606  // Local Declarations
607  // ------------------
608  int i, k, scan, numOfPs, *badFrame, minFrames, fftSizeHalf,
609  scanFailed, peakIndex;
610  float accum, dclevel, scale, lengthAve, *data1, *data2, *spectrum,
611  median, peak, ratio, *spectrumPtr;
612  struct Complex *input2ft;
613  char *fileName, *title;
614 /* char *titlePeak; */
615 /* char *fileNamePeak; */
616 
617  // Algorithm
618  // ---------
619  minFrames = MIN_FRAMES_PER_SCAN * format->framesPerScan;
620  fftSizeHalf = (format->fftsize >> 1);
621 
622  // Allocate memory
623  FFTarray = (struct Complex *) calloc(MAXFFTSIZE, sizeof(struct Complex));
624  input2ft = (struct Complex *) calloc(format->fftsize, sizeof(struct Complex));
625  spectrum = (float *) calloc (fftSizeHalf, sizeof (float));
626 
627  // Compute spectrum
628  numOfPs = 0;
629  lengthAve = 0.0;
630 
631 /* // Open file for plotting the Peak and the Median as a function of the scan */
632 
633 /* fileNamePeak = (char *) calloc (MAX_STRING_LENGTH, sizeof (char)); */
634 /* titlePeak = (char *) calloc (MAX_STRING_LENGTH, sizeof (char)); */
635 /* sprintf (fileNamePeak, "PeakSpectrumScanChannel%d", X); */
636 /* sprintf (titlePeak, "PeakChannel %d", X); */
637 
638 
639  for (scan = 0; scan < format->numOfScans; scan++)
640  {
641  scanFailed = 0;
642  memset (input2ft, 0, (sizeof(struct Complex)) * format->fftsize);
643  badFrame = rejectList + scan * format->framesPerScan; // Set to beginning of this scan
644  data1 = inData1 + scan * format->framesPerScan; // Set to beginning of this scan
645  data2 = inData2 + scan * format->framesPerScan; // Set to beginning of this scan
646 
647  // Accumulate to the DC level here:
648  accum = 0.F;
649  k = 0;
650  for (i = 0; i < format->framesPerScan; i++)
651  {
652  // Accumulate good frames only
653  if (!(*badFrame))
654  {
655  accum += *data1 - *data2;
656 
657  // Also copy to fft input array
658  input2ft[k].r = *data1 - *data2;
659  k++;
660  }
661  data1++;
662  data2++;
663  badFrame++;
664  }
665  lengthAve += (float) k;
666 
667  // Process this scan if there were enough good frames
668  if (k > minFrames)
669  {
670  // DC level of this scan
671  dclevel = accum / ((float) k);
672 
673  // Now subtract the dc level from the values we just inputted to the fft input array:
674  for (i = 0; i < k; i++)
675  input2ft[i].r -= dclevel;
676 
677  // Now apply the window function
678  input2ft[--i].r *= 0.145F; // Should point to last nonzero element.
679  input2ft[0].r *= 0.145F;
680  input2ft[--i].r *= 0.5F;
681  input2ft[1].r *= 0.5F;
682  input2ft[--i].r *= 0.855F;
683  input2ft[2].r *= 0.855F;
684 
685  // Now do the FFT:
686  FFT (input2ft, FFTlevel); // Output is waiting in FFTarray
687 
688  // Analyse the scan spectrum
689  spectrumPtr = spectrum;
690  for (i = 0; i < fftSizeHalf; i++)
691  *spectrumPtr++ = Cmag2(FFTarray[i]);
692 
693  peak = signalPeak (spectrum, 0, fftSizeHalf, &peakIndex);
694  median = signalMedian (spectrum, 0, fftSizeHalf);
695  ratio = peak/median;
696 
697  Peakvector[scan]=peak;
698 
699 
700  // Check validity of the peak power
701  if ((ratio > 10.0) && (peakIndex > lowFreqIndex) && (peakIndex < highFreqIndex))
702  {
703  // Now add the (sqrd mag) of the fft result to the power spectrum output:
704  for (i = 0; i < fftSizeHalf; i++)
705  output[i] += spectrum[i];
706 
707  // Increment number of power spectrums
708  numOfPs++;
709  }
710  else
711  {
712  scanFailed = 1;
713  // Transfer bad scans to rejection list
714  for (i = 0; i < format->framesPerScan; i++)
715  rejectList[i + scan * format->framesPerScan] |= BSL_SNR_ERROR;
716  }
717 
718  // Plot
719  if (plotFile && diagnostic > 2)
720  {
721  if (scanFailed)cpl_msg_info(cpl_func,"\n <<ERROR>>: Scan %3d rejected \n\n", scan);
722  cpl_msg_info(cpl_func," Expected low frequency index = %3d \n", lowFreqIndex);
723  cpl_msg_info(cpl_func," Expected high frequency index = %3d \n", highFreqIndex);
724  cpl_msg_info(cpl_func," Found peak index at = %3d \n", peakIndex);
725  cpl_msg_info(cpl_func," peak/median = %f \n", ratio);
726  if (scanFailed) fprintf (midiReportPtr, "\n <<ERROR>>: Scan %3d rejected \n\n", scan);
727  fprintf (midiReportPtr, " Expected low frequency index = %3d \n", lowFreqIndex);
728  fprintf (midiReportPtr, " Expected high frequency index = %3d \n", highFreqIndex);
729  fprintf (midiReportPtr, " Found peak index at = %3d \n", peakIndex);
730  fprintf (midiReportPtr, " peak/median = %f \n", ratio);
731 
732  fileName = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
733  title = (char *) calloc (MAX_STRING_LENGTH, sizeof (char));
734  sprintf (fileName, "SpectrumScan%dChannel%d", scan, X);
735  sprintf (title, "Power Spectrum. Scan %d, Channel %d", scan, X);
736  midiCreatePlotFile2D (fileName, title, "Frequancy bin", "Power Spectrum",
737  1, spectrum, 0, fftSizeHalf, 1, 0);
738  free (fileName);
739  free (title);
740  }
741 
742 
743  }
744  }
745 
746 
747 /* midiCreatePlotFile2D (fileNamePeak, titlePeak, "Scan", "Peak", 0, Peakvector, 0, format->numOfScans, 1, 0); */
748 /* free (fileNamePeak); */
749 /* free (titlePeak); */
750 
751 
752 
753  // All done accumulating. Now normalize:
754  if (numOfPs > 0)
755  {
756  // Take into account energy in scan after windowed
757  lengthAve /= ((float) numOfPs);
758  scale = 4.F * ((float) format->fftsize) / (((float) numOfPs) * (lengthAve - 3.996));
759  for (i = 0; i < fftSizeHalf; i++)
760  output[i] *= scale;
761  }
762 
763  // Release memory
764  free (input2ft);
765  free (spectrum);
766  free (FFTarray);
767 
768  return (numOfPs);
769 }
770 /********************************************************************************/
771 
772 
773 /******************************************************************************
774 * European Southern Observatory
775 * VLTI MIDI Data Reduction Software
776 *
777 * Module name: findSpectralPeak
778 * Input/Output: See function arguments to avoid duplication
779 * Description: Performs a 3-pt interpolation
780 *
781 * History:
782 * 21-Jul-03 (JM)
783 * 20-Jan-05 (csabet) Integrated
784 ******************************************************************************/
785 void findSpectralPeak (
786  float *data, // In: Spectrum input
787  int lowFreqIndex, // In: First index to consider
788  int highFreqIndex, // In: Last index to consider + 1
789  float *peakch, // Ou: Interpolated channel number
790  float *peakinterp) // Ou: Interpolated value at that position
791 {
792 
793  /* Local Declarations
794  --------------------*/
795  int i, j = lowFreqIndex;
796  float peakval = 0.F;
797 
798 
799  /* Algorithm
800  -----------*/
801  for (i = lowFreqIndex; i < highFreqIndex; i++)
802  {
803  if (data[i] > peakval)
804  {
805  j = i;
806  peakval = data[i];
807  }
808  }
809 
810  if ((j == lowFreqIndex) || (j == (highFreqIndex-1)))
811  { // basically that means it failed:
812  *peakch = 0.F;
813  *peakinterp = 0.F;
814  return;
815  }
816 
817  // Do 3-pt interp and return results:
818  *peakch = ((float) j) + (data[j-1]-data[j+1])/(2.F*(data[j-1]+data[j+1]-2.F*data[j]));
819  if (*peakch<0.F) *peakch = 0.F; // just in case.....
820  if (*peakch > ((float) highFreqIndex)) *peakch = ((float) highFreqIndex);
821  *peakinterp = data[j] - 0.125F*(data[j+1] - data[j-1]) * (data[j+1] - data[j-1]) /
822  (data[j+1] + data[j-1] - 2.F*data[j]);
823 
824  return;
825 }
826 /*****************************************************************************/
827 
828 
829 
830 
831 
832 /******************************************************************************
833 * European Southern Observatory
834 * VLTI MIDI Data Reduction Software
835 *
836 * Module name: analyseSpectrum
837 * Input/Output: See function arguments to avoid duplication
838 * Description: Computes unnormalized visibility estimate from spectrum
839 *
840 * History:
841 * 21-Jul-03 (JM)
842 * 20-Jan-05 (csabet) Cleaned up, added error calculation and Integrated
843 ******************************************************************************/
844 float analyseSpectrum ( // Ou: Unnormalized visibility
845  ImageFormat *format, // In: Points to the image format
846  float fringeFreq, // In: Expected optical frequency of fringe, in units of
847  // *spectrum (i.e. actualfreq = fringeFreq * optfreqcal/fftsize)
848  float *spectrum, // In: Main input
849  float calib, // In: Optical freq cal, per fft freq point
850  float *fringePowerErr) // Ou: Error of Unnormalized visibility
851 {
852 
853  /* Local Declarations
854  --------------------*/
855  float fringePower, fringeWidth, slope, offset;
856  int fringeLo1,fringeLo2, tenTHz, fringeHi1,fringeHi2, i;
857  float *noiseSpec, loPwr, hiPwr;
858  int lopt, hipt;
859  float whitenoise = 0.F;
860  int pass;
861 
862  /* Algorithm
863  -----------*/
864 
865  // Allocate memory
866  noiseSpec = (float *) calloc (format->fftsize/2, sizeof(float));
867 
868  // Very crude estimate of the half width of the fringe. (Need to increase when atmospheric OPD velocity is important)
869  fringeWidth = 1.5 * ((float) format->fftsize) /
870  (((float) format->framesPerScan) - 4.F); // -4 to take windowing into account
871 
872  fringeHi1 = (int)(0.5F + fringeFreq + fringeWidth);
873  fringeHi2 = (int)(0.5F + fringeFreq + 3.F * fringeWidth);
874  if (fringeHi2 >= (format->fftsize/2 - 5))
875  fringeHi2 = (format->fftsize/2 - 6);
876  if (fringeHi1 >= (fringeHi2-1)) // very unlikely
877  fringeHi1 = fringeHi2-2;
878 
879  fringeLo1 = (int)(0.5F + fringeFreq - 3.F*fringeWidth);
880  fringeLo2 = (int)(0.5F + fringeFreq - fringeWidth);
881 
882  // NEW: Do NOT include anything below 10 THz:
883  tenTHz = (int) (0.5F + 10.F/calib) ;
884  if (fringeLo1 < tenTHz)
885  fringeLo1 = tenTHz;
886  if (fringeLo1 >= (fringeLo2-1)) // JUST in case
887  fringeLo1 = fringeLo2-2;
888 
889  // NEW: Do 5 passes, each with updated estimate of whitenoise:
890  for (pass = 0; pass < 5; pass++)
891  {
892  // Make est of whitenoise from very highest freqs. First time around, noiseSpec==0
893  whitenoise = 0.F; // to accum
894  for (i = fringeHi2; i < format->fftsize/2; i++)
895  whitenoise += (spectrum[i] - noiseSpec[i]);
896 
897  whitenoise /= (float) (format->fftsize/2 - fringeHi2); // Estimate of whitenoise level. Acual noiselevel = noiseSpec[i] + whitenoise
898 
899  loPwr = 0.0; // To accum
900  for (i = fringeLo1; i < fringeLo2; i++)
901  {
902  if (spectrum[i] > (1.05F*whitenoise))
903  loPwr += log((double) (spectrum[i] - whitenoise));
904  else
905  loPwr += log((double) (.05F*whitenoise));
906  }
907 
908  loPwr /= (double) (fringeLo2 - fringeLo1); // Get average
909 
910  hiPwr = 0.0; // To accum
911  for (i = fringeHi1; i < fringeHi2; i++)
912  {
913  if (spectrum[i] > (1.05F*whitenoise))
914  hiPwr += log((double) (spectrum[i] - whitenoise));
915  else
916  hiPwr += log((double) (.05F*whitenoise));
917  }
918 
919  hiPwr /= (double) (fringeHi2 - fringeHi1); // Get average
920 
921  // Now fit a line to it!
922  slope = (hiPwr-loPwr)/(log((fringeHi2+fringeHi1-1)*0.5F) - log((fringeLo2 + fringeLo1-1)*0.5F));
923  offset = loPwr - slope*log((fringeLo2 + fringeLo1-1)*0.5F);
924 
925  // Now fill in the estimated "noise spectrum":
926  for (i = 1; i < (format->fftsize/2); i++)
927  noiseSpec[i] = exp(offset + slope*log(i));
928 
929  noiseSpec[0] = noiseSpec[1];
930  }
931 
932  if (diagnostic)cpl_msg_info(cpl_func," %6.3f %7.2f %8.2f ", slope, offset, whitenoise);
933  fprintf (midiReportPtr, " %6.3f %7.2f %8.2f ", slope, offset, whitenoise);
934 
935  fringePower = 0.F; // to accum
936  *fringePowerErr = 0.F; // Added, csabet 21-Feb-05
937  lopt = (int)(fringeFreq - fringeWidth);
938  if (lopt < 0) lopt = 0;
939  hipt = (int)(fringeFreq + fringeWidth + 1.F);
940 
941  if (hipt >= format->fftsize/2) hipt = format->fftsize/2 - 1;
942 
943  for (i = lopt; i <= hipt; i++)
944  {
945  fringePower += (spectrum[i] - noiseSpec[i] - whitenoise);
946  *fringePowerErr += (noiseSpec[i] + whitenoise);
947  }
948 
949  // Release memory
950  free (noiseSpec);
951 
952  return (fringePower);
953 }
954 /*****************************************************************************/
955