source: tags/release-1.6.1/src/param.cc @ 1441

Last change on this file since 1441 was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

File size: 74.8 KB
Line 
1// -----------------------------------------------------------------------
2// param.cc: Dealing with the set of parameters for Duchamp.
3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
28#include <iostream>
29#include <iomanip>
30#include <fstream>
31#include <sstream>
32#include <string>
33#include <algorithm>
34#include <stdlib.h>
35#include <ctype.h>
36#include <math.h>
37#include <unistd.h>
38#include <duchamp/param.hh>
39#include <duchamp/fitsHeader.hh>
40#include <duchamp/duchamp.hh>
41#include <duchamp/pgheader.hh>
42#include <duchamp/ATrous/filter.hh>
43#include <duchamp/ATrous/FilterFactory.hh>
44#include <duchamp/Utils/utils.hh>
45#include <duchamp/Utils/Section.hh>
46#include <duchamp/Utils/VOParam.hh>
47#include <duchamp/Outputs/columns.hh>
48
49namespace duchamp
50{
51  const std::string defaultSection = "[*,*,*]";
52
53  /****************************************************************/
54  ///////////////////////////////////////////////////
55  //// Accessor Functions for Parameter class:
56  ///////////////////////////////////////////////////
57  Param::~Param()
58  {
59    /// Deletes the offsets array if the sizeOffsets parameter is
60    /// positive.
61    if(this->sizeOffsets>0) delete [] this->offsets;
62  }
63
64  Param::Param()
65  {
66    this->defaultValues();
67  }
68
69  void Param::defaultValues()
70  {
71    /// Provides default intial values for the parameters. Note that
72    /// imageFile has no default value!
73
74    // Input files
75    this->imageFile         = "";
76    this->flagSubsection    = false;
77    this->pixelSec          = Section();
78    this->flagReconExists   = false;
79    this->reconFile         = "";
80    this->flagSmoothExists  = false;
81    this->smoothFile        = "";
82    this->usePrevious       = false;
83    this->objectList        = "";
84    // Output files
85    this->flagLog           = false;
86    this->logFile           = "duchamp-Logfile.txt";
87    this->outFile           = "duchamp-Results.txt";
88    this->flagSeparateHeader= false;
89    this->headerFile        = "duchamp-Results.hdr";
90    this->flagWriteBinaryCatalogue = true;
91    this->binaryCatalogue   = "duchamp-Catalogue.dpc";
92    this->flagPlotSpectra   = true;
93    this->spectraFile       = "duchamp-Spectra.ps";
94    this->flagPlotIndividualSpectra = false;
95    this->flagTextSpectra   = false;
96    this->spectraTextFile   = "duchamp-Spectra.txt";
97    this->flagOutputBaseline    = false;
98    this->fileOutputBaseline    = "";
99    this->flagOutputMomentMap    = false;
100    this->fileOutputMomentMap    = "";
101    this->flagOutputMomentMask    = false;
102    this->fileOutputMomentMask    = "";
103    this->flagOutputMask    = false;
104    this->fileOutputMask    = "";
105    this->flagMaskWithObjectNum = false;
106    this->flagOutputSmooth  = false;
107    this->fileOutputSmooth  = "";
108    this->flagOutputRecon   = false;
109    this->fileOutputRecon   = "";
110    this->flagOutputResid   = false;
111    this->fileOutputResid   = "";
112    this->flagVOT           = false;
113    this->votFile           = "duchamp-Results.xml";
114    this->flagKarma         = false;
115    this->karmaFile         = "duchamp-Results.ann";
116    this->flagDS9           = false;
117    this->ds9File           = "duchamp-Results.reg";
118    this->flagCasa          = false;
119    this->casaFile          = "duchamp-Results.crf";
120    this->annotationType    = "borders";
121    this->flagMaps          = true;
122    this->detectionMap      = "duchamp-DetectionMap.ps";
123    this->momentMap         = "duchamp-MomentMap.ps";
124    this->flagXOutput       = true;
125    this->precFlux          = Catalogues::prFLUX;
126    this->precVel           = Catalogues::prVEL;
127    this->precSNR           = Catalogues::prSNR;
128    // Cube related parameters
129    this->flagBlankPix      = false;
130    this->blankPixValue     = -8.00061;
131    this->blankKeyword      = 1;
132    this->bscaleKeyword     = -8.00061;
133    this->bzeroKeyword      = 0.;
134    this->newFluxUnits      = "";
135    // Flagged channel parameters
136    this->flaggedChannelList = "";
137    this->flaggedChannels   = std::vector<int>();
138    this->flaggedChannelMask= std::vector<bool>();
139    // Beam
140    this->areaBeam          = 0.;
141    this->fwhmBeam          = 0.;
142    this->beamAsUsed.empty();
143    this->searchType        = "spatial";
144    // Trim-related         
145    this->flagTrim          = false;
146    this->hasBeenTrimmed    = false;
147    this->borderLeft        = 0;
148    this->borderRight       = 0;
149    this->borderBottom      = 0;
150    this->borderTop         = 0;
151    // Subsection offsets
152    this->sizeOffsets       = 0;
153    this->xSubOffset        = 0;
154    this->ySubOffset        = 0;
155    this->zSubOffset        = 0;
156    // Baseline related
157    this->flagBaseline      = false;
158    this->baselineType      = "atrous";
159    this->baselineBoxWidth  = 51;
160    // Detection-related   
161    this->flagNegative      = false;
162    // Object growth       
163    this->flagGrowth        = false;
164    this->growthCut         = 3.;
165    this->flagUserGrowthThreshold = false;
166    this->growthThreshold   = 0.;
167    // FDR analysis         
168    this->flagFDR           = false;
169    this->alphaFDR          = 0.01;
170    this->FDRnumCorChan     = 2;
171    // Other detection     
172    this->flagStatSec       = false;
173    this->statSec           = Section();
174    this->flagRobustStats   = true;
175    this->snrCut            = 5.;
176    this->threshold         = 0.;
177    this->flagUserThreshold = false;
178    // Smoothing
179    this->flagSmooth        = false;
180    this->smoothType        = "spectral";
181    this->hanningWidth      = 5;
182    this->kernMaj           = 3.;
183    this->kernMin           = -1.;
184    this->kernPA            = 0.;
185    this->smoothEdgeMethod  = "equal";
186    this->spatialSmoothCutoff = 1.e-10;
187    // A trous reconstruction parameters
188    this->flagATrous        = false;
189    this->reconDim          = 1;
190    this->scaleMin          = 1;
191    this->scaleMax          = 0;
192    this->snrRecon          = 4.;
193    this->reconConvergence  = 0.005;
194    this->filterCode        = 1;
195//    this->reconFilter.define(this->filterCode);
196    this->reconFilter = 0;
197    // Volume-merging parameters
198    this->flagAdjacent      = true;
199    this->threshSpatial     = 3.;
200    this->threshVelocity    = 7.;
201    this->minChannels       = 3;
202    this->minPix            = 2;
203    this->minVoxels         = 4;
204    this->maxChannels       = -1;
205    this->maxPix            = -1;
206    this->maxVoxels         = -1;
207    this->flagRejectBeforeMerge = false;
208    this->flagTwoStageMerging = true;
209    // Input-Output related
210    this->spectralMethod    = "peak";
211    this->spectralType      = "";
212    this->restFrequency     = -1.;
213    this->restFrequencyUsed = false;
214    this->spectralUnits     = "";
215    this->pixelCentre       = "centroid";
216    this->sortingParam      = "vel";
217    this->borders           = true;
218    this->blankEdge         = true;
219    this->verbose           = true;
220    this->commentStr        = "";
221  }
222
223  Param::Param (const Param& p)
224  {
225    operator=(p);
226  }
227
228  Param& Param::operator= (const Param& p)
229  {
230    if(this == &p) return *this;
231    this->imageFile         = p.imageFile;
232    this->flagSubsection    = p.flagSubsection;
233    this->pixelSec          = p.pixelSec;
234    this->flagReconExists   = p.flagReconExists;
235    this->reconFile         = p.reconFile;     
236    this->flagSmoothExists  = p.flagSmoothExists;
237    this->smoothFile        = p.smoothFile;     
238    this->usePrevious       = p.usePrevious;
239    this->objectList        = p.objectList;
240    this->flagLog           = p.flagLog;       
241    this->logFile           = p.logFile;       
242    this->outFile           = p.outFile;       
243    this->flagSeparateHeader= p.flagSeparateHeader;
244    this->headerFile        = p.headerFile;
245    this->flagWriteBinaryCatalogue = p.flagWriteBinaryCatalogue;
246    this->binaryCatalogue   = p.binaryCatalogue;
247    this->flagPlotSpectra   = p.flagPlotSpectra;
248    this->spectraFile       = p.spectraFile;   
249    this->flagPlotIndividualSpectra = p.flagPlotIndividualSpectra;
250    this->flagTextSpectra   = p.flagTextSpectra;   
251    this->spectraTextFile   = p.spectraTextFile;   
252    this->flagOutputBaseline    = p.flagOutputBaseline;
253    this->fileOutputBaseline    = p.fileOutputBaseline;
254    this->flagOutputMomentMap    = p.flagOutputMomentMap;
255    this->fileOutputMomentMap    = p.fileOutputMomentMap;
256    this->flagOutputMomentMask   = p.flagOutputMomentMask;
257    this->fileOutputMomentMask   = p.fileOutputMomentMask;
258    this->flagOutputMask    = p.flagOutputMask;
259    this->fileOutputMask    = p.fileOutputMask;
260    this->flagMaskWithObjectNum = p.flagMaskWithObjectNum;
261    this->flagOutputSmooth  = p.flagOutputSmooth;
262    this->fileOutputSmooth  = p.fileOutputSmooth;
263    this->flagOutputRecon   = p.flagOutputRecon;
264    this->fileOutputRecon   = p.fileOutputRecon;
265    this->flagOutputResid   = p.flagOutputResid;
266    this->fileOutputResid   = p.fileOutputResid;
267    this->flagVOT           = p.flagVOT;         
268    this->votFile           = p.votFile;       
269    this->flagKarma         = p.flagKarma;     
270    this->karmaFile         = p.karmaFile;     
271    this->flagDS9           = p.flagDS9;     
272    this->ds9File           = p.ds9File;     
273    this->flagCasa          = p.flagCasa;     
274    this->casaFile          = p.casaFile;     
275    this->annotationType    = p.annotationType;
276    this->flagMaps          = p.flagMaps;       
277    this->detectionMap      = p.detectionMap;   
278    this->momentMap         = p.momentMap;     
279    this->flagXOutput       = p.flagXOutput;       
280    this->precFlux          = p.precFlux;
281    this->precVel           = p.precVel;
282    this->precSNR           = p.precSNR;
283    this->flagNegative      = p.flagNegative;
284    this->flagBlankPix      = p.flagBlankPix;   
285    this->blankPixValue     = p.blankPixValue; 
286    this->blankKeyword      = p.blankKeyword;   
287    this->bscaleKeyword     = p.bscaleKeyword; 
288    this->bzeroKeyword      = p.bzeroKeyword;   
289    this->newFluxUnits      = p.newFluxUnits;
290    this->flaggedChannelList = p.flaggedChannelList;
291    this->flaggedChannels   = p.flaggedChannels;
292    this->flaggedChannelMask= p.flaggedChannelMask;
293    this->areaBeam          = p.areaBeam;     
294    this->fwhmBeam          = p.fwhmBeam;     
295    this->beamAsUsed        = p.beamAsUsed;
296    this->searchType        = p.searchType;
297    this->flagTrim          = p.flagTrim;   
298    this->hasBeenTrimmed    = p.hasBeenTrimmed;   
299    this->borderLeft        = p.borderLeft;     
300    this->borderRight       = p.borderRight;   
301    this->borderBottom      = p.borderBottom;   
302    this->borderTop         = p.borderTop;     
303    if(this->sizeOffsets>0) delete [] this->offsets;
304    this->sizeOffsets       = p.sizeOffsets;
305    if(this->sizeOffsets>0){
306      this->offsets           = new long[this->sizeOffsets];
307      for(int i=0;i<this->sizeOffsets;i++) this->offsets[i] = p.offsets[i];
308    }
309    this->xSubOffset        = p.xSubOffset;     
310    this->ySubOffset        = p.ySubOffset;     
311    this->zSubOffset        = p.zSubOffset;
312    this->flagBaseline      = p.flagBaseline;
313    this->baselineType      = p.baselineType;
314    this->baselineBoxWidth  = p.baselineBoxWidth;
315    this->flagGrowth        = p.flagGrowth;
316    this->growthCut         = p.growthCut;
317    this->growthThreshold   = p.growthThreshold;
318    this->flagUserGrowthThreshold = p.flagUserGrowthThreshold;
319    this->flagFDR           = p.flagFDR;
320    this->alphaFDR          = p.alphaFDR;
321    this->FDRnumCorChan     = p.FDRnumCorChan;
322    this->flagStatSec       = p.flagStatSec;
323    this->statSec           = p.statSec;
324    this->flagRobustStats   = p.flagRobustStats;
325    this->snrCut            = p.snrCut;
326    this->threshold         = p.threshold;
327    this->flagUserThreshold = p.flagUserThreshold;
328    this->flagSmooth        = p.flagSmooth;
329    this->smoothType        = p.smoothType;
330    this->hanningWidth      = p.hanningWidth;
331    this->kernMaj           = p.kernMaj;
332    this->kernMin           = p.kernMin;
333    this->kernPA            = p.kernPA;
334    this->smoothEdgeMethod  = p.smoothEdgeMethod;
335    this->spatialSmoothCutoff = p.spatialSmoothCutoff;
336    this->flagATrous        = p.flagATrous;
337    this->reconDim          = p.reconDim;
338    this->scaleMin          = p.scaleMin;
339    this->scaleMax          = p.scaleMax;
340    this->snrRecon          = p.snrRecon;
341    this->reconConvergence  = p.reconConvergence;
342    this->filterCode        = p.filterCode;
343    this->reconFilter       = p.reconFilter;
344    this->flagAdjacent      = p.flagAdjacent;
345    this->threshSpatial     = p.threshSpatial;
346    this->threshVelocity    = p.threshVelocity;
347    this->minChannels       = p.minChannels;
348    this->minPix            = p.minPix;
349    this->minVoxels         = p.minVoxels;
350    this->maxChannels       = p.maxChannels;
351    this->maxPix            = p.maxPix;
352    this->maxVoxels         = p.maxVoxels;
353    this->flagRejectBeforeMerge = p.flagRejectBeforeMerge;
354    this->flagTwoStageMerging = p.flagTwoStageMerging;
355    this->spectralMethod    = p.spectralMethod;
356    this->spectralType      = p.spectralType;
357    this->restFrequency     = p.restFrequency;
358    this->restFrequencyUsed = p.restFrequencyUsed;
359    this->spectralUnits     = p.spectralUnits;
360    this->pixelCentre       = p.pixelCentre;
361    this->sortingParam      = p.sortingParam;
362    this->borders           = p.borders;
363    this->blankEdge         = p.blankEdge;
364    this->verbose           = p.verbose;
365    this->commentStr        = p.commentStr;
366    return *this;
367  }
368  //--------------------------------------------------------------------
369
370  OUTCOME Param::getopts(int argc, char ** argv, std::string progname)
371  {
372    ///   A function that reads in the command-line options, in a manner
373    ///    tailored for use with the main Duchamp program.
374    ///
375    ///   \param argc The number of command line arguments.
376    ///   \param argv The array of command line arguments.
377
378    OUTCOME returnValue = FAILURE;
379    if(argc==1){
380      std::cout << ERR_USAGE_MSG;
381      returnValue = FAILURE;
382    }
383    else {
384      std::string file;
385      float thresh;
386      bool changeX = false, changeThresh=false;
387      this->defaultValues();
388      char c;
389      while( ( c = getopt(argc,argv,"p:f:t:hvx") )!=-1){
390        switch(c) {
391        case 'p':
392          file = optarg;
393          if(this->readParams(file)==FAILURE){
394            DUCHAMPERROR(progname,"Could not open parameter file " << file);
395          }
396          else returnValue = SUCCESS;
397          break;
398        case 'f':
399          file = optarg;
400          this->imageFile = file;
401          returnValue = SUCCESS;
402          break;
403        case 'v':
404          std::cout << PROGNAME << " version " << VERSION << std::endl;
405          break;
406        case 'x':
407          changeX = true;
408          break;
409        case 't':
410          thresh = atof(optarg);
411          changeThresh = true;
412          break;
413        case 'h':
414        default :
415          std::cout << ERR_USAGE_MSG;
416          break;
417        }
418      }
419      if(changeX){
420        if(returnValue == SUCCESS) this->setFlagXOutput(false);
421        else {
422          DUCHAMPERROR(progname, "You need to specify either a parameter file or FITS image.\n");
423          std::cout << "\n" << ERR_USAGE_MSG;
424        }
425      }
426      if(changeThresh){
427        this->threshold = thresh;
428        this->flagUserThreshold = true;
429        this->checkPars();
430      }
431    }
432    return returnValue;
433  }
434  //--------------------------------------------------------------------
435
436  bool Param::isBlank(float &value)
437  {
438    ///  Tests whether the value passed as the argument is BLANK or not.
439    ///  \param value Pixel value to be tested.
440    ///  \return False if flagBlankPix is false. Else, compare to the
441    ///  relevant FITS keywords, using integer comparison.
442
443    return this->flagBlankPix &&
444      (this->blankKeyword == int((value-this->bzeroKeyword)/this->bscaleKeyword));
445  }
446
447    std::vector<bool> Param::makeBlankMask(float *array, size_t size)
448  {
449    ///  This returns an array of bools, saying whether each pixel in the
450    ///  given array is BLANK or not. If the pixel is BLANK, set mask to
451    ///  false, else set to true. The array is allocated by the function.
452
453      std::vector<bool> mask(size);
454      for(size_t i=0;i<size;i++) mask[i] = !this->isBlank(array[i]);
455      return mask;
456  }
457
458
459    std::vector<bool> Param::makeStatMask(float *array, size_t *dim)
460  {
461    ///  This returns an array of bools, saying whether each pixel in
462    ///  the given array is suitable for a stats calculation. It needs
463    ///  to be in the StatSec (if defined), not blank and not a flagged
464    ///  channel. The array is allocated by the function with a 'new' call.
465
466      std::vector<bool> mask(dim[0]*dim[1]*dim[2]);
467    std::vector<bool> flaggedChans = this->getChannelFlags(dim[2]);
468    for(size_t x=0;x<dim[0];x++) {
469      for(size_t y=0;y<dim[1];y++) {
470        for(size_t z=0;z<dim[2];z++) {
471          size_t i = x+y*dim[0]+z*dim[0]*dim[1];
472          mask[i] = !this->isBlank(array[i]) && !flaggedChans[z] && this->isStatOK(x,y,z);
473        }
474      }
475    }
476    return mask;
477  }
478
479    bool Param::isFlaggedChannel(int z)
480    {
481        /// Tests whether a given channel has been flagged by the user
482
483        // bool isFlagged=false;
484        // for(size_t i=0;i<this->flaggedChannels.size()&&!isFlagged;i++)
485        //     isFlagged=(z==this->flaggedChannels[i]);
486        // return isFlagged;
487
488        if(this->flaggedChannelMask.size()==0) return false;
489        else if(z>int(this->flaggedChannelMask.size()) || z<0) return false;
490        else return this->flaggedChannelMask[z];
491
492    }
493
494    std::vector<bool> Param::getChannelFlags(int numChannels)
495    {
496
497        std::vector<bool> flags(numChannels,false);
498        for(std::vector<int>::iterator chan = this->flaggedChannels.begin(); chan!=this->flaggedChannels.end(); chan++){
499            // channels are zero-based, but channel-specification is 1-based
500            if(*chan<=numChannels && *chan>-1) flags[*chan-1] = true;
501        }
502        return flags;
503    }
504
505
506  bool Param::isStatOK(int x, int y, int z)
507  {
508    /// Test whether a given pixel position lies within the subsection
509    /// given by the statSec parameter. Only tested if the flagSubsection
510    /// parameter is true -- if it isn't, we just return true since all
511    /// pixels are therefore available for statstical calculations.
512    /// \param x X-value of pixel being tested.
513    /// \param y Y-value of pixel being tested.
514    /// \param z Z-value of pixel being tested.
515    /// \return True if pixel is able to be used for statistical
516    /// calculations. False otherwise.
517
518    int xval=x,yval=y,zval=z;
519    if(flagSubsection){
520      xval += pixelSec.getStart(0);
521      yval += pixelSec.getStart(1);
522      zval += pixelSec.getStart(2);
523    }
524    return !flagStatSec || statSec.isInside(xval,yval,zval);
525  }
526
527  std::vector<bool> Param::getObjectChoices()
528  {
529    ///  Returns a list of bool values, indicating whether a given
530    ///  object was requested or not. The size of the vector is
531    ///  determined by the maximum value in objectList. For instance,
532    ///  if objectList="2,3,5-8", then the returned vector will be
533    ///  [0,1,1,0,1,1,1,1].
534    ///  \return Vector of bool values.
535
536      if(this->objectListVector.size()==0) return std::vector<bool>(0);
537      else {
538          int maxNum = *std::max_element(this->objectListVector.begin(), this->objectListVector.end());
539          std::vector<bool> choices(maxNum,false);
540          for(std::vector<int>::iterator obj = objectListVector.begin();obj!=objectListVector.end();obj++)
541              choices[*obj-1] = true;
542          return choices;
543      }
544  }
545
546  std::vector<bool> Param::getObjectChoices(int numObjects)
547  {
548    ///  Returns a list of bool values, indicating whether a given
549    ///  object was requested or not. The size of the vector is given
550    ///  by the numObjects parameter. So, if objectList="2,3,5-8", then
551    ///  the returned vector from a getObjectChoices(10) call will be
552    ///  [0,1,1,0,1,1,1,1,0,0].
553    ///  \param numObjects How many objects there are in total.
554    ///  \return Vector of bool values.
555
556    if(this->objectList==""){
557      std::vector<bool> choices(numObjects,true);
558      return choices;
559    }
560    else{
561      std::vector<bool> choices(numObjects,false);
562      std::vector<int> duds,goodlist;
563      for(std::vector<int>::iterator obj = this->objectListVector.begin();obj!=this->objectListVector.end();obj++){
564          if(*obj<=numObjects) {
565              choices[*obj-1] = true;
566              goodlist.push_back(*obj);
567          }
568          else duds.push_back(*obj);
569      }
570      if(duds.size()>0){
571          this->objectListVector = goodlist;
572          std::stringstream dudlist;
573          dudlist << duds[0];
574          for(size_t i=1;i<duds.size();i++) dudlist << ","<<duds[i];
575          std::string obj="object";
576          if(duds.size()>1) obj+= "s";
577          DUCHAMPWARN("Object Selection", "You have only detected " << numObjects << " objects, so the requested "
578                      << obj << " '" << dudlist.str() << "' cannot be returned. Please check your request, as it doesn't match the results.");
579      }
580      return choices;
581    }
582
583  }
584
585  /****************************************************************/
586  /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
587  /// / Other Functions using the  Parameter class:
588  /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
589
590  OUTCOME Param::readParams(std::string paramfile)
591  {
592    /// The parameters are read in from a disk file, on the assumption that each
593    ///  line of the file has the format "parameter value" (eg. alphafdr 0.1)
594    ///
595    /// The case of the parameter name does not matter, nor does the
596    /// formatting of the spaces (it can be any amount of whitespace or
597    /// tabs).
598    ///
599    /// \param paramfile A std::string containing the parameter filename.
600    ///
601    /// \return FAILURE if the parameter file does not exist. SUCCESS if
602    /// it is able to read it.
603
604    if(!USE_PGPLOT){
605      // Change default values for these parameters when we don't use PGPlot
606      this->flagXOutput = false;
607      this->flagMaps = false;
608      this->flagPlotSpectra = false;
609    }
610
611    std::ifstream fin(paramfile.c_str());
612    if(!fin.is_open()) return FAILURE;
613    std::string line;
614    while( !std::getline(fin,line,'\n').eof()){
615
616      if(line[0]!='#'){
617        std::stringstream ss;
618        ss.str(line);
619        std::string arg;
620        ss >> arg;
621        arg = makelower(arg);
622        if(arg=="imagefile")       this->imageFile = readFilename(ss);
623        if(arg=="flagsubsection")  this->flagSubsection = readFlag(ss);
624        if(arg=="subsection")      this->pixelSec.setSection(readSval(ss));
625        if(arg=="flagreconexists") this->flagReconExists = readFlag(ss);
626        if(arg=="reconfile")       this->reconFile = readSval(ss);
627        if(arg=="flagsmoothexists")this->flagSmoothExists = readFlag(ss);
628        if(arg=="smoothfile")      this->smoothFile = readSval(ss);
629        if(arg=="beamarea")        this->areaBeam = readFval(ss);
630        if(arg=="beamfwhm")        this->fwhmBeam = readFval(ss);
631        if(arg=="useprevious")     this->usePrevious = readFlag(ss);
632        if(arg=="objectlist")      this->objectList = readSval(ss);
633
634        if(arg=="flaglog")         this->flagLog = readFlag(ss);
635        if(arg=="logfile")         this->logFile = readSval(ss);
636        if(arg=="outfile")         this->outFile = readSval(ss);
637        if(arg=="flagseparateheader") this->flagSeparateHeader = readFlag(ss);
638        if(arg=="headerfile")      this->headerFile = readFilename(ss);
639        if(arg=="flagwritebinarycatalogue") this->flagWriteBinaryCatalogue = readFlag(ss);
640        if(arg=="binarycatalogue") this->binaryCatalogue = readFilename(ss);
641        if(arg=="flagplotspectra") this->flagPlotSpectra = readFlag(ss);
642        if(arg=="spectrafile")     this->spectraFile = readFilename(ss);
643        if(arg=="flagplotindividualspectra") this->flagPlotIndividualSpectra = readFlag(ss);
644        if(arg=="flagtextspectra") this->flagTextSpectra = readFlag(ss);
645        if(arg=="spectratextfile") this->spectraTextFile = readFilename(ss);
646        if(arg=="flagoutputbaseline")  this->flagOutputBaseline = readFlag(ss);
647        if(arg=="fileoutputbaseline")  this->fileOutputBaseline = readFilename(ss);
648        if(arg=="flagoutputmomentmap")  this->flagOutputMomentMap = readFlag(ss);
649        if(arg=="fileoutputmomentmap")  this->fileOutputMomentMap = readFilename(ss);
650        if(arg=="flagoutputmomentmask")  this->flagOutputMomentMask = readFlag(ss);
651        if(arg=="fileoutputmomentmask")  this->fileOutputMomentMask = readFilename(ss);
652        if(arg=="flagoutputmask")  this->flagOutputMask = readFlag(ss);
653        if(arg=="fileoutputmask")  this->fileOutputMask = readFilename(ss);
654        if(arg=="flagmaskwithobjectnum") this->flagMaskWithObjectNum = readFlag(ss);
655        if(arg=="flagoutputsmooth")this->flagOutputSmooth = readFlag(ss);
656        if(arg=="fileoutputsmooth")this->fileOutputSmooth = readFilename(ss);
657        if(arg=="flagoutputrecon") this->flagOutputRecon = readFlag(ss);
658        if(arg=="fileoutputrecon") this->fileOutputRecon = readFilename(ss);
659        if(arg=="flagoutputresid") this->flagOutputResid = readFlag(ss);
660        if(arg=="fileoutputresid") this->fileOutputResid = readFilename(ss);
661        if(arg=="flagvot")         this->flagVOT = readFlag(ss);
662        if(arg=="votfile")         this->votFile = readFilename(ss);
663        if(arg=="flagkarma")       this->flagKarma = readFlag(ss);
664        if(arg=="karmafile")       this->karmaFile = readFilename(ss);
665        if(arg=="flagds9")         this->flagDS9 = readFlag(ss);
666        if(arg=="ds9file")         this->ds9File = readFilename(ss);
667        if(arg=="flagcasa")        this->flagCasa = readFlag(ss);
668        if(arg=="casafile")        this->casaFile = readFilename(ss);
669        if(arg=="annotationtype")  this->annotationType = readSval(ss);
670        if(arg=="flagmaps")        this->flagMaps = readFlag(ss);
671        if(arg=="detectionmap")    this->detectionMap = readFilename(ss);
672        if(arg=="momentmap")       this->momentMap = readFilename(ss);
673        if(arg=="flagxoutput")     this->flagXOutput = readFlag(ss);
674        if(arg=="newfluxunits")    this->newFluxUnits = readSval(ss);
675        if(arg=="precflux")        this->precFlux = readIval(ss);
676        if(arg=="precvel")         this->precVel = readIval(ss);
677        if(arg=="precsnr")         this->precSNR = readIval(ss);
678
679        if(arg=="flagtrim")        this->flagTrim = readFlag(ss);
680        if(arg=="flaggedchannels") this->flaggedChannelList = readSval(ss);
681        if(arg=="flagbaseline")    this->flagBaseline = readFlag(ss);
682        if(arg=="baselinetype")    this->baselineType = readSval(ss);
683        if(arg=="baselineboxwidth") this->baselineBoxWidth = readIval(ss);
684        if(arg=="searchtype")      this->searchType = readSval(ss);
685
686        if(arg=="flagnegative")    this->flagNegative = readFlag(ss);
687        if(arg=="flaggrowth")      this->flagGrowth = readFlag(ss);
688        if(arg=="growthcut")       this->growthCut = readFval(ss);
689        if(arg=="growththreshold"){
690          this->growthThreshold = readFval(ss);
691          this->flagUserGrowthThreshold = true;
692        }
693
694        if(arg=="flagfdr")         this->flagFDR = readFlag(ss);
695        if(arg=="alphafdr")        this->alphaFDR = readFval(ss);
696        if(arg=="fdrnumcorchan")   this->FDRnumCorChan = readIval(ss);
697        if(arg=="flagstatsec")     this->flagStatSec = readFlag(ss);
698        if(arg=="statsec")         this->statSec.setSection(readSval(ss));
699        if(arg=="flagrobuststats") this->flagRobustStats = readFlag(ss);
700        if(arg=="snrcut")          this->snrCut = readFval(ss);
701        if(arg=="threshold"){
702          this->threshold = readFval(ss);
703          this->flagUserThreshold = true;
704        }
705     
706        if(arg=="flagsmooth")      this->flagSmooth = readFlag(ss);
707        if(arg=="smoothtype")      this->smoothType = readSval(ss);
708        if(arg=="hanningwidth")    this->hanningWidth = readIval(ss);
709        if(arg=="kernmaj")         this->kernMaj = readFval(ss);
710        if(arg=="kernmin")         this->kernMin = readFval(ss);
711        if(arg=="kernpa")          this->kernPA = readFval(ss);
712        if(arg=="smoothedgemethod") this->smoothEdgeMethod = readSval(ss);
713        if(arg=="spatialsmoothcutoff") this->spatialSmoothCutoff = readFval(ss);
714
715        if(arg=="flagatrous")      this->flagATrous = readFlag(ss);
716        if(arg=="recondim")        this->reconDim = readIval(ss);
717        if(arg=="scalemin")        this->scaleMin = readIval(ss);
718        if(arg=="scalemax")        this->scaleMax = readIval(ss);
719        if(arg=="snrrecon")        this->snrRecon = readFval(ss);
720        if(arg=="reconconvergence") this->reconConvergence = readFval(ss);
721        if(arg=="filtercode")      this->filterCode = readIval(ss);
722
723        if(arg=="flagadjacent")    this->flagAdjacent = readFlag(ss);
724        if(arg=="threshspatial")   this->threshSpatial = readFval(ss);
725        if(arg=="threshvelocity")  this->threshVelocity = readFval(ss);
726        if(arg=="minpix")          this->minPix = readIval(ss);
727        if(arg=="minchannels")     this->minChannels = readIval(ss);
728        if(arg=="minvoxels")       this->minVoxels = readIval(ss);
729        if(arg=="maxpix")          this->maxPix = readIval(ss);
730        if(arg=="maxchannels")     this->maxChannels = readIval(ss);
731        if(arg=="maxvoxels")       this->maxVoxels = readIval(ss);
732        if(arg=="flagrejectbeforemerge") this->flagRejectBeforeMerge = readFlag(ss);
733        if(arg=="flagtwostagemerging") this->flagTwoStageMerging = readFlag(ss);
734
735        if(arg=="spectralmethod")  this->spectralMethod=makelower(readSval(ss));
736        if(arg=="spectraltype")    this->spectralType = readSval(ss);
737        if(arg=="restfrequency")   this->restFrequency = readFval(ss);
738        if(arg=="spectralunits")   this->spectralUnits = readSval(ss);
739        if(arg=="pixelcentre")     this->pixelCentre = makelower(readSval(ss));
740        if(arg=="sortingparam")    this->sortingParam = makelower(readSval(ss));
741        if(arg=="drawborders")     this->borders = readFlag(ss);
742        if(arg=="drawblankedges")  this->blankEdge = readFlag(ss);
743        if(arg=="verbose")         this->verbose = readFlag(ss);
744
745        // Dealing with deprecated parameters.
746        if(arg=="flagblankpix"){
747          this->flagTrim = readFlag(ss);
748          DUCHAMPWARN("Reading parameters","The parameter flagBlankPix is deprecated. Please use the flagTrim parameter in future.");
749          DUCHAMPWARN("Reading parameters","   Setting flagTrim = " << stringize(this->flagTrim));
750        }
751        if(arg=="blankpixvalue"){
752          DUCHAMPWARN("Reading parameters","The parameter blankPixValue is deprecated. This value is only taken from the FITS header.");
753        }
754        if(arg=="beamsize"){
755          this->areaBeam = readFval(ss);
756          DUCHAMPWARN("Reading parameters","The parameter beamSize is deprecated. You can specify the beam size by beamArea or beamFWHM.");
757          DUCHAMPWARN("Reading parameters","   Setting beamArea = " << this->areaBeam);
758        }
759        if(arg=="flagmw"){
760            DUCHAMPWARN("Reading parameters", "The parameters flagMW, minMW and maxMW have been deprecated.");
761            DUCHAMPWARN("Reading parameters", "   Instead, use the parameter flaggedChannels to indicate channels & channel ranges to be excluded from detection.");
762        }
763      }
764    }
765
766    this->checkPars();
767
768    return SUCCESS;
769
770  }
771 
772  void Param::checkPars()
773  {
774
775    // If flagSubsection is false, but the parset had a subsection string in it, we want to set this back to the default.
776    if(!this->flagSubsection){
777      this->pixelSec.setSection(defaultSection);
778    }
779    if(!this->flagStatSec){
780      this->statSec.setSection(defaultSection);
781    }
782
783    // If we have usePrevious=false, set the objectlist to blank so that we use all of them. Otherwise, define the vector list of choices.
784    if(!this->usePrevious) this->objectList = "";
785    else this->objectListVector = selectionToIntVec(this->objectList);
786
787    // Defining the vector list of flagged channels
788    if(this->flaggedChannelList.size()>0){
789        this->flaggedChannels = selectionToIntVec(this->flaggedChannelList);
790        this->flaggedChannelMask = std::vector<bool>(*std::max_element(this->flaggedChannels.begin(),this->flaggedChannels.end()),false);
791        for(size_t i=0;i<this->flaggedChannels.size();i++) this->flaggedChannelMask[ this->flaggedChannels[i] ] = true;
792    }
793
794    // If pgplot was not included in the compilation, need to set flagXOutput to false
795    if(!USE_PGPLOT){
796      if(this->flagXOutput || this->flagMaps || this->flagPlotSpectra || this->flagPlotIndividualSpectra)
797        DUCHAMPWARN("Reading parameters","PGPlot has not been enabled, so setting flagXOutput, flagMaps, flagPlotSpectra and flagPlotIndividualSpectra to false.");
798      this->flagXOutput = false;
799      this->flagMaps = false;
800      this->flagPlotSpectra = false;
801      this->flagPlotIndividualSpectra = false;
802    }
803
804    if(!this->flagPlotSpectra && this->flagPlotIndividualSpectra){
805      DUCHAMPWARN("Reading parameters","flagPlotSpectra is false, so setting flagPlotIndividualSpectra to false as well.");
806      this->flagPlotIndividualSpectra = false;
807    }
808
809    // Correcting bad precision values -- if negative, set to 0
810    if(this->precFlux<0) this->precFlux = 0;
811    if(this->precVel<0)  this->precVel = 0;
812    if(this->precSNR<0)  this->precSNR = 0;
813
814    // Can only have "spatial" or "spectral" as search types
815    if(this->searchType != "spatial" && this->searchType != "spectral"){
816      DUCHAMPWARN("Reading parameters","You have requested a search type of \""<<this->searchType<<"\" -- Only \"spectral\" and \"spatial\" are accepted, so setting to \"spatial\".");
817      this->searchType = "spatial";
818    }
819
820    // The wavelet reconstruction takes precendence over the smoothing.
821    if(this->flagATrous) this->flagSmooth = false;
822
823    // Check validity of recon parameters
824    if(this->flagATrous){
825      if(this->reconConvergence < 0.){
826        DUCHAMPWARN("Reading Parameters","Your reconConvergence value is negative ("<<this->reconConvergence<<") - setting to " << -this->reconConvergence <<".");
827        this->reconConvergence *= -1.;
828      }
829
830//      this->reconFilter.define(this->filterCode);
831      FilterFactory filtFac;
832      this->reconFilter = filtFac.getFilter(this->filterCode);
833
834      if((this->scaleMax) > 0 && (this->scaleMax < this->scaleMin)){
835        DUCHAMPWARN("Reading Parameters","Reconstruction scaleMax ("<<this->scaleMax<<") is less than scaleMin ("<<this->scaleMin<<"): setting both to "<<this->scaleMin);
836        this->scaleMax = this->scaleMin;
837      }
838
839      if( (this->reconDim < 1) || (this->reconDim > 3) ){
840        DUCHAMPWARN("Reading Parameters", "You requested a " << this->reconDim << " dimensional reconstruction. Setting reconDim to 1");
841        this->reconDim = 1;
842      }
843
844      if( this->snrRecon < 0.){
845        DUCHAMPWARN("Reading Parameters", "Your snrRecon value is negative (" << this->snrRecon<<"). Turning reconstruction off -- fix your parameter file!");
846        this->flagATrous = false;
847      }
848
849    }
850
851    // Check validity of smoothing parameters
852    if(this->flagSmooth){
853       
854        // Make sure smoothType is an acceptable type -- default is "spectral"
855        if((this->smoothType!="spectral")&&
856           (this->smoothType!="spatial")){
857            DUCHAMPWARN("Reading parameters","The requested value of the parameter smoothType, \"" << this->smoothType << "\", is invalid -- changing to \"spectral\".");
858            this->smoothType = "spectral";
859        }
860
861        // If kernMin has not been given, or is negative, make it equal to kernMaj
862        if(this->kernMin < 0) this->kernMin = this->kernMaj;
863       
864        // Check the smoothEdgeMethod and spatialSmoothCutoff parameters.
865        if(this->smoothType=="spatial"){
866            if((this->smoothEdgeMethod != "equal") && (this->smoothEdgeMethod!="truncate") && (this->smoothEdgeMethod!="scale")){
867                DUCHAMPWARN("Reading parameters","The requested value of the parameter smoothEdgeMethod, \""<< this->smoothEdgeMethod << "\", is invalid - changing to \"equal\".");
868                this->smoothEdgeMethod = "equal";
869            }
870            if(this->spatialSmoothCutoff<0.){
871                this->spatialSmoothCutoff *= -1.;
872                DUCHAMPWARN("Reading parameters","The value of spatialSmoothCutoff is negative. Changing to "<<this->spatialSmoothCutoff);
873            }
874        }
875
876    }
877
878    if(this->flagUserThreshold){
879
880      // If we specify a manual threshold, need to also specify a manual growth threshold
881      // If we haven't done so, turn growing off
882      if(this->flagGrowth && !this->flagUserGrowthThreshold){
883        DUCHAMPWARN("Reading parameters","You have specified a manual search threshold, but not a manual growth threshold. You need to do so using the \"growthThreshold\" parameter.");
884        DUCHAMPWARN("Reading parameters","The growth function is being turned off.");
885        this->flagGrowth = false;
886      }
887
888      // If we specify a manual threshold, we don't need the FDR method, so turn it off if requested.
889      if(this->flagFDR){
890        DUCHAMPWARN("Reading parameters","You have specified a manual search threshold, so we don't need to use the FDR method. Setting \"flagFDR=false\".");
891        this->flagFDR = false;
892      }
893
894    }   
895
896    // Make sure the growth level is less than the detection level. Else turn off growing.
897    if(this->flagGrowth){
898      std::stringstream errmsg;
899      bool doWarn = false;
900      if(this->flagUserThreshold &&
901         ( (this->threshold < this->growthThreshold)
902           || (this->snrCut < this->growthCut) ) ){
903        errmsg << "Your \"growthThreshold\" parameter" << this->growthThreshold <<" is larger than your \"threshold\"" << this->threshold;
904        doWarn = true;
905      }
906     
907      if(!this->flagUserThreshold &&
908         (this->snrCut < this->growthCut)) {
909        errmsg << "Your \"growthCut\" parameter " << this->growthCut << " is larger than your \"snrCut\"" << this->snrCut;
910        doWarn = true;
911      }
912
913      if(doWarn){
914        DUCHAMPWARN("Reading parameters",errmsg);
915        DUCHAMPWARN("Reading parameters","The growth function is being turned off.");
916
917      }
918    }
919
920    // Make sure the annnotationType is an acceptable option -- default is "borders"
921    if((this->annotationType != "borders") && (this->annotationType!="circles") && (this->annotationType!="ellipses")){
922      DUCHAMPWARN("Reading parameters","The requested value of the parameter annotationType, \"" << this->annotationType << "\", is invalid -- changing to \"borders\".");
923      this->annotationType = "borders";
924    }
925     
926
927    // Make sure spectralMethod is an acceptable type -- default is "peak"
928    if((this->spectralMethod!="peak")&&
929       (this->spectralMethod!="sum")){
930      DUCHAMPWARN("Reading parameters","The requested value of the parameter spectralMethod, \"" << this->spectralMethod << "\", is invalid -- changing to \"peak\".");
931      this->spectralMethod = "peak";
932    }
933
934    // make sure pixelCentre is an acceptable type -- default is "peak"
935    if((this->pixelCentre!="centroid")&&
936       (this->pixelCentre!="average") &&
937       (this->pixelCentre!="peak")       ){
938      DUCHAMPWARN("Reading parameters","The requested value of the parameter pixelCentre, \"" << this->pixelCentre << "\", is invalid -- changing to \"centroid\".");
939      this->pixelCentre = "centroid";
940    }
941
942    // Make sure sortingParam is an acceptable type -- default is "vel"
943    bool OK = false;
944    int loc=(this->sortingParam[0]=='-') ? 1 : 0;
945    for(int i=0;i<numSortingParamOptions;i++)
946      OK = OK || this->sortingParam.substr(loc)==sortingParamOptions[i];
947    if(!OK){
948      DUCHAMPWARN("Reading parameters","The requested value of the parameter sortingParam, \"" << this->sortingParam << "\", is invalid. -- changing to \"vel\".");
949      this->sortingParam = "vel";
950    }
951
952    // Make sure minVoxels is appropriate given minChannels & minPixels
953    if(this->minVoxels < (this->minPix + this->minChannels - 1) ){
954      DUCHAMPWARN("Reading parameters","Changing minVoxels to " << this->minPix + this->minChannels - 1 << " given minPix="<<this->minPix << " and minChannels="<<this->minChannels);
955      this->minVoxels = this->minPix + this->minChannels - 1;
956    }
957   
958    // check that baselines are being calculated if we want to save them to a FITS file
959    if(this->flagOutputBaseline && !this->flagBaseline){
960      DUCHAMPWARN("Reading parameters","Saving of baseline values to a FITS file has been requested, but baselines are not being calculated. Turning off saving of baseline values.");
961      this->flagOutputBaseline = false;
962    }
963
964    // check that the baseline option is valid
965    if(this->flagBaseline){
966        if (this->baselineType != "atrous" && this->baselineType != "median"){
967            DUCHAMPWARN("Reading parameters", "The only types of baseline subtraction available are 'atrous' or 'median' - you provided '"<<this->baselineType <<"'. Setting to 'atrous'.");
968            this->baselineType = "atrous";
969        }
970        if(this->baselineType == "median" && this->baselineBoxWidth%2 == 0){
971            DUCHAMPWARN("Reading parameters", "The baseline box width needs to be odd. Changing from " << this->baselineBoxWidth << " to " << this->baselineBoxWidth+1 <<".");
972            this->baselineBoxWidth++;
973        }
974    }
975     
976  }
977
978  OUTCOME Param::checkImageExists()
979  {
980    /// A simple check to see whether the image actually exists or not, using the cfitsio interface.
981    /// If it does, we return SUCCESS, otherwise we throw an exception.
982
983    int exists,status = 0;  /* MUST initialize status */
984    fits_file_exists(this->imageFile.c_str(),&exists,&status);
985    if(exists<=0){
986      fits_report_error(stderr, status);
987      DUCHAMPTHROW("Cube Reader","Requested image " << this->imageFile << " does not exist!");
988      return FAILURE;
989    }
990    return SUCCESS;
991  }
992
993
994  void recordParameters(std::ostream& theStream, Param &par, std::string paramName, std::string paramDesc, std::string paramValue)
995  {
996   
997    const int width = 60;
998    int widthText = width - paramName.size();
999
1000    theStream << par.commentString()
1001              << std::setw(widthText) << paramDesc
1002              << std::setiosflags(std::ios::right) << paramName
1003              << "  =  " << std::resetiosflags(std::ios::right) << paramValue
1004              <<std::endl;
1005  }
1006
1007  std::string fileOption(bool flag, std::string file)
1008  {
1009    std::ostringstream ss;
1010    ss << stringize(flag);
1011    if(flag) ss << " --> " << file;
1012    return ss.str();
1013   
1014  }
1015
1016  std::ostream& operator<< ( std::ostream& theStream, Param& par)
1017  {
1018    /// Print out the parameter set in a formatted, easy to read style.
1019    /// Lists the parameters, a description of them, and their value.
1020
1021    // BUG -- can get error: `boolalpha' is not a member of type `ios' -- old compilers: gcc 2.95.3?
1022    //   theStream.setf(std::ios::boolalpha);
1023    theStream.setf(std::ios::left);
1024    theStream  <<par.commentString()<<"\n"<<par.commentString()<<"---- Parameters ----"<<std::endl;
1025    theStream  << std::setfill('.');
1026    if(par.getFlagSubsection())
1027      recordParam(theStream, par, "[imageFile]", "Image to be analysed", par.getImageFile()<<par.getSubsection());
1028    else
1029      recordParam(theStream, par, "[imageFile]", "Image to be analysed", par.getImageFile());
1030    if(par.getFlagRestFrequencyUsed()){
1031      recordParam(theStream, par, "[restFrequency]","Rest frequency as used", par.getRestFrequency());
1032    }
1033    if(par.getFlagReconExists() && par.getFlagATrous()){
1034      recordParam(theStream, par, "[reconExists]", "Reconstructed array exists?", stringize(par.getFlagReconExists()));
1035      recordParam(theStream, par, "[reconFile]", "FITS file containing reconstruction", par.getReconFile());
1036    }
1037    if(par.getFlagSmoothExists() && par.getFlagSmooth()){
1038      recordParam(theStream, par, "[smoothExists]", "Smoothed array exists?", stringize(par.getFlagSmoothExists()));
1039      recordParam(theStream, par, "[smoothFile]", "FITS file containing smoothed array", par.getSmoothFile());
1040    }
1041    recordParam(theStream, par, "[logFile]", "Intermediate Logfile", par.logFile);
1042    recordParam(theStream, par, "[outFile]", "Final Results file", par.getOutFile());
1043    if(par.getFlagSeparateHeader()){
1044      recordParam(theStream, par, "[headerFile]", "Header for results file", par.getHeaderFile());
1045    }
1046    if(USE_PGPLOT && par.getFlagPlotSpectra()){
1047      std::string label=par.getSpectraFile();
1048      if(par.getFlagPlotIndividualSpectra()) label += ", with individual spectra too";
1049      recordParam(theStream, par, "[spectraFile]", "Spectrum file", label);
1050    }
1051    if(par.getFlagTextSpectra()){
1052      recordParam(theStream, par, "[spectraTextFile]", "Text file with ascii spectral data", par.getSpectraTextFile());
1053    }
1054    if(par.getFlagVOT()){
1055      recordParam(theStream, par, "[votFile]", "VOTable file", par.getVOTFile());
1056    }
1057    if(par.getFlagKarma()){
1058      recordParam(theStream, par, "[karmaFile]", "Karma annotation file" , par.getKarmaFile());
1059    }
1060    if(par.getFlagDS9()){
1061      recordParam(theStream, par, "[ds9File]", "DS9 annotation file" , par.getDS9File());
1062    }
1063    if(par.getFlagCasa()){
1064      recordParam(theStream, par, "[casaFile]", "CASA annotation file" , par.getCasaFile());
1065    }
1066    if(USE_PGPLOT && par.getFlagMaps()){
1067      recordParam(theStream, par, "[momentMap]", "0th Moment Map", par.getMomentMap());
1068      recordParam(theStream, par, "[detectionMap]", "Detection Map", par.getDetectionMap());
1069    }
1070    if(USE_PGPLOT){
1071      recordParam(theStream, par, "[flagXOutput]", "Display a map in a pgplot xwindow?", stringize(par.getFlagXOutput()));
1072    }
1073    if(par.getFlagATrous()){
1074      recordParam(theStream, par, "[flagOutputRecon]", "Saving reconstructed cube?", fileOption(par.getFlagOutputRecon(),par.outputReconFile()));
1075      recordParam(theStream, par, "[flagOutputResid]", "Saving residuals from reconstruction?", fileOption(par.getFlagOutputResid(),par.outputResidFile()));
1076    }                                                 
1077    if(par.getFlagSmooth()){   
1078      recordParam(theStream, par, "[flagOutputSmooth]", "Saving smoothed cube?", fileOption(par.getFlagOutputSmooth(),par.outputSmoothFile()));
1079    }                                                 
1080    recordParam(theStream, par, "[flagOutputMask]", "Saving mask cube?", fileOption(par.getFlagOutputMask(),par.outputMaskFile()));
1081    recordParam(theStream, par, "[flagOutputMomentMap]", "Saving 0th moment to FITS file?", fileOption(par.getFlagOutputMomentMap(),par.outputMomentMapFile()));
1082    recordParam(theStream, par, "[flagOutputMomentMask]", "Saving 0th moment mask to FITS file?", fileOption(par.getFlagOutputMomentMask(),par.outputMomentMaskFile()));
1083    recordParam(theStream, par, "[flagOutputBaseline]", "Saving baseline values to FITS file?", fileOption(par.getFlagOutputBaseline(),par.outputBaselineFile()));
1084
1085    theStream  << par.commentString() <<"------"<<std::endl;
1086
1087    recordParam(theStream, par, "[searchType]", "Type of searching performed", par.getSearchType());
1088    if(par.getFlagBlankPix()){
1089      recordParam(theStream, par, "", "Blank Pixel Value", par.getBlankPixVal());
1090    }
1091    recordParam(theStream, par, "[flagTrim]", "Trimming Blank Pixels?", stringize(par.getFlagTrim()));
1092    recordParam(theStream, par, "[flagNegative]", "Searching for Negative features?", stringize(par.getFlagNegative()));
1093    if(par.getFlaggedChannelList().size()>0){
1094        recordParam(theStream, par, "[flaggedChannels]", "Channels flagged by user", par.getFlaggedChannelList());
1095    }
1096    if(par.beamAsUsed.origin()==EMPTY){  // No beam in FITS file and no information provided
1097      recordParam(theStream, par, "", "Area of Beam", "No beam");
1098    }
1099    else if(par.beamAsUsed.origin()==HEADER){ // Report beam size from FITS file
1100      recordParam(theStream, par, "", "Area of Beam (pixels)", par.beamAsUsed.area() << "   (beam: " << par.beamAsUsed.maj() << " x " << par.beamAsUsed.min() <<" pixels)");
1101    }
1102    else if(par.beamAsUsed.origin()==PARAM){ // Report beam size requested in parameter set input
1103      if(par.fwhmBeam>0.) recordParam(theStream, par, "[beamFWHM]", "FWHM of Beam (pixels)", par.beamAsUsed.maj() << "   (beam area = " << par.beamAsUsed.area() <<" pixels)");
1104      else  recordParam(theStream, par, "[beamArea]", "Area of Beam (pixels)", par.beamAsUsed.area());
1105    }
1106    else{
1107      recordParam(theStream, par, "[beam info]", "Size & shape of beam", "No information available!");
1108    }
1109    recordParam(theStream, par, "[flagBaseline]", "Removing baselines before search?", stringize(par.getFlagBaseline()));
1110    if(par.getFlagBaseline()){
1111        recordParam(theStream, par, "[baselineType]", "Baseline removal algorithm", par.getBaselineType());
1112        if(par.getBaselineType()=="median")
1113            recordParam(theStream, par, "[baselineBoxWidth]", "Box width for median baseline estimation", par.getBaselineBoxWidth());
1114    }
1115    recordParam(theStream, par, "[flagSmooth]", "Smoothing data prior to searching?", stringize(par.getFlagSmooth()));
1116    if(par.getFlagSmooth()){           
1117      recordParam(theStream, par, "[smoothType]", "Type of smoothing", par.getSmoothType());
1118      if(par.getSmoothType()=="spectral")
1119        recordParam(theStream, par, "[hanningWidth]", "Width of hanning filter", par.getHanningWidth());
1120      else{
1121        recordParam(theStream, par, "[kernMaj]", "Gaussian kernel major axis FWHM [pix]", par.getKernMaj());
1122        recordParam(theStream, par, "[kernMin]", "Gaussian kernel minor axis FWHM [pix]", par.getKernMin());
1123        recordParam(theStream, par, "[kernPA]",  "Gaussian kernel position angle [deg]",  par.getKernPA());
1124        recordParam(theStream, par, "[smoothEdgeMethod]","Method for treating edge pixels", par.getSmoothEdgeMethod());
1125        recordParam(theStream, par, "[spatialSmoothCutoff]","Cutoff value for determining kernel", par.getSpatialSmoothCutoff());
1126      }
1127    }
1128    recordParam(theStream, par, "[flagATrous]", "Using A Trous reconstruction?", stringize(par.getFlagATrous()));
1129    if(par.getFlagATrous()){                           
1130      recordParam(theStream, par, "[reconDim]", "Number of dimensions in reconstruction", par.getReconDim());
1131      if(par.getMaxScale()>0){
1132        recordParam(theStream, par, "[scaleMin-scaleMax]", "Scales used in reconstruction", par.getMinScale()<<"-"<<par.getMaxScale());
1133      }
1134      else{
1135        recordParam(theStream, par, "[scaleMin]", "Minimum scale in reconstruction", par.getMinScale());
1136      }
1137      recordParam(theStream, par, "[snrRecon]", "SNR Threshold within reconstruction", par.getAtrousCut());
1138      recordParam(theStream, par, "[reconConvergence]", "Residual convergence criterion", par.getReconConvergence());
1139      recordParam(theStream, par, "[filterCode]", "Filter being used for reconstruction", par.getFilterCode()<<" ("<<par.getFilterName()<<")");
1140    }                                                 
1141    recordParam(theStream, par, "[flagRobustStats]", "Using Robust statistics?", stringize(par.getFlagRobustStats()));
1142    if(par.getFlagStatSec()){
1143      recordParam(theStream, par, "[statSec]", "Section used by statistics calculation", par.statSec.getSection());
1144    }
1145    recordParam(theStream, par, "[flagFDR]", "Using FDR analysis?", stringize(par.getFlagFDR()));
1146    if(par.getFlagFDR()){                                     
1147      recordParam(theStream, par, "[alphaFDR]", "Alpha value for FDR analysis", par.getAlpha());
1148      recordParam(theStream, par, "[FDRnumCorChan]", "Number of correlated channels for FDR", par.getFDRnumCorChan());
1149    }                                                 
1150    else {
1151      if(par.getFlagUserThreshold()){
1152        recordParam(theStream, par, "[threshold]", "Detection Threshold", par.getThreshold());
1153      }
1154      else{
1155        recordParam(theStream, par, "[snrCut]", "SNR Threshold (in sigma)", par.getCut());
1156      }
1157    }
1158    recordParam(theStream, par, "[minPix]", "Minimum # Pixels in a detection", par.getMinPix());
1159    recordParam(theStream, par, "[minChannels]", "Minimum # Channels in a detection", par.getMinChannels());
1160    recordParam(theStream, par, "[minVoxels]", "Minimum # Voxels in a detection", par.getMinVoxels());
1161    if(par.getMaxPix()>0) recordParam(theStream, par, "[maxPix]", "Maximum # Pixels in a detection", par.getMaxPix());
1162    if(par.getMaxChannels()>0) recordParam(theStream, par, "[maxChannels]", "Maximum # Channels in a detection", par.getMaxChannels());
1163    if(par.getMaxVoxels()>0) recordParam(theStream, par, "[maxVoxels]", "Maximum # Voxels in a detection", par.getMaxVoxels());
1164    recordParam(theStream, par, "[flagGrowth]", "Growing objects after detection?", stringize(par.getFlagGrowth()));
1165    if(par.getFlagGrowth()) {                         
1166      if(par.getFlagUserGrowthThreshold()){
1167        recordParam(theStream, par, "[growthThreshold]", "Threshold for growth", par.getGrowthThreshold());
1168      }
1169      else{
1170        recordParam(theStream, par, "[growthCut]", "SNR Threshold for growth", par.getGrowthCut());
1171      }
1172    }
1173    recordParam(theStream, par, "[flagAdjacent]", "Using Adjacent-pixel criterion?", stringize(par.getFlagAdjacent()));
1174    if(!par.getFlagAdjacent()){
1175      recordParam(theStream, par, "[threshSpatial]", "Max. spatial separation for merging", par.getThreshS());
1176    }
1177    recordParam(theStream, par, "[threshVelocity]", "Max. velocity separation for merging", par.getThreshV());
1178    recordParam(theStream, par, "[flagRejectBeforeMerge]", "Reject objects before merging?", stringize(par.getFlagRejectBeforeMerge()));
1179    recordParam(theStream, par, "[flagTwoStageMerging]", "Merge objects in two stages?", stringize(par.getFlagTwoStageMerging()));
1180    recordParam(theStream, par, "[spectralMethod]", "Method of spectral plotting", par.getSpectralMethod());
1181    recordParam(theStream, par, "[pixelCentre]", "Type of object centre used in results", par.getPixelCentre());
1182
1183    theStream  << par.commentString() <<"--------------------\n";
1184    theStream  << std::setfill(' ');
1185    theStream.unsetf(std::ios::left);
1186    //  theStream.unsetf(std::ios::boolalpha);
1187    return theStream;
1188  }
1189
1190  std::vector<VOParam> Param::getVOParams()
1191  {
1192    std::vector<VOParam> vopars;
1193    vopars.push_back(VOParam("imageFile","meta.file;meta.fits","char",this->imageFile,this->imageFile.size(),""));
1194    vopars.push_back(VOParam("flagSubsection","meta.code","boolean",this->flagSubsection,0,""));
1195    if(this->flagSubsection)
1196      vopars.push_back(VOParam("subsection","","char",this->pixelSec.getSection(),this->pixelSec.getSection().size(),""));
1197    vopars.push_back(VOParam("flagStatSec","meta.code","boolean",this->flagStatSec,0,""));
1198    if(this->flagSubsection)
1199      vopars.push_back(VOParam("StatSec","","char",this->statSec.getSection(),this->statSec.getSection().size(),""));
1200    if(this->flagReconExists)
1201      vopars.push_back(VOParam("reconfile","meta.file;meta.fits","char",this->reconFile, this->reconFile.size(),""));
1202    if(this->flagSmoothExists)
1203      vopars.push_back(VOParam("smoothfile","meta.file;meta.fits","char",this->smoothFile, this->smoothFile.size(),""));
1204    if(this->usePrevious)
1205      vopars.push_back(VOParam("objectlist","","char",this->objectList,this->objectList.size(),""));
1206
1207    vopars.push_back(VOParam("searchType","meta.note","char",this->searchType,this->searchType.size(),""));
1208    vopars.push_back(VOParam("flagNegative","meta.code","boolean",this->flagNegative,0,""));
1209    vopars.push_back(VOParam("flagBaseline","meta.code","boolean",this->flagBaseline,0,""));
1210    if(this->flagBaseline){
1211        vopars.push_back(VOParam("baselineType","meta.note","char",this->baselineType,this->baselineType.size(),""));
1212        if(this->baselineType=="median")
1213            vopars.push_back(VOParam("baselineBoxWidth","","int",this->baselineBoxWidth,0,""));
1214    }
1215    vopars.push_back(VOParam("flagRobustStats","meta.code","boolean",this->flagRobustStats,0,""));
1216    vopars.push_back(VOParam("flagFDR","meta.code","boolean",this->flagFDR,0,""));
1217    if(this->flagFDR){
1218      vopars.push_back(VOParam("alphaFDR","stat.param","float",this->alphaFDR,0,""));
1219      vopars.push_back(VOParam("FDRnumCorChan","stat.param","int",this->FDRnumCorChan,0,""));
1220    }
1221    else{
1222      if(this->flagUserThreshold)
1223            vopars.push_back(VOParam("threshold","phot.flux;stat.min","float",this->threshold,0,""));
1224      else
1225        vopars.push_back(VOParam("snrCut","stat.snr;phot;stat.min","float",this->snrCut,0,""));
1226    }
1227    vopars.push_back(VOParam("flagGrowth","meta.code","boolean",this->flagGrowth,0,""));
1228    if(this->flagGrowth){
1229      if(this->flagUserGrowthThreshold)
1230        vopars.push_back(VOParam("growthThreshold","phot.flux;stat.min","float",this->growthThreshold,0,""));
1231      else
1232        vopars.push_back(VOParam("growthCut","stat.snr;phot;stat.min","float",this->growthCut,0,""));
1233    }
1234    vopars.push_back(VOParam("minPix","","int",this->minPix,0,""));
1235    vopars.push_back(VOParam("minChannels","","int",this->minChannels,0,""));
1236    vopars.push_back(VOParam("minVoxels","","int",this->minVoxels,0,""));
1237    if(this->maxPix>0) vopars.push_back(VOParam("maxPix","","int",this->maxPix,0,""));
1238    if(this->maxChannels>0) vopars.push_back(VOParam("maxChannels","","int",this->maxChannels,0,""));
1239    if(this->maxVoxels>0) vopars.push_back(VOParam("maxVoxels","","int",this->maxVoxels,0,""));
1240    vopars.push_back(VOParam("flagAdjacent","meta.code","boolean",this->flagAdjacent,0,""));
1241    if(!this->flagAdjacent)
1242      vopars.push_back(VOParam("threshSpatial","","float",this->threshSpatial,0,""));
1243    vopars.push_back(VOParam("threshVelocity","","float",this->threshVelocity,0,""));
1244    vopars.push_back(VOParam("flagRejectBeforeMerge","","boolean",this->flagRejectBeforeMerge,0,""));
1245    vopars.push_back(VOParam("flagTwoStageMerging","","boolean",this->flagTwoStageMerging,0,""));
1246    vopars.push_back(VOParam("pixelCentre","","char",this->pixelCentre,this->pixelCentre.size(),""));
1247    vopars.push_back(VOParam("flagSmooth","meta.code","boolean",this->flagSmooth,0,""));
1248    if(this->flagSmooth){
1249      vopars.push_back(VOParam("smoothType","","char",this->smoothType,this->smoothType.size(),""));
1250      if(this->smoothType=="spectral")
1251        vopars.push_back(VOParam("hanningWidth","","int",this->hanningWidth,0,""));
1252      else{
1253        vopars.push_back(VOParam("kernMaj","","float",this->kernMaj,0,""));
1254        vopars.push_back(VOParam("kernMin","","float",this->kernMin,0,""));
1255        vopars.push_back(VOParam("kernPA","","float",this->kernPA,0,""));
1256        vopars.push_back(VOParam("smoothEdgeMethod","","char",this->smoothEdgeMethod,this->smoothEdgeMethod.size(),""));
1257        vopars.push_back(VOParam("spatialSmoothCutoff","","float", this->spatialSmoothCutoff,0,""));
1258      }
1259    }
1260    vopars.push_back(VOParam("flagATrous","meta.code","boolean",this->flagATrous,0,""));
1261    if(this->flagATrous){
1262      vopars.push_back(VOParam("reconDim","","int",this->reconDim,0,""));
1263      vopars.push_back(VOParam("scaleMin","","int",this->scaleMin,0,""));
1264      if(this->scaleMax>0)
1265        vopars.push_back(VOParam("scaleMax","","int",this->scaleMax,0,""));
1266      vopars.push_back(VOParam("snrRecon","","float",this->snrRecon,0,""));
1267      vopars.push_back(VOParam("reconConvergence","","float",this->reconConvergence,0,""));
1268      vopars.push_back(VOParam("filterCode","","int",this->filterCode,0,""));
1269    }
1270    if(this->beamAsUsed.origin()==PARAM){
1271      if(this->fwhmBeam>0)
1272        vopars.push_back(VOParam("beamFWHM","","float",this->fwhmBeam,0,""));
1273      else
1274        vopars.push_back(VOParam("beamArea","","float",this->areaBeam,0,""));
1275    }
1276    if(this->restFrequencyUsed){
1277      vopars.push_back(VOParam("restFrequency","em.freq","float",this->restFrequency,0,"Hz"));
1278    }
1279
1280    return vopars;
1281
1282  }
1283
1284  void Param::writeToBinaryFile(std::string &filename)
1285  {
1286    std::ofstream outfile(filename.c_str(), std::ios::out | std::ios::binary | std::ios::app);
1287    writeStringToBinaryFile(outfile,this->imageFile);
1288    outfile.write(reinterpret_cast<const char*>(&this->flagSubsection), sizeof this->flagSubsection);
1289    if(this->flagSubsection) writeStringToBinaryFile(outfile,this->pixelSec.getSection());
1290    outfile.write(reinterpret_cast<const char*>(&this->flagStatSec), sizeof this->flagStatSec);
1291    if(this->flagStatSec) writeStringToBinaryFile(outfile,this->statSec.getSection());
1292    outfile.write(reinterpret_cast<const char*>(&this->flagReconExists), sizeof this->flagReconExists);
1293    if(this->flagReconExists) writeStringToBinaryFile(outfile,this->reconFile);
1294    outfile.write(reinterpret_cast<const char*>(&this->flagSmoothExists), sizeof this->flagSmoothExists);
1295    if(this->flagSmoothExists) writeStringToBinaryFile(outfile,this->smoothFile);
1296    //
1297    writeStringToBinaryFile(outfile,this->searchType);
1298    outfile.write(reinterpret_cast<const char*>(&this->flagNegative), sizeof this->flagNegative);
1299    outfile.write(reinterpret_cast<const char*>(&this->flagBaseline), sizeof this->flagBaseline);
1300    if(this->flagBaseline){
1301        writeStringToBinaryFile(outfile,this->baselineType);
1302        if(this->baselineType=="median")
1303            outfile.write(reinterpret_cast<const char*>(&this->baselineBoxWidth), sizeof this->baselineBoxWidth);
1304    }
1305    outfile.write(reinterpret_cast<const char*>(&this->flagRobustStats), sizeof this->flagRobustStats);
1306    outfile.write(reinterpret_cast<const char*>(&this->flagFDR), sizeof this->flagFDR);
1307    if(this->flagFDR){
1308      outfile.write(reinterpret_cast<const char*>(&this->alphaFDR), sizeof this->alphaFDR);
1309      outfile.write(reinterpret_cast<const char*>(&this->FDRnumCorChan), sizeof this->FDRnumCorChan);
1310      bool beamFromParam=(this->beamAsUsed.origin() == PARAM);
1311      outfile.write(reinterpret_cast<const char*>(&beamFromParam), sizeof beamFromParam);
1312      if(beamFromParam){
1313        outfile.write(reinterpret_cast<const char*>(&this->fwhmBeam), sizeof this->fwhmBeam);
1314        outfile.write(reinterpret_cast<const char*>(&this->areaBeam), sizeof this->areaBeam);
1315      }
1316    }
1317    else{
1318      outfile.write(reinterpret_cast<const char*>(&this->flagUserThreshold), sizeof this->flagUserThreshold);
1319      if(this->flagUserThreshold)
1320        outfile.write(reinterpret_cast<const char*>(&this->threshold), sizeof this->threshold);
1321      else
1322        outfile.write(reinterpret_cast<const char*>(&this->snrCut), sizeof this->snrCut);
1323    }
1324    outfile.write(reinterpret_cast<const char*>(&this->flagGrowth), sizeof this->flagGrowth);
1325    if(this->flagGrowth){
1326      outfile.write(reinterpret_cast<const char*>(&this->flagUserGrowthThreshold), sizeof this->flagUserGrowthThreshold);
1327      if(this->flagUserGrowthThreshold)
1328        outfile.write(reinterpret_cast<const char*>(&this->growthThreshold), sizeof this->growthThreshold);
1329      else
1330        outfile.write(reinterpret_cast<const char*>(&this->growthCut), sizeof this->growthCut);
1331    }
1332    outfile.write(reinterpret_cast<const char*>(&this->minPix), sizeof this->minPix);
1333    outfile.write(reinterpret_cast<const char*>(&this->minChannels), sizeof this->minChannels);
1334    outfile.write(reinterpret_cast<const char*>(&this->minVoxels), sizeof this->minVoxels);
1335    outfile.write(reinterpret_cast<const char*>(&this->maxPix), sizeof this->maxPix);
1336    outfile.write(reinterpret_cast<const char*>(&this->maxChannels), sizeof this->maxChannels);
1337    outfile.write(reinterpret_cast<const char*>(&this->maxVoxels), sizeof this->maxVoxels);
1338    outfile.write(reinterpret_cast<const char*>(&this->flagAdjacent), sizeof this->flagAdjacent);
1339    if(!this->flagAdjacent)
1340      outfile.write(reinterpret_cast<const char*>(&this->threshSpatial), sizeof this->threshSpatial);
1341    outfile.write(reinterpret_cast<const char*>(&this->threshVelocity), sizeof this->threshVelocity);
1342    outfile.write(reinterpret_cast<const char*>(&this->flagRejectBeforeMerge), sizeof this->flagRejectBeforeMerge);
1343    outfile.write(reinterpret_cast<const char*>(&this->flagTwoStageMerging), sizeof this->flagTwoStageMerging);
1344    outfile.write(reinterpret_cast<const char*>(&this->flagSmooth), sizeof this->flagSmooth);
1345    if(this->flagSmooth){
1346      bool type=(this->smoothType=="spectral");
1347      outfile.write(reinterpret_cast<const char*>(&type), sizeof type);
1348      if(type)
1349        outfile.write(reinterpret_cast<const char*>(&this->hanningWidth), sizeof this->hanningWidth);
1350      else{
1351        outfile.write(reinterpret_cast<const char*>(&this->kernMaj), sizeof this->kernMaj);
1352        outfile.write(reinterpret_cast<const char*>(&this->kernMin), sizeof this->kernMin);
1353        outfile.write(reinterpret_cast<const char*>(&this->kernPA), sizeof this->kernPA);
1354        outfile.write(reinterpret_cast<const char*>(&this->smoothEdgeMethod), sizeof this->smoothEdgeMethod);
1355        outfile.write(reinterpret_cast<const char*>(&this->spatialSmoothCutoff), sizeof this->spatialSmoothCutoff);
1356      }
1357    }
1358    outfile.write(reinterpret_cast<const char*>(&this->flagATrous), sizeof this->flagATrous);
1359    if(this->flagATrous){
1360      outfile.write(reinterpret_cast<const char*>(&this->reconDim), sizeof this->reconDim);
1361      outfile.write(reinterpret_cast<const char*>(&this->scaleMin), sizeof this->scaleMin);
1362      outfile.write(reinterpret_cast<const char*>(&this->scaleMax), sizeof this->scaleMax);
1363      outfile.write(reinterpret_cast<const char*>(&this->snrRecon), sizeof this->snrRecon);
1364      outfile.write(reinterpret_cast<const char*>(&this->reconConvergence), sizeof this->reconConvergence);
1365      outfile.write(reinterpret_cast<const char*>(&this->filterCode), sizeof this->filterCode);
1366    }
1367    writeStringToBinaryFile(outfile,this->flaggedChannelList);
1368
1369    outfile.close();
1370  }
1371
1372  std::streampos Param::readFromBinaryFile(std::string &filename, std::streampos loc)
1373  {
1374    std::ifstream infile(filename.c_str(), std::ios::in | std::ios::binary);
1375    if(!infile.is_open()){
1376      DUCHAMPERROR("read binary parameters","Could not open binary catalogue \""<<filename <<"\"");
1377      return -1;
1378    }
1379    infile.seekg(loc);
1380    this->imageFile = readStringFromBinaryFile(infile);
1381    infile.read(reinterpret_cast<char*>(&this->flagSubsection), sizeof this->flagSubsection);
1382    if(this->flagSubsection){
1383      std::string sec=readStringFromBinaryFile(infile);
1384      this->pixelSec.setSection(sec);
1385    }
1386    infile.read(reinterpret_cast<char*>(&this->flagStatSec), sizeof this->flagStatSec);
1387    if(this->flagStatSec){
1388      std::string sec=readStringFromBinaryFile(infile);
1389      this->statSec.setSection(sec);
1390    }
1391    infile.read(reinterpret_cast<char*>(&this->flagReconExists), sizeof this->flagReconExists);
1392    if(this->flagReconExists) this->reconFile=readStringFromBinaryFile(infile);
1393    infile.read(reinterpret_cast<char*>(&this->flagSmoothExists), sizeof this->flagSmoothExists);
1394    if(this->flagSmoothExists) this->smoothFile=readStringFromBinaryFile(infile);
1395    //
1396    this->searchType=readStringFromBinaryFile(infile);
1397    infile.read(reinterpret_cast<char*>(&this->flagNegative), sizeof this->flagNegative);
1398    infile.read(reinterpret_cast<char*>(&this->flagBaseline), sizeof this->flagBaseline);
1399    if(this->flagBaseline){
1400        this->baselineType = readStringFromBinaryFile(infile);
1401        if(this->baselineType == "median")
1402            infile.read(reinterpret_cast<char*>(&this->baselineBoxWidth), sizeof this->baselineBoxWidth);
1403    }
1404    infile.read(reinterpret_cast<char*>(&this->flagRobustStats), sizeof this->flagRobustStats);
1405    infile.read(reinterpret_cast<char*>(&this->flagFDR), sizeof this->flagFDR);
1406    if(this->flagFDR){
1407      infile.read(reinterpret_cast<char*>(&this->alphaFDR), sizeof this->alphaFDR);
1408      infile.read(reinterpret_cast<char*>(&this->FDRnumCorChan), sizeof this->FDRnumCorChan);
1409      bool beamFromParam;
1410      infile.read(reinterpret_cast<char*>(&beamFromParam), sizeof beamFromParam);
1411      if(beamFromParam){
1412        infile.read(reinterpret_cast<char*>(&this->fwhmBeam), sizeof this->fwhmBeam);
1413        infile.read(reinterpret_cast<char*>(&this->areaBeam), sizeof this->areaBeam);
1414      }
1415    }
1416    else{
1417      infile.read(reinterpret_cast<char*>(&this->flagUserThreshold), sizeof this->flagUserThreshold);
1418      if(this->flagUserThreshold)
1419        infile.read(reinterpret_cast<char*>(&this->threshold), sizeof this->threshold);
1420      else
1421        infile.read(reinterpret_cast<char*>(&this->snrCut), sizeof this->snrCut);
1422    }
1423    infile.read(reinterpret_cast<char*>(&this->flagGrowth), sizeof this->flagGrowth);
1424    if(this->flagGrowth){
1425      infile.read(reinterpret_cast<char*>(&this->flagUserGrowthThreshold), sizeof this->flagUserGrowthThreshold);
1426      if(this->flagUserGrowthThreshold)
1427        infile.read(reinterpret_cast<char*>(&this->growthThreshold), sizeof this->growthThreshold);
1428      else
1429        infile.read(reinterpret_cast<char*>(&this->growthCut), sizeof this->growthCut);
1430    }
1431    infile.read(reinterpret_cast<char*>(&this->minPix), sizeof this->minPix);
1432    infile.read(reinterpret_cast<char*>(&this->minChannels), sizeof this->minChannels);
1433    infile.read(reinterpret_cast<char*>(&this->minVoxels), sizeof this->minVoxels);
1434    infile.read(reinterpret_cast<char*>(&this->maxPix), sizeof this->maxPix);
1435    infile.read(reinterpret_cast<char*>(&this->maxChannels), sizeof this->maxChannels);
1436    infile.read(reinterpret_cast<char*>(&this->maxVoxels), sizeof this->maxVoxels);
1437    infile.read(reinterpret_cast<char*>(&this->flagAdjacent), sizeof this->flagAdjacent);
1438    if(!this->flagAdjacent)
1439      infile.read(reinterpret_cast<char*>(&this->threshSpatial), sizeof this->threshSpatial);
1440    infile.read(reinterpret_cast<char*>(&this->threshVelocity), sizeof this->threshVelocity);
1441    infile.read(reinterpret_cast<char*>(&this->flagRejectBeforeMerge), sizeof this->flagRejectBeforeMerge);
1442    infile.read(reinterpret_cast<char*>(&this->flagTwoStageMerging), sizeof this->flagTwoStageMerging);
1443    infile.read(reinterpret_cast<char*>(&this->flagSmooth), sizeof this->flagSmooth);
1444    if(this->flagSmooth){
1445      bool type;
1446      infile.read(reinterpret_cast<char*>(&type), sizeof type);
1447      this->smoothType = type ? "spectral" : "spatial";
1448      if(type)
1449        infile.read(reinterpret_cast<char*>(&this->hanningWidth), sizeof this->hanningWidth);
1450      else{
1451        infile.read(reinterpret_cast<char*>(&this->kernMaj), sizeof this->kernMaj);
1452        infile.read(reinterpret_cast<char*>(&this->kernMin), sizeof this->kernMin);
1453        infile.read(reinterpret_cast<char*>(&this->kernPA), sizeof this->kernPA);
1454        infile.read(reinterpret_cast<char*>(&this->smoothEdgeMethod), sizeof this->smoothEdgeMethod);
1455        infile.read(reinterpret_cast<char*>(&this->spatialSmoothCutoff), sizeof this->spatialSmoothCutoff);
1456      }
1457    }
1458    infile.read(reinterpret_cast<char*>(&this->flagATrous), sizeof this->flagATrous);
1459    if(this->flagATrous){
1460      infile.read(reinterpret_cast<char*>(&this->reconDim), sizeof this->reconDim);
1461      infile.read(reinterpret_cast<char*>(&this->scaleMin), sizeof this->scaleMin);
1462      infile.read(reinterpret_cast<char*>(&this->scaleMax), sizeof this->scaleMax);
1463      infile.read(reinterpret_cast<char*>(&this->snrRecon), sizeof this->snrRecon);
1464      infile.read(reinterpret_cast<char*>(&this->reconConvergence), sizeof this->reconConvergence);
1465      infile.read(reinterpret_cast<char*>(&this->filterCode), sizeof this->filterCode);
1466    }
1467    this->flaggedChannelList=readStringFromBinaryFile(infile);
1468
1469    std::streampos newloc = infile.tellg();
1470    infile.close();
1471    return newloc;
1472
1473  }
1474
1475
1476
1477
1478  void Param::copyHeaderInfo(FitsHeader &head)
1479  {
1480    ///  A function to copy across relevant header keywords from the
1481    ///  FitsHeader class to the Param class, as they are needed by
1482    ///  functions in the Param class.
1483    ///  The parameters are the keywords BLANK, BSCALE, BZERO, and the beam size.
1484
1485    this->blankKeyword  = head.getBlankKeyword();
1486    this->bscaleKeyword = head.getBscaleKeyword();
1487    this->bzeroKeyword  = head.getBzeroKeyword();
1488    this->blankPixValue = this->blankKeyword * this->bscaleKeyword +
1489      this->bzeroKeyword;
1490  }
1491
1492  std::string Param::inputWithoutExtension()
1493  {
1494    /// This function takes the input filename and returns a string
1495    /// that doesn't have its .fits extension. It will also remove a
1496    /// .fits.gz extension. If no such extension exists, then the full
1497    /// filename is returned.
1498
1499    std::string inputName = this->imageFile;
1500    std::string outputName;
1501    size_t size=inputName.size();
1502    if(size>5 && inputName.substr(size-5,5)==".fits") 
1503      outputName = inputName.substr(0,size-5);
1504    else if(size>8 && inputName.substr(size-8,8)==".fits.gz")
1505      outputName = inputName.substr(0,size-8);
1506    else
1507      outputName = inputName;
1508    return outputName;
1509  }
1510
1511  std::string Param::outputMaskFile()
1512  {
1513    ///  This function produces the required filename in which to save
1514    ///  the mask image, indicating which pixels have been detected as
1515    ///  part of an object. If the input image is image.fits, then the
1516    ///  output will be image.MASK.fits.
1517
1518    if(this->fileOutputMask==""){
1519      std::string outputName = this->inputWithoutExtension();
1520      outputName += ".MASK.fits";
1521      return outputName;
1522    }
1523    else return this->fileOutputMask;
1524  }
1525
1526  std::string Param::outputMomentMapFile()
1527  {
1528    ///  This function produces the required filename in which to save
1529    ///  the moment-0 FITS image. If the input image is image.fits, then the
1530    ///  output will be image.MOM0.fits.
1531
1532    if(this->fileOutputMomentMap==""){
1533      std::string outputName = this->inputWithoutExtension();
1534      outputName += ".MOM0.fits";
1535      return outputName;
1536    }
1537    else return this->fileOutputMomentMap;
1538  }
1539
1540  std::string Param::outputMomentMaskFile()
1541  {
1542    ///  This function produces the required filename in which to save
1543    ///  the moment-0 FITS image. If the input image is image.fits, then the
1544    ///  output will be image.MOM0.fits.
1545
1546    if(this->fileOutputMomentMask==""){
1547      std::string outputName = this->inputWithoutExtension();
1548      outputName += ".MOM0MASK.fits";
1549      return outputName;
1550    }
1551    else return this->fileOutputMomentMask;
1552  }
1553
1554  std::string Param::outputBaselineFile()
1555  {
1556    ///  This function produces the required filename in which to save
1557    ///  the baseline FITS image. If the input image is image.fits, then the
1558    ///  output will be image.BASE.fits.
1559
1560    if(this->fileOutputBaseline==""){
1561      std::string outputName = this->inputWithoutExtension();
1562      outputName += ".BASE.fits";
1563      return outputName;
1564    }
1565    else return this->fileOutputBaseline;
1566  }
1567
1568  std::string Param::outputSmoothFile()
1569  {
1570    ///  This function produces the required filename in which to save
1571    ///   the smoothed array. If the input image is image.fits, then
1572    ///   the output will be:
1573    ///    <ul><li> Spectral smoothing: image.SMOOTH-1D-3.fits, where the
1574    ///             width of the Hanning filter was 3 pixels.
1575    ///        <li> Spatial smoothing : image.SMOOTH-2D-3-2-20-E-10.fits, where
1576    ///             kernMaj=3, kernMin=2 and kernPA=20 degrees, EQUAL edge method, and cutoff of 1.e-10.
1577    ///    </ul>
1578
1579    if(this->fileOutputSmooth==""){
1580      std::stringstream ss;
1581      ss << this->inputWithoutExtension();
1582      if(this->flagSubsection) ss<<".sub";
1583      if(this->smoothType=="spectral")
1584        ss << ".SMOOTH-1D-" << this->hanningWidth << ".fits";
1585      else if(this->smoothType=="spatial"){
1586          char method='X';
1587          if(this->smoothEdgeMethod=="equal") method='E';
1588          else if (this->smoothEdgeMethod=="truncate") method='T';
1589          else if (this->smoothEdgeMethod=="scale") method='S';
1590          ss << ".SMOOTH-2D-"
1591             << this->kernMaj << "-"
1592             << this->kernMin << "-"
1593             << this->kernPA  << "-"
1594             << method        << "-"
1595             << -log10(this->spatialSmoothCutoff)
1596             << ".fits";
1597      }
1598      return ss.str();
1599    }
1600    else return this->fileOutputSmooth;
1601  }
1602
1603  std::string Param::outputReconFile()
1604  {
1605    /// This function produces the required filename in which to save
1606    ///  the reconstructed array. If the input image is image.fits, then
1607    ///  the output will be eg. image.RECON-3-2-4-1.fits, where the numbers are
1608    ///  3=reconDim, 2=filterCode, 4=snrRecon, 1=minScale
1609
1610    if(this->fileOutputRecon==""){
1611      std::stringstream ss;
1612      ss << this->inputWithoutExtension();
1613      if(this->flagSubsection) ss<<".sub";
1614      ss << ".RECON-" << this->reconDim
1615         << "-"       << this->filterCode
1616         << "-"       << this->snrRecon
1617         << "-"       << this->scaleMin
1618         << "-"       << this->scaleMax
1619         << "-"       << this->reconConvergence
1620         << ".fits";
1621      return ss.str();
1622    }
1623    else return this->fileOutputRecon;
1624  }
1625
1626  std::string Param::outputResidFile()
1627  {
1628    /// This function produces the required filename in which to save
1629    ///  the reconstructed array. If the input image is image.fits, then
1630    ///  the output will be eg. image.RESID-3-2-4-1.fits, where the numbers are
1631    ///  3=reconDim, 2=filterCode, 4=snrRecon, 1=scaleMin
1632
1633    if(this->fileOutputResid==""){
1634      std::stringstream ss;
1635      ss << this->inputWithoutExtension();
1636      if(this->flagSubsection) ss<<".sub";
1637      ss << ".RESID-" << this->reconDim
1638         << "-"       << this->filterCode
1639         << "-"       << this->snrRecon
1640         << "-"       << this->scaleMin
1641         << "-"       << this->scaleMax
1642         << "-"       << this->reconConvergence
1643         << ".fits";
1644      return ss.str();
1645    }
1646    else return this->fileOutputResid;
1647  }
1648
1649}
Note: See TracBrowser for help on using the repository browser.