Line data Source code
1 :
2 : // -----------------------------------------------------------------------------
3 :
4 : /*
5 :
6 : CalStatsDerived.cc
7 :
8 : Description:
9 : ------------
10 : This file contains the member functions of the classes derived from CalStats.
11 :
12 : Classes:
13 : --------
14 : CalStatsReal - This class feeds real data to the CalStats base class.
15 : CalStatsAmp - This class converts complex data to amplitudes and initializes
16 : the CalStats base class.
17 : CalStatsPhase - This class converts complex data to phases and initializes the
18 : CalStats base class.
19 :
20 : Inhertited classes:
21 : -------------------
22 : CalStats - This class calculates statistics on CASA caltables.
23 :
24 : Modification history:
25 : ---------------------
26 : 2011 Nov 15 - Nick Elias, NRAO
27 : Initial version created with classes CalStatsAmp and
28 : CalStatsPhase.
29 : 2011 Dec 11 - Nick Elias, NRAO
30 : Class CalStatsReal added.
31 : 2012 Jan 25 - Nick Elias, NRAO
32 : Logging capability added. Error checking added.
33 :
34 : */
35 :
36 : // -----------------------------------------------------------------------------
37 : // Includes
38 : // -----------------------------------------------------------------------------
39 :
40 : #include <calanalysis/CalAnalysis/CalStatsDerived.h>
41 : #include <casacore/casa/Utilities/GenSort.h>
42 :
43 : // -----------------------------------------------------------------------------
44 : // Start of casa namespace
45 : // -----------------------------------------------------------------------------
46 :
47 : using namespace casacore;
48 : namespace casa {
49 :
50 : const uInt CalStatsPhase::NUM_ITER_UNWRAP = 50;
51 : const Double CalStatsPhase::NEW_RANGE_FACTOR = 5.0;
52 :
53 : // -----------------------------------------------------------------------------
54 : // Start of CalStatsReal class
55 : // -----------------------------------------------------------------------------
56 :
57 : /*
58 :
59 : CalStatsReal
60 :
61 : Description:
62 : ------------
63 : This class feeds real data to the CalStats base class.
64 :
65 : Inhertited classes:
66 : -------------------
67 : CalStats - This class calculates statistics of new CASA caltables.
68 :
69 : Class public member functions:
70 : ------------------------------
71 : CalStatsReal - This constructor feeds real data to the CalStats base class.
72 : ~CalStatsReal - This destructor deallocates the internal memory of an instance.
73 :
74 : 2011 Dec 11 - Nick Elias, NRAO
75 : Initial version created with public member functions
76 : CalStatsReal() and ~CalStatsReal().
77 :
78 : */
79 :
80 : // -----------------------------------------------------------------------------
81 : // Start of CalStatsReal public member functions
82 : // -----------------------------------------------------------------------------
83 :
84 : /*
85 :
86 : CalStatsReal::CalStatsReal
87 :
88 : Description:
89 : ------------
90 : This class feeds real data to the CalStats base class..
91 :
92 : NB: The FEED axis is always included as an iteration axis by default because one
93 : cannot perform a fit along it. The other iteration axis is defined by the user.
94 :
95 : NB: The default CalStats constructor is called first as the default, then the
96 : standard one is called at the end.
97 :
98 : Inputs:
99 : -------
100 : oValue - This reference to a Cube<Double> instance contains the values.
101 : oValueErr - This reference to a Cube<Double> instance contains the value
102 : errors.
103 : oFlag - This reference to a Cube<Bool> instance contains the flags.
104 : oFeed - This reference to a Vector<String> instance is the feed
105 : abscissae.
106 : oFrequency - This reference to a Vector<Double> instance is the frequency
107 : abscissae.
108 : oTime - This reference to a Vector<Double> instance is the time
109 : abscissae.
110 : eAxisIterUserID - This reference to a CalStats::AXIS enum contains either the
111 : FREQUENCY or TIME iteration axes (user defined).
112 :
113 : Outputs:
114 : --------
115 : None.
116 :
117 : Modification history:
118 : ---------------------
119 : 2011 Dec 11 - Nick Elias, NRAO
120 : Initial version.
121 : 2012 Jan 25 - Nick Elias, NRAO
122 : Error checking added.
123 :
124 : */
125 :
126 : // -----------------------------------------------------------------------------
127 :
128 0 : CalStatsReal::CalStatsReal( const Cube<Double>& oValue,
129 : const Cube<Double>& oValueErr, const Cube<Bool>& oFlag,
130 : const Vector<String>& oFeed, const Vector<Double>& oFrequency,
131 0 : const Vector<Double>& oTime, const CalStats::AXIS& eAxisIterUserID )
132 0 : : CalStats() {
133 :
134 : // Create an instance of the CalStats base class constructor and copy its
135 : // state to this CalStatsReal instance
136 :
137 : CalStats* poCS;
138 :
139 : try {
140 0 : poCS = new CalStats( oValue, oValueErr, oFlag, oFeed, oFrequency, oTime,
141 0 : eAxisIterUserID );
142 : }
143 0 : catch ( AipsError oAE ) {
144 0 : throw( oAE );
145 : }
146 :
147 0 : oAxisIterID = IPosition( poCS->axisIterID() );
148 0 : eAxisNonIterID = poCS->axisNonIterID();
149 :
150 0 : oAxisIterFeed = Vector<String>( poCS->axisIterFeed() );
151 0 : oAxisIterUser = Vector<Double>( poCS->axisIterUser() );
152 0 : oAxisNonIter = Vector<Double>( poCS->axisNonIter() );
153 :
154 0 : oStatsShape = IPosition( poCS->statsShape() );
155 :
156 0 : poValue = new Cube<Double>( poCS->value() );
157 0 : poValueErr = new Cube<Double>( poCS->valueErr() );
158 0 : poFlag = new Cube<Bool>( poCS->flag() );
159 :
160 0 : poValueIter = new ArrayIterator<Double>( *poValue, oAxisIterID, false );
161 0 : poValueIter->reset();
162 :
163 0 : poValueErrIter = new ArrayIterator<Double>( *poValueErr, oAxisIterID, false );
164 0 : poValueErrIter->reset();
165 :
166 0 : poFlagIter = new ArrayIterator<Bool>( *poFlag, oAxisIterID, false );
167 0 : poFlagIter->reset();
168 :
169 0 : delete poCS;
170 :
171 :
172 : // Return
173 :
174 0 : return;
175 :
176 : }
177 :
178 : // -----------------------------------------------------------------------------
179 :
180 : /*
181 :
182 : CalStatsReal::~CalStatsReal
183 :
184 : Description:
185 : ------------
186 : This destructor deallocates the internal memory of an instance.
187 :
188 : Inputs:
189 : -------
190 : None.
191 :
192 : Outputs:
193 : --------
194 : None.
195 :
196 : Modification history:
197 : ---------------------
198 : 2011 Dec 11 - Nick Elias, NRAO
199 : Initial version.
200 :
201 : */
202 :
203 : // -----------------------------------------------------------------------------
204 :
205 0 : CalStatsReal::~CalStatsReal( void ) {}
206 :
207 : // -----------------------------------------------------------------------------
208 : // End of CalStatsReal public member functions
209 : // -----------------------------------------------------------------------------
210 :
211 : // -----------------------------------------------------------------------------
212 : // End of CalStatsReal class
213 : // -----------------------------------------------------------------------------
214 :
215 : // -----------------------------------------------------------------------------
216 : // Start of CalStatsAmp class
217 : // -----------------------------------------------------------------------------
218 :
219 : /*
220 :
221 : CalStatsAmp
222 :
223 : Description:
224 : ------------
225 : This class converts complex data to amplitudes and initializes the CalStats base
226 : class.
227 :
228 : Inhertited classes:
229 : -------------------
230 : CalStats - This class calculates statistics of new CASA caltables.
231 :
232 : CalStatsAmp public member functions:
233 : ------------------------------------
234 : CalStatsAmp - This generic constructor converts complex data to amplitudes and
235 : initializes the CalStats base class.
236 : ~CalStatsAmp - This destructor deallocates the internal memory of an instance.
237 :
238 : CalStatsAmp public static member functions:
239 : -------------------------------------------
240 : norm - This member function normalizes the amplitudes their errors.
241 :
242 : Modification history:
243 : ---------------------
244 : 2011 Nov 15 - Nick Elias, NRAO
245 : Initial version created with public member functions are
246 : CalStatsAmp() and ~CalStatsAmp(); and public static member
247 : function is norm().
248 :
249 : */
250 :
251 : // -----------------------------------------------------------------------------
252 : // Start of CalStatsAmp public member functions
253 : // -----------------------------------------------------------------------------
254 :
255 : /*
256 :
257 : CalStatsAmp::CalStatsAmp
258 :
259 : Description:
260 : ------------
261 : This class converts complex data and their errors to amplitudes and their errors
262 : and initializes the CalStats base class.
263 :
264 : NB: The FEED axis is always included as an iteration axis by default because one
265 : cannot perform a fit along it. The other iteration axis is defined by the user.
266 :
267 : NB: The default CalStats constructor is called first as the default, then the
268 : standard one is called at the end.
269 :
270 : NB: The are no input data real-imaginary cross correlations available, so the
271 : amplitude errors do not include them.
272 :
273 : Inputs:
274 : -------
275 : oValue - This reference to a Cube<DComplex> instance contains the
276 : values.
277 : oValueErr - This reference to a Cube<Double> instance contains the value
278 : errors (real and imaginary parts).
279 : oFlag - This reference to a Cube<Bool> instance contains the flags.
280 : oFeed - This reference to a Vector<String> instance is the feed
281 : abscissae.
282 : oFrequency - This reference to a Vector<Double> instance is the frequency
283 : abscissae.
284 : oTime - This reference to a Vector<Double> instance is the time
285 : abscissae.
286 : eAxisIterUserID - This reference to a CalStats::AXIS enum contains either the
287 : FREQUENCY or TIME iteration axes (user defined).
288 : bNorm - This reference to a Bool variable contains the normalization
289 : flag (true = normalize, false = don't normalize).
290 :
291 : Outputs:
292 : --------
293 : None.
294 :
295 : Modification history:
296 : ---------------------
297 : 2011 Nov 15 - Nick Elias, NRAO
298 : Initial version.
299 : 2012 Jan 25 - Nick Elias, NRAO
300 : Error checking added.
301 : 2012 Feb 15 - Nick Elias, NRAO
302 : Value error input parameter changed from DComplex to Double.
303 : 2012 Mar 28 - Nick Elias, NRAO
304 : Changed the normalization code so that vectors are iteratively fed
305 : to CalStatsAmp::norm().
306 : 2012 Mar 29 - Nick Elias, NRAO
307 : Member function can now normalize along the frequency and time
308 : axes.
309 :
310 : */
311 :
312 : // -----------------------------------------------------------------------------
313 :
314 0 : CalStatsAmp::CalStatsAmp( const Cube<DComplex>& oValue,
315 : const Cube<Double>& oValueErr, const Cube<Bool>& oFlag,
316 : const Vector<String>& oFeed, const Vector<Double>& oFrequency,
317 : const Vector<Double>& oTime, const CalStats::AXIS& eAxisIterUserID,
318 0 : const Bool& bNorm ) : CalStats() {
319 :
320 : // Calculate the amplitudes and their errors
321 :
322 0 : Cube<Double> oAmp( amplitude( oValue ) );
323 :
324 0 : Cube<Double> oAmpErr = oValueErr.copy();
325 :
326 :
327 : // Create the iterators. The input flag cube is copied since it cannot be
328 : // modified.
329 :
330 0 : IPosition oIterShape( 2, (ssize_t) CalStats::FEED, eAxisIterUserID );
331 :
332 0 : Cube<Bool> oFlagCopy( oFlag.copy() );
333 0 : ArrayIterator<Bool> oFlagIter( oFlagCopy, oIterShape, false );
334 :
335 0 : ArrayIterator<Double> oAmpIter( oAmp, oIterShape, false );
336 0 : ArrayIterator<Double> oAmpErrIter( oAmpErr, oIterShape, false );
337 :
338 :
339 : // If selected, normalize the amplitudes and their errors
340 :
341 0 : while ( bNorm && !oAmpIter.pastEnd() ) {
342 :
343 0 : uInt uiNumAbs = 0;
344 0 : if ( eAxisIterUserID == CalStats::TIME ) {
345 0 : uiNumAbs = oFrequency.nelements();
346 : } else {
347 0 : uiNumAbs = oTime.nelements();
348 : }
349 :
350 0 : if ( uiNumAbs <= 1 ) {
351 0 : oFlagIter.next(); oAmpIter.next(); oAmpErrIter.next();
352 0 : continue;
353 : }
354 :
355 0 : IPosition oShape( 1, uiNumAbs );
356 :
357 0 : Vector<Bool> oFlagV( oFlagIter.array().copy().reform(oShape) );
358 0 : Vector<Double> oAmpV( oAmpIter.array().copy().reform(oShape) );
359 0 : Vector<Double> oAmpErrV( oAmpErrIter.array().copy().reform(oShape) );
360 :
361 0 : norm( oAmpV, oAmpErrV, oFlagV );
362 :
363 0 : oFlagIter.array() = oFlagV;
364 0 : oAmpIter.array() = oAmpV;
365 0 : oAmpErrIter.array() = oAmpErrV;
366 :
367 0 : oFlagIter.next(); oAmpIter.next(); oAmpErrIter.next();
368 :
369 : }
370 :
371 :
372 : // Create an instance of the CalStats base class constructor and copy its
373 : // state to this CalStatsAmp instance
374 :
375 : CalStats* poCS;
376 :
377 : try {
378 0 : poCS = new CalStats( oAmp, oAmpErr, oFlagCopy, oFeed, oFrequency, oTime,
379 0 : eAxisIterUserID );
380 : }
381 0 : catch ( AipsError oAE ) {
382 0 : throw( oAE );
383 : }
384 :
385 0 : oAxisIterID = IPosition( poCS->axisIterID() );
386 0 : eAxisNonIterID = poCS->axisNonIterID();
387 :
388 0 : oAxisIterFeed = Vector<String>( poCS->axisIterFeed() );
389 0 : oAxisIterUser = Vector<Double>( poCS->axisIterUser() );
390 0 : oAxisNonIter = Vector<Double>( poCS->axisNonIter() );
391 :
392 0 : oStatsShape = IPosition( poCS->statsShape() );
393 :
394 0 : poValue = new Cube<Double>( poCS->value() );
395 0 : poValueErr = new Cube<Double>( poCS->valueErr() );
396 0 : poFlag = new Cube<Bool>( poCS->flag() );
397 :
398 0 : poValueIter = new ArrayIterator<Double>( *poValue, oAxisIterID, false );
399 0 : poValueIter->reset();
400 :
401 0 : poValueErrIter = new ArrayIterator<Double>( *poValueErr, oAxisIterID, false );
402 0 : poValueErrIter->reset();
403 :
404 0 : poFlagIter = new ArrayIterator<Bool>( *poFlag, oAxisIterID, false );
405 0 : poFlagIter->reset();
406 :
407 0 : delete poCS;
408 :
409 :
410 : // Return
411 :
412 0 : return;
413 :
414 : }
415 :
416 : // -----------------------------------------------------------------------------
417 :
418 : /*
419 :
420 : CalStatsAmp::~CalStatsAmp
421 :
422 : Description:
423 : ------------
424 : This destructor deallocates the internal memory of an instance.
425 :
426 : Inputs:
427 : -------
428 : None.
429 :
430 : Outputs:
431 : --------
432 : None.
433 :
434 : Modification history:
435 : ---------------------
436 : 2011 Nov 15 - Nick Elias, NRAO
437 : Initial version.
438 :
439 : */
440 :
441 : // -----------------------------------------------------------------------------
442 :
443 0 : CalStatsAmp::~CalStatsAmp( void ) {}
444 :
445 : // -----------------------------------------------------------------------------
446 : // End of CalStatsAmp public member functions
447 : // -----------------------------------------------------------------------------
448 :
449 : // -----------------------------------------------------------------------------
450 : // Start of CalStatsAmp public static member functions
451 : // -----------------------------------------------------------------------------
452 :
453 : /*
454 :
455 : CalStatsAmp::norm
456 :
457 : Description:
458 : ------------
459 : This member function normalizes the amplitudes and their errors.
460 :
461 : NB: The normalization is applied only along the frequency axis.
462 :
463 : NB: The normalization is applied only when the number of unflagged frequencies
464 : is greater than 1.
465 :
466 : NB: All flags corresponding to amplitudes less then 1.0E-08 times the peak
467 : amplitude (along the FREQUENCY axis) are updated to true.
468 :
469 : Inputs:
470 : -------
471 : oAmp - This reference to a Vector<Double> instance contains the unnormalized
472 : amplitudes.
473 : oAmpErr - This reference to a Vector<Double> instance contains the unnormalized
474 : amplitude errors.
475 : oFlag - This reference to a Vector<Bool> instance contains the flags.
476 :
477 : Outputs:
478 : --------
479 : oAmp - This reference to a Vector<Double> instance contains the normalized
480 : amplitudes.
481 : oAmpErr - This reference to a Vector<Double> instance contains the normalized
482 : amplitude errors.
483 : oFlag - This reference to a Vector<Bool> instance contains the flags.
484 :
485 : Modification history:
486 : ---------------------
487 : 2011 Dec 11 - Nick Elias, NRAO
488 : Initial version.
489 : 2012 Jan 25 - Nick Elias, NRAO
490 : Logging capability added.
491 : 2012 Mar 28 - Nick Elias, NRAO
492 : Eliminated iteration and made input amplitude, amplitude error,
493 : and flag cubes into vectors. Flags are now actually used.
494 :
495 : */
496 :
497 : // -----------------------------------------------------------------------------
498 :
499 0 : void CalStatsAmp::norm( Vector<Double>& oAmp, Vector<Double>& oAmpErr,
500 : Vector<Bool>& oFlag ) {
501 :
502 : // Eliminate the flagged amplitudes and their errors
503 :
504 0 : MaskedArray<Double> oAmpM( oAmp, !oFlag );
505 0 : Vector<Double> oAmpC( oAmpM.getCompressedArray() );
506 :
507 0 : MaskedArray<Double> oAmpErrM( oAmpErr, !oFlag );
508 0 : Vector<Double> oAmpErrC( oAmpErrM.getCompressedArray() );
509 :
510 :
511 : // Return if the length of the abscissa is unity
512 :
513 0 : uInt uiNumAbsC = oAmpC.nelements();
514 :
515 0 : if ( uiNumAbsC <= 1 ) {
516 0 : LogIO log( LogOrigin( "CalStatsAmp", "norm", WHERE ) );
517 : // An entire scan for a basline being flagged can cause this
518 : // This is not entirly uncommon so this was switched from WARN -> NORMAL
519 : log << LogIO::NORMAL
520 : << "Abscissa has a dimension <= 1, no normalization"
521 0 : << LogIO::POST;
522 0 : return;
523 : }
524 :
525 :
526 : // Normalize the amplitudes and their errors along the abscissa. Flag all low
527 : // amplitudes.
528 :
529 0 : Double dAmpMax = max( oAmpC );
530 :
531 0 : Vector<Bool> oFlagLow( oAmp <= (Double) 1.0E-08*dAmpMax );
532 0 : oFlag = oFlag || oFlagLow;
533 :
534 0 : uInt uiNumAbs = oAmp.nelements();
535 :
536 0 : for ( uInt a=0; a<uiNumAbs; a++ ) {
537 0 : if ( !oFlag[a] ) {
538 0 : oAmp[a] /= dAmpMax;
539 0 : oAmpErr[a] /= dAmpMax;
540 : }
541 : }
542 :
543 :
544 : // Return
545 :
546 0 : return;
547 :
548 : }
549 :
550 : // -----------------------------------------------------------------------------
551 : // End of CalStatsAmp public static member functions
552 : // -----------------------------------------------------------------------------
553 :
554 : // -----------------------------------------------------------------------------
555 : // End of CalStatsAmp class
556 : // -----------------------------------------------------------------------------
557 :
558 : // -----------------------------------------------------------------------------
559 : // Start of CalStatsPhase class
560 : // -----------------------------------------------------------------------------
561 :
562 : /*
563 :
564 : CalStatsPhase
565 :
566 : Description:
567 : ------------
568 : This class converts complex data to phases and initializes the CalStats base
569 : class.
570 :
571 : Inhertited classes:
572 : -------------------
573 : CalStats - This class calculates statistics of new CASA caltables.
574 :
575 : Class public member functions:
576 : ------------------------------
577 : CalStatsPhase - This generic constructor converts complex data to amplitudes
578 : and initializes the CalStats base class.
579 : ~CalStatsPhase - This destructor deallocates the internal memory of an instance.
580 :
581 : CalStatsPhase public static member functions:
582 : ---------------------------------------------
583 : unwrapGD - This member function unwraps the phases along the frequency axis
584 : with respect to the group delay.
585 : unwrapSimple - This member function performs a simple unwrapping procedure for
586 : both frequency and temporal abscissae.
587 :
588 : CalStatsPhase private static member functions:
589 : ----------------------------------------------
590 : fringePacket2 - This member function forms the squared-amplitude fringe packet.
591 :
592 : CalStatsPhase templated private static member functions:
593 : --------------------------------------------------------
594 : maxLocation - This member function finds the abscissa corresponding to the peak
595 : value of an ordinate vector.
596 :
597 : Modification history:
598 : ---------------------
599 : 2011 Nov 15 - Nick Elias, NRAO
600 : Initial version created with public member functions are
601 : CalStatsPhase() and ~CalStatsPhase(); and public static member
602 : function is unwrap().
603 : 2012 Mar 27 - Nick Elias, NRAO
604 : Private static member functions fringePacket2() and maxLocation()
605 : added. Private static member variables NUM_ITER_UNWRAP and
606 : NEW_RANGE_FACTOR added.
607 : 2012 Mar 30 - Nick Elias, NRAO
608 : Public static member function unwrap() renamed to unwrapGD().
609 : Public static member function unwrapSimple() added.
610 :
611 : */
612 :
613 : // -----------------------------------------------------------------------------
614 : // Start of CalStatsPhase public member functions
615 : // -----------------------------------------------------------------------------
616 :
617 : /*
618 :
619 : CalStatsPhase::CalStatsPhase
620 :
621 : Description:
622 : ------------
623 : This class converts complex data and their errors to phases and their errors and
624 : initializes the CalStats base class.
625 :
626 : NB: The FEED axis is always included as an iteration axis by default because one
627 : cannot perform a fit along it. The other iteration axis is defined by the user.
628 :
629 : NB: All flags corresponding to amplitudes less then 1.0E-08 times the peak
630 : amplitude are updated to true.
631 :
632 : NB: The default CalStats constructor is called first as the default, then the
633 : standard one is called at the end.
634 :
635 : NB: The are no input data real-imaginary cross correlations available, so the
636 : phase errors do not include them.
637 :
638 : NB: For unwrapping along the time axis (iteration axis CalStats::FREQUENCY), the
639 : unwrapSimple() function is used. For unwrapping along the frequency axis
640 : (iteration axis CalStats::TIME), dJumpMax==0.0 leads to unwrapGD() while
641 : dJumpMax!=0.0 leads to unwrapSimple().
642 :
643 : Inputs:
644 : -------
645 : oValue - This reference to a Cube<DComplex> instance contains the
646 : values.
647 : oValueErr - This reference to a Cube<Double> instance contains the value
648 : errors (real and imaginary parts).
649 : oFlag - This reference to a Cube<Bool> instance contains the flags.
650 : oFeed - This reference to a Vector<String> instance is the feed
651 : abscissae.
652 : oFrequency - This reference to a Vector<Double> instance is the frequency
653 : abscissae.
654 : oTime - This reference to a Vector<Double> instance is the time
655 : abscissae.
656 : eAxisIterUserID - This reference to a CalStats::AXIS enum contains either the
657 : CalStats::FREQUENCY or CalStats::TIME iteration axes (user
658 : defined).
659 : bUnwrap - This reference to a Bool variable contains the unwrapping flag
660 : (true = unwrap, false = don't unwrap).
661 : dJumpMax - This reference to a Double variable contains the maximum
662 : deviation from +/- M_PI for adjacent points to be unwrapped
663 : by +/- 2.0*M_PI (in radians). This parameter is always used
664 : when the specified iteration axis is CalStats::FREQUENCY
665 : (unwrapping along the CalStats::TIME axis). If the specified
666 : iteration axis is CalStats::TIME (unwrapping along the
667 : CalStats::FREQUENCY axis), this parameter selects the type of
668 : unwrapping (dJumpMax==0.0 --> group-delay unwrapping, dJumpMax
669 : != 0.0 --> simple unwrapping).
670 :
671 : Outputs:
672 : --------
673 : None.
674 :
675 : Modification history:
676 : ---------------------
677 : 2011 Nov 15 - Nick Elias, NRAO
678 : Initial version.
679 : 2011 Dec 11 - Nick Elias, NRAO
680 : Flag updates according to low amplitude was added.
681 : 2012 Jan 25 - Nick Elias, NRAO
682 : Error checking added.
683 : 2012 Feb 15 - Nick Elias, NRAO
684 : Value error input parameter changed from DComplex to Double.
685 : 2012 Mar 28 - Nick Elias, NRAO
686 : Changed the unwrapping code so that vectors are iteratively fed to
687 : CalStatsPhase::unwrapSimple() or CalStatsPhase::unwrapGD().
688 : 2012 Apr 01 - Nick Elias, NRAO
689 : Input parameter dJumpMax added.
690 :
691 : */
692 :
693 : // -----------------------------------------------------------------------------
694 :
695 0 : CalStatsPhase::CalStatsPhase( const Cube<DComplex>& oValue,
696 : const Cube<Double>& oValueErr, const Cube<Bool>& oFlag,
697 : const Vector<String>& oFeed, const Vector<Double>& oFrequency,
698 : const Vector<Double>& oTime, const CalStats::AXIS& eAxisIterUserID,
699 0 : const Bool& bUnwrap, const Double& dJumpMax ) : CalStats() {
700 :
701 : // Calculate the phases and the initial phase error cube (set to 0.0)
702 :
703 0 : Cube<Double> oPhase( phase(oValue) );
704 :
705 0 : Cube<Double> oPhaseErr( oPhase.shape() );
706 :
707 :
708 : // Create the iterators. The input flag cube is copied since it cannot be
709 : // modified.
710 :
711 0 : IPosition oIterShape( 2, (ssize_t) CalStats::FEED, eAxisIterUserID );
712 :
713 0 : ReadOnlyArrayIterator<DComplex> oValueIter( oValue, oIterShape, false );
714 0 : ReadOnlyArrayIterator<Double> oValueErrIter( oValueErr, oIterShape, false );
715 :
716 0 : Cube<Bool> oFlagCopy( oFlag.copy() );
717 0 : ArrayIterator<Bool> oFlagIter( oFlagCopy, oIterShape, false );
718 :
719 0 : ArrayIterator<Double> oPhaseIter( oPhase, oIterShape, false );
720 0 : ArrayIterator<Double> oPhaseErrIter( oPhaseErr, oIterShape, false );
721 :
722 :
723 : // If selected, unwrap the phases
724 :
725 0 : while ( bUnwrap && !oPhaseIter.pastEnd() ) {
726 :
727 0 : uInt uiNumAbs = 0;
728 0 : if ( eAxisIterUserID == CalStats::TIME ) {
729 0 : uiNumAbs = oFrequency.nelements();
730 : } else {
731 0 : uiNumAbs = oTime.nelements();
732 : }
733 :
734 0 : if ( uiNumAbs <= 1 ) {
735 0 : oFlagIter.next(); oPhaseIter.next();
736 0 : continue;
737 : }
738 :
739 0 : IPosition oShape( 1, uiNumAbs );
740 :
741 0 : Vector<Bool> oFlagV( oFlagIter.array().copy().reform(oShape) );
742 0 : Vector<Double> oPhaseV( oPhaseIter.array().copy().reform(oShape) );
743 :
744 0 : if ( eAxisIterUserID == CalStats::TIME ) {
745 0 : if ( dJumpMax == 0.0 ) {
746 0 : unwrapGD( oPhaseV, oFrequency, oFlagV );
747 : } else {
748 0 : unwrapSimple( oPhaseV, dJumpMax, oFlagV );
749 : }
750 : } else {
751 0 : unwrapSimple( oPhaseV, dJumpMax, oFlagV );
752 : }
753 :
754 0 : oPhaseIter.array() = oPhaseV;
755 :
756 0 : oFlagIter.next(); oPhaseIter.next();
757 :
758 : }
759 :
760 :
761 : // Reset the iterators
762 :
763 0 : oFlagIter.reset(); oPhaseIter.next();
764 :
765 :
766 : // Calculate the phase errors. They require dividing by amplitude. Set the
767 : // flags according to low amplitudes (corresponding to phase errors greater
768 : // than M_PI). All flagged phase errors are set to M_PI. The iteration axes
769 : // are FEED and TIME. A FREQUENCY for loop is located inside the FEED/TIME
770 : // iteration loop to set the errors.
771 :
772 0 : while ( !oValueIter.pastEnd() ) {
773 :
774 0 : uInt uiNumAbs = oValueIter.array().nelements();
775 0 : IPosition oShape( 1, uiNumAbs );
776 :
777 0 : Vector<Double> oPhaseErrV( oShape );
778 :
779 0 : Vector<DComplex> oValueV( oValueIter.array().copy().reform(oShape) );
780 0 : Vector<Double> oValueErrV( oValueErrIter.array().copy().reform(oShape) );
781 :
782 0 : Vector<Double> oAmpV( amplitude(oValueV) );
783 :
784 0 : Vector<Bool> oFlagV( oFlagIter.array().copy().reform(oShape) );
785 0 : Vector<Bool> oFlagLow( oAmpV <= oValueErrV/((Double) M_PI) );
786 :
787 0 : oFlagV = oFlagV || oFlagLow;
788 0 : oFlagIter.array() = oFlagV;
789 :
790 0 : for ( uInt a=0; a<uiNumAbs; a++ ) {
791 0 : if ( !oFlagV[a] ) {
792 0 : oPhaseErrV[a] = oValueErrV[a] / oAmpV[a];
793 : } else {
794 0 : oPhaseErrV[a] = (Double) M_PI;
795 : }
796 : }
797 :
798 0 : oPhaseErrIter.array() = oPhaseErrV;
799 :
800 0 : oValueIter.next(); oValueErrIter.next(); oFlagIter.next();
801 0 : oPhaseErrIter.next();
802 :
803 : }
804 :
805 :
806 : // Create an instance of the CalStats base class constructor and copy its
807 : // state to this CalStatsPhase instance
808 :
809 : CalStats* poCS;
810 :
811 : try {
812 0 : poCS = new CalStats( oPhase, oPhaseErr, oFlagCopy, oFeed, oFrequency, oTime,
813 0 : eAxisIterUserID );
814 : }
815 0 : catch ( AipsError oAE ) {
816 0 : throw( oAE );
817 : }
818 :
819 0 : oAxisIterID = IPosition( poCS->axisIterID() );
820 0 : eAxisNonIterID = poCS->axisNonIterID();
821 :
822 0 : oAxisIterFeed = Vector<String>( poCS->axisIterFeed() );
823 0 : oAxisIterUser = Vector<Double>( poCS->axisIterUser() );
824 0 : oAxisNonIter = Vector<Double>( poCS->axisNonIter() );
825 :
826 0 : oStatsShape = IPosition( poCS->statsShape() );
827 :
828 0 : poValue = new Cube<Double>( poCS->value() );
829 0 : poValueErr = new Cube<Double>( poCS->valueErr() );
830 0 : poFlag = new Cube<Bool>( poCS->flag() );
831 :
832 0 : poValueIter = new ArrayIterator<Double>( *poValue, oAxisIterID, false );
833 0 : poValueIter->reset();
834 :
835 0 : poValueErrIter = new ArrayIterator<Double>( *poValueErr, oAxisIterID, false );
836 0 : poValueErrIter->reset();
837 :
838 0 : poFlagIter = new ArrayIterator<Bool>( *poFlag, oAxisIterID, false );
839 0 : poFlagIter->reset();
840 :
841 0 : delete poCS;
842 :
843 :
844 : // Return
845 :
846 0 : return;
847 :
848 : }
849 :
850 : // -----------------------------------------------------------------------------
851 :
852 : /*
853 :
854 : CalStatsPhase::~CalStatsPhase
855 :
856 : Description:
857 : ------------
858 : This destructor deallocates the internal memory of an instance.
859 :
860 : Inputs:
861 : -------
862 : None.
863 :
864 : Outputs:
865 : --------
866 : None.
867 :
868 : Modification history:
869 : ---------------------
870 : 2011 Nov 15 - Nick Elias, NRAO
871 : Initial version.
872 :
873 : */
874 :
875 : // -----------------------------------------------------------------------------
876 :
877 0 : CalStatsPhase::~CalStatsPhase( void ) {}
878 :
879 : // -----------------------------------------------------------------------------
880 : // End of CalStatsPhase public member functions
881 : // -----------------------------------------------------------------------------
882 :
883 : // -----------------------------------------------------------------------------
884 : // Start of CalStatsPhase public static member functions
885 : // -----------------------------------------------------------------------------
886 :
887 : /*
888 :
889 : CalStatsPhase::unwrapSimple
890 :
891 : Description:
892 : ------------
893 : This member function performs a simple unwrapping procedure for both frequency
894 : and temporal abscissae.
895 :
896 : Algorithm:
897 : ----------
898 : * If the first point is a little less than +M_PI and the second point is a
899 : little more than -M_PI, add 2.0*M_PI to the second point.
900 : * If the first point is a little more than -M_PI and the second point is a
901 : ittle less than +M_PI, subtract 2.0*M_PI from the second point.
902 : * "A little more" means within dJumpMax of +/- M_PI.
903 : * Flagged data are ignored, which could be a problem if a lot of them occur
904 : sequentially.
905 :
906 : Inputs:
907 : -------
908 : oPhase - This reference to a Vector<Double> instance contains the wrapped
909 : phases.
910 : dJumpMax - This reference to a Double variable contains the maximum deviation
911 : from +/- M_PI for adjacent points to be unwrapped by +/- 2.0*M_PI (in
912 : radians).
913 : oFlag - This reference to a Vector<Bool> instance contains the flags.
914 :
915 : Outputs:
916 : --------
917 : oPhase - This reference to a Vector<Double> instance contains the unwrapped
918 : phases.
919 :
920 : Modification history:
921 : ---------------------
922 : 2012 Mar 30 - Nick Elias, NRAO
923 : Initial version.
924 :
925 : */
926 :
927 : // -----------------------------------------------------------------------------
928 :
929 0 : void CalStatsPhase::unwrapSimple( Vector<Double>& oPhase,
930 : const Double& dJumpMax, const Vector<Bool>& oFlag ) {
931 :
932 : // Initialize the number of elements and make an immutable copy of the input
933 : // phase vector
934 :
935 0 : uInt uiNumAbs = oPhase.nelements();
936 :
937 0 : Vector<Double> oPhaseIn( oPhase.copy() );
938 :
939 :
940 : // Perform the simple unwrapping. The unwrapping occurs if subsequent points
941 : // are both within dJumpMax of M_PI or -M_PI. Flagged data are ignored.
942 :
943 0 : for ( uInt a=1; a<uiNumAbs; a++ ) {
944 :
945 0 : if ( oFlag[a-1] ) continue;
946 :
947 0 : uInt a2 = 0;
948 0 : for ( a2=a; a2<uiNumAbs; a2++ ) {
949 0 : if ( !oFlag[a2] ) break;
950 : }
951 0 : if ( a2 >= uiNumAbs ) return;
952 :
953 : // The first point is a little less than +M_PI and the second point is a
954 : // little more than -M_PI, add 2.0*M_PI to the second point
955 0 : if ( M_PI-oPhaseIn[a-1] <= dJumpMax && M_PI+oPhaseIn[a2] <= dJumpMax ) {
956 0 : for ( uInt a3=a2; a3<uiNumAbs; a3++ ) oPhase[a3] += 2.0 * M_PI;
957 : }
958 :
959 : // The first point is a little more than -M_PI and the second point is a
960 : // little less than +M_PI, subtract 2.0*M_PI from the second point
961 0 : if ( M_PI+oPhaseIn[a-1] <= dJumpMax && M_PI-oPhaseIn[a2] <= dJumpMax ) {
962 0 : for ( uInt a3=a2; a3<uiNumAbs; a3++ ) oPhase[a3] -= 2.0 * M_PI;
963 : }
964 :
965 : }
966 :
967 :
968 : // Return
969 :
970 0 : return;
971 :
972 : }
973 :
974 : // -----------------------------------------------------------------------------
975 :
976 : /*
977 :
978 : CalStatsPhase::unwrapGD
979 :
980 : Description:
981 : ------------
982 : This member function unwraps the phases along the frequency axis with respect to
983 : the group delay.
984 :
985 : NB: The unwrapping is applied only along the frequency axis. The unwrapping is
986 : applied only when the number of unflagged frequencies is greater than 1 (setting
987 : the bar very low). If the number of unflagged frequencies is small, you may
988 : get crappy results.
989 :
990 : NB: This algorithm should work better with low-S/N data compared to simple
991 : unwrapping, but it will not work if the S/N is abysmally low. To understand
992 : why this statement is true, consider an analogy with BPOLY. BPOLY is used when
993 : the S/N per channel is low. The fit uses all bandpass data at once to maximize
994 : the available S/N. This phase unwrapping algorithm creates a fringe packet,
995 : using all of the bandpass data at once, to estimate the delay before unwrapping.
996 :
997 : NB: If the true delay is outside of the unaliased search window, the unwrapping
998 : aliases into the search window. This scenario is OK if only continuous phase
999 : plotting is required.
1000 :
1001 : NB: If the dispersion or other wiggles are large, this technique may not work
1002 : well.
1003 :
1004 : Algorithm:
1005 : ----------
1006 : * Sort the input frequencies and form the differences. Sort the frequency
1007 : differences. The desired frequency increment is the minimum value (except for
1008 : zero, which arises datasets from spectral windows with the same frequencies;
1009 : choose the next largest value).
1010 : * Determine the maximum frequency.
1011 : * For the first iteration:
1012 : - Calculate the initial time increment using the maximum frequency (Nyquist
1013 : criterion).
1014 : - Calculate the initial time range using the frequency increment.
1015 : - Form the initial time vector. The edges of the unaliased search window are
1016 : +/- 0.5 times the initial time range (centered around zero group delay).
1017 : - Form the initial squared-amplitude fringe packet.
1018 : - Find the peak of the initial squared-amplitude fringe packet. The time
1019 : corresponding to this peak is the initial group delay estimate.
1020 : * For subsequent iterations:
1021 : - Set the new time range to NEW_RANGE_FACTOR times the previous time
1022 : increment.
1023 : - Set the new time increment to the new time range divided by the number of
1024 : times (this number is the same as the initial iteration and doesn't change).
1025 : - Form the new time vector. The edges of the search window are +/- times the
1026 : new time range (centered around the previous group delay estimate).
1027 : - Form the new squared-amplitude fringe packet.
1028 : - Find the peak of the new squared-amplitude fringe packet. The time
1029 : corresponding to this peak is the new group delay estimate.
1030 : - Has the group delay converged? If not repeat for another iteration,
1031 : otherwise stop iterating. The maximum number of iterations is
1032 : NUM_ITER_UNWRAP.
1033 : * Form the phase versus frequency using the group delay.
1034 : * Subtract the group delay phases from the input phases to form the differential
1035 : delay.
1036 : * Subtract the first differential delay from all of the differential delays.
1037 : * Starting at the first frequency, search for phase jumps. For each one found,
1038 : add/subtract 2.0*M_PI*N (N=the number of phase jumps; it can be positive or
1039 : negative) for all subsequenct frequencies. Flagged data are not unwrapped.
1040 :
1041 : Inputs:
1042 : -------
1043 : oPhase - This reference to a Vector<Double> instance contains the wrapped
1044 : phases.
1045 : oFrequency - This reference to a Vector<Double> instance is the frequency
1046 : abscissa.
1047 : oFlag - This reference to a Vector<Bool> instance contains the flags.
1048 :
1049 : Outputs:
1050 : --------
1051 : oPhase - This reference to a Vector<Double> instance contains the unwrapped
1052 : phases.
1053 :
1054 : Modification history:
1055 : ---------------------
1056 : 2011 Nov 15 - Nick Elias, NRAO
1057 : Initial stub version.
1058 : 2012 Jan 25 - Nick Elias, NRAO
1059 : Logging capability added.
1060 : 2012 Mar 27 - Nick Elias, NRAO
1061 : Initial working version.
1062 : 2012 Mar 28 - Nick Elias, NRAO
1063 : Eliminated iteration and made input phase and flag cubes into
1064 : vectors. Flags are now actually used.
1065 :
1066 : */
1067 :
1068 : // -----------------------------------------------------------------------------
1069 :
1070 0 : void CalStatsPhase::unwrapGD( Vector<Double>& oPhase,
1071 : const Vector<Double>& oFrequency, const Vector<Bool>& oFlag ) {
1072 :
1073 : // Eliminate the flagged phases and frequencies
1074 :
1075 0 : MaskedArray<Double> oPhaseM( oPhase, !oFlag );
1076 0 : Vector<Double> oPhaseC( oPhaseM.getCompressedArray() );
1077 :
1078 0 : MaskedArray<Double> oFrequencyM( oFrequency, !oFlag );
1079 0 : Vector<Double> oFrequencyC( oFrequencyM.getCompressedArray() );
1080 :
1081 :
1082 : // Return if the length of the frequency axis is unity
1083 :
1084 0 : uInt uiNumFrequencyC = oFrequencyC.nelements();
1085 :
1086 0 : if ( uiNumFrequencyC <= 1 ) {
1087 0 : LogIO log( LogOrigin( "CalStatsPhase", "unwrap", WHERE ) );
1088 : log << LogIO::WARN
1089 : << "Frequency axis has a dimension <= 1, no unwrapping performed"
1090 0 : << LogIO::POST;
1091 0 : return;
1092 : }
1093 :
1094 :
1095 : // Calculate the minimum frequency increment. If there are overlapping
1096 : // spectral windows, some of the frequency increments may be zero if the
1097 : // duplicate channels are not flagged. Make sure to ignore all zeros.
1098 :
1099 0 : Vector<Double> oFreqDeltaC( uiNumFrequencyC-1 );
1100 :
1101 0 : for ( uInt f=1; f<uiNumFrequencyC; f++ ) {
1102 0 : oFreqDeltaC[f-1] = oFrequencyC[f] - oFrequencyC[f-1];
1103 : }
1104 :
1105 0 : Sort::Order eOrder = Sort::Ascending;
1106 0 : Int iOptions = Sort::QuickSort;
1107 0 : GenSort<Double>::sort( oFreqDeltaC, eOrder, (int) iOptions );
1108 :
1109 0 : uInt fD = 0;
1110 0 : for ( fD=0; fD<uiNumFrequencyC-1; fD++ ) {
1111 0 : if ( oFreqDeltaC[fD] != 0.0 ) break;
1112 : }
1113 :
1114 0 : if ( fD >= uiNumFrequencyC-1 ) {
1115 0 : LogIO log( LogOrigin( "CalStatsPhase", "unwrap", WHERE ) );
1116 0 : log << "Something is very wrong with the frequencies" << LogIO::EXCEPTION;
1117 : }
1118 :
1119 0 : Double dFreqDeltaC = oFreqDeltaC[fD];
1120 :
1121 :
1122 : // Calculate the maximum frequency
1123 :
1124 0 : Double dFreqMaxC = max( oFrequencyC );
1125 :
1126 :
1127 : // Calculate the initial time increment and range
1128 :
1129 0 : Double dTimeDelta = 0.5 / dFreqMaxC;
1130 :
1131 0 : Double dTimeRange = 1.0 / dFreqDeltaC;
1132 :
1133 :
1134 : // Initialize the time vector. The center of the time range is zero group
1135 : // delay.
1136 :
1137 0 : uInt uiNumTime = (uInt) fabs( dTimeRange/dTimeDelta + 1.0 );
1138 :
1139 0 : Vector<Double> oTime( uiNumTime );
1140 0 : indgen<Double>( oTime, 0.0-0.5*dTimeRange, dTimeDelta );
1141 :
1142 :
1143 : // Form the squared magnitude of the initial fringe packet and find the group
1144 : // delay
1145 :
1146 0 : Vector<Double> oFringePacket( fringePacket2( oPhaseC, oFrequencyC, oTime ) );
1147 :
1148 0 : Double dGroupDelay = maxLocation<Double>( oTime, oFringePacket );
1149 :
1150 :
1151 : // Initialize the number of iterations
1152 :
1153 0 : uInt uiNumIter = 0;
1154 :
1155 :
1156 : // Iteratively improve the group delay estimate
1157 :
1158 0 : while ( uiNumIter < NUM_ITER_UNWRAP ) {
1159 :
1160 0 : dTimeRange = NEW_RANGE_FACTOR * dTimeDelta;
1161 0 : Double dTimeDeltaNew = dTimeRange / (uiNumTime+1);
1162 :
1163 0 : indgen<Double>( oTime, dGroupDelay-0.5*dTimeDelta, dTimeDeltaNew );
1164 :
1165 0 : oFringePacket = fringePacket2( oPhaseC, oFrequencyC, oTime );
1166 0 : Double dGroupDelayNew = maxLocation<Double>( oTime, oFringePacket );
1167 :
1168 0 : if ( fabs(dGroupDelayNew-dGroupDelay)/dTimeDelta < 1.0E-08 ) break;
1169 :
1170 0 : dTimeDelta = dTimeDeltaNew;
1171 0 : dGroupDelay = dGroupDelayNew;
1172 :
1173 0 : uiNumIter++;
1174 :
1175 : }
1176 :
1177 :
1178 : // If the number of iterations has been exceeded, print a warning and set
1179 : // the group delay to the middle of the time range
1180 :
1181 0 : if ( uiNumIter > NUM_ITER_UNWRAP ) {
1182 :
1183 0 : dGroupDelay = mean( oTime );
1184 :
1185 0 : LogIO log( LogOrigin( "CalStatsPhase", "unwrap", WHERE ) );
1186 : log << LogIO::WARN
1187 : << "Number of iterations exceeded for group delay calculation\n"
1188 : << "Using the mean time from the last iteration"
1189 0 : << LogIO::POST;
1190 :
1191 : }
1192 :
1193 :
1194 : // Calculate the differential phases, which are the input phases minus the
1195 : // group delay. Make sure to subtract the initial value from all values.
1196 :
1197 0 : uInt uiNumFrequency = oFrequency.nelements();
1198 :
1199 0 : Vector<Double> oDiffPhase( oPhase - 2.0*M_PI*oFrequency*dGroupDelay );
1200 0 : oDiffPhase -= oDiffPhase[0];
1201 :
1202 :
1203 : // If phase wraps are found, unwrap them. Flagged data are not unwrapped.
1204 :
1205 0 : for ( uInt f=1; f<uiNumFrequency; f++ ) {
1206 :
1207 0 : if ( oFlag[f-1] ) continue;
1208 :
1209 0 : uInt f2 = 0;
1210 0 : for ( f2=f; f2<uiNumFrequency; f2++ ) if ( !oFlag[f2] ) break;
1211 :
1212 0 : if ( f2 >= uiNumFrequency ) break;
1213 :
1214 0 : Double dDiffPhase = oDiffPhase[f2] - oDiffPhase[f-1];
1215 :
1216 0 : Int N = 0;
1217 0 : while ( dDiffPhase + 2.0*M_PI*N <= -M_PI ) N++;
1218 0 : while ( dDiffPhase + 2.0*M_PI*N > M_PI ) N--;
1219 :
1220 0 : if ( N == 0 ) continue;
1221 :
1222 0 : for ( uInt f3=f2; f3<uiNumFrequency; f3++ ) oPhase[f3] += 2.0 * M_PI * N;
1223 :
1224 : }
1225 :
1226 :
1227 : // Return
1228 :
1229 0 : return;
1230 :
1231 : }
1232 :
1233 : // -----------------------------------------------------------------------------
1234 : // End of CalStatsPhase public static member functions
1235 : // -----------------------------------------------------------------------------
1236 :
1237 : // -----------------------------------------------------------------------------
1238 : // Start of CalStatsPhase private static member functions
1239 : // -----------------------------------------------------------------------------
1240 :
1241 : /*
1242 :
1243 : Description:
1244 : ------------
1245 : This member function forms the squared-amplitude fringe packet.
1246 :
1247 : Inputs:
1248 : -------
1249 : oPhase - This Vector<Double>() instance contains the wrapped phases.
1250 : oFrequency - This Vector<Double>() instance contains the frequencies.
1251 : oTime - This Vector<Double>() instance contains the times.
1252 :
1253 : Outputs:
1254 : --------
1255 : The reference to the Vector<Double>() instance containing the squared-amplitude
1256 : fringe packet, returned via the function value.
1257 :
1258 : Modification history:
1259 : ---------------------
1260 : 2012 Mar 27 - Nick Elias, NRAO
1261 : Initial version.
1262 :
1263 : */
1264 :
1265 : // -----------------------------------------------------------------------------
1266 :
1267 0 : Vector<Double>& CalStatsPhase::fringePacket2( const Vector<Double>& oPhase,
1268 : const Vector<Double>& oFrequency, const Vector<Double>& oTime ) {
1269 :
1270 : // Initialize the pointer to the squared-amplitude fringe packet
1271 :
1272 0 : uInt uiNumTime = oTime.nelements();
1273 :
1274 : Vector<Double>* poFringePacket;
1275 0 : poFringePacket = new Vector<Double>( uiNumTime, 0.0 );
1276 :
1277 :
1278 : // Calculate the complex fringe packet for all times using all frequencies and
1279 : // phases
1280 :
1281 0 : uInt uiNumFrequency = oFrequency.nelements();
1282 :
1283 0 : Vector<DComplex> oFringePacketC( uiNumTime, DComplex( 0.0, 0.0 ) );
1284 :
1285 0 : for ( uInt f=0; f<uiNumFrequency; f++ ) {
1286 0 : Vector<DComplex> oFringePacketCF( uiNumTime, DComplex( 0.0, 0.0 ) );
1287 0 : setReal( oFringePacketCF, cos( 2.0*M_PI*oFrequency[f]*oTime - oPhase[f] ) );
1288 0 : setImag( oFringePacketCF, sin( 2.0*M_PI*oFrequency[f]*oTime - oPhase[f] ) );
1289 0 : operator+=( oFringePacketC, oFringePacketCF );
1290 : }
1291 :
1292 :
1293 : // Calculate and return the reference to the squared-amplitude fringe packet
1294 :
1295 0 : *poFringePacket = square( amplitude( oFringePacketC ) );
1296 0 : *poFringePacket /= (Double) uiNumFrequency * uiNumFrequency;
1297 :
1298 0 : return( *poFringePacket );
1299 :
1300 : }
1301 :
1302 : // -----------------------------------------------------------------------------
1303 : // End of CalStatsPhase private static member functions
1304 : // -----------------------------------------------------------------------------
1305 :
1306 : // -----------------------------------------------------------------------------
1307 : // End of CalStatsPhase class
1308 : // -----------------------------------------------------------------------------
1309 :
1310 : };
1311 :
1312 : // -----------------------------------------------------------------------------
1313 : // End of casa namespace
1314 : // -----------------------------------------------------------------------------
|