source: trunk/src/param.cc @ 1137

Last change on this file since 1137 was 1137, checked in by MatthewWhiting, 11 years ago

Just about solving #180 - all ascii output now has comments in the right places, with only the table data uncommented. The table written to the screen is unaffected. The log file summary stuff is also untouched, but it needs a rethink anyway...

File size: 55.9 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/Utils/utils.hh>
44#include <duchamp/Utils/Section.hh>
45#include <duchamp/Utils/VOParam.hh>
46#include <duchamp/Outputs/columns.hh>
47
48namespace duchamp
49{
50  const std::string defaultSection = "[*,*,*]";
51
52  /****************************************************************/
53  ///////////////////////////////////////////////////
54  //// Accessor Functions for Parameter class:
55  ///////////////////////////////////////////////////
56  Param::~Param()
57  {
58    /// Deletes the offsets array if the sizeOffsets parameter is
59    /// positive.
60    if(this->sizeOffsets>0) delete [] this->offsets;
61  }
62
63  Param::Param()
64  {
65    this->defaultValues();
66  }
67
68  void Param::defaultValues()
69  {
70    /// Provides default intial values for the parameters. Note that
71    /// imageFile has no default value!
72
73    // Input files
74    this->imageFile         = "";
75    this->flagSubsection    = false;
76    this->pixelSec.setSection(defaultSection);
77    this->flagReconExists   = false;
78    this->reconFile         = "";
79    this->flagSmoothExists  = false;
80    this->smoothFile        = "";
81    this->usePrevious       = false;
82    this->objectList        = "";
83    // Output files
84    this->flagLog           = false;
85    this->logFile           = "duchamp-Logfile.txt";
86    this->outFile           = "duchamp-Results.txt";
87    this->flagSeparateHeader= false;
88    this->headerFile        = "duchamp-Results.hdr";
89    this->flagPlotSpectra   = true;
90    this->spectraFile       = "duchamp-Spectra.ps";
91    this->flagTextSpectra   = false;
92    this->spectraTextFile   = "duchamp-Spectra.txt";
93    this->flagOutputBaseline    = false;
94    this->fileOutputBaseline    = "";
95    this->flagOutputMomentMap    = false;
96    this->fileOutputMomentMap    = "";
97    this->flagOutputMask    = false;
98    this->fileOutputMask    = "";
99    this->flagMaskWithObjectNum = false;
100    this->flagOutputSmooth  = false;
101    this->fileOutputSmooth  = "";
102    this->flagOutputRecon   = false;
103    this->fileOutputRecon   = "";
104    this->flagOutputResid   = false;
105    this->fileOutputResid   = "";
106    this->flagVOT           = false;
107    this->votFile           = "duchamp-Results.xml";
108    this->flagKarma         = false;
109    this->karmaFile         = "duchamp-Results.ann";
110    this->flagDS9           = false;
111    this->ds9File           = "duchamp-Results.reg";
112    this->flagCasa          = false;
113    this->casaFile          = "duchamp-Results.crf";
114    this->annotationType    = "borders";
115    this->flagMaps          = true;
116    this->detectionMap      = "duchamp-DetectionMap.ps";
117    this->momentMap         = "duchamp-MomentMap.ps";
118    this->flagXOutput       = true;
119    this->precFlux          = Catalogues::prFLUX;
120    this->precVel           = Catalogues::prVEL;
121    this->precSNR           = Catalogues::prSNR;
122    // Cube related parameters
123    this->flagBlankPix      = false;
124    this->blankPixValue     = -8.00061;
125    this->blankKeyword      = 1;
126    this->bscaleKeyword     = -8.00061;
127    this->bzeroKeyword      = 0.;
128    this->newFluxUnits      = "";
129    // Milky-Way parameters
130    this->flagMW            = false;
131    this->maxMW             = 112;
132    this->minMW             = 75;
133    this->areaBeam          = 0.;
134    this->fwhmBeam          = 0.;
135    this->beamAsUsed.empty();
136    this->searchType        = "spatial";
137    // Trim-related         
138    this->flagTrim          = false;
139    this->hasBeenTrimmed    = false;
140    this->borderLeft        = 0;
141    this->borderRight       = 0;
142    this->borderBottom      = 0;
143    this->borderTop         = 0;
144    // Subsection offsets
145    this->sizeOffsets       = 0;
146    this->xSubOffset        = 0;
147    this->ySubOffset        = 0;
148    this->zSubOffset        = 0;
149    // Baseline related
150    this->flagBaseline      = false;
151    // Detection-related   
152    this->flagNegative      = false;
153    // Object growth       
154    this->flagGrowth        = false;
155    this->growthCut         = 3.;
156    this->flagUserGrowthThreshold = false;
157    this->growthThreshold   = 0.;
158    // FDR analysis         
159    this->flagFDR           = false;
160    this->alphaFDR          = 0.01;
161    this->FDRnumCorChan     = 2;
162    // Other detection     
163    this->flagStatSec       = false;
164    this->statSec.setSection(defaultSection);
165    this->flagRobustStats   = true;
166    this->snrCut            = 5.;
167    this->threshold         = 0.;
168    this->flagUserThreshold = false;
169    // Smoothing
170    this->flagSmooth        = false;
171    this->smoothType        = "spectral";
172    this->hanningWidth      = 5;
173    this->kernMaj           = 3.;
174    this->kernMin           = -1.;
175    this->kernPA            = 0.;
176    // A trous reconstruction parameters
177    this->flagATrous        = false;
178    this->reconDim          = 1;
179    this->scaleMin          = 1;
180    this->scaleMax          = 0;
181    this->snrRecon          = 4.;
182    this->reconConvergence  = 0.005;
183    this->filterCode        = 1;
184    this->reconFilter.define(this->filterCode);
185    // Volume-merging parameters
186    this->flagAdjacent      = true;
187    this->threshSpatial     = 3.;
188    this->threshVelocity    = 7.;
189    this->minChannels       = 3;
190    this->minPix            = 2;
191    this->minVoxels         = 4;
192    this->flagRejectBeforeMerge = false;
193    this->flagTwoStageMerging = true;
194    // Input-Output related
195    this->spectralMethod    = "peak";
196    this->spectralType      = "";
197    this->restFrequency     = -1.;
198    this->restFrequencyUsed = false;
199    this->spectralUnits     = "";
200    this->pixelCentre       = "centroid";
201    this->sortingParam      = "vel";
202    this->borders           = true;
203    this->blankEdge         = true;
204    this->verbose           = true;
205  }
206
207  Param::Param (const Param& p)
208  {
209    operator=(p);
210  }
211
212  Param& Param::operator= (const Param& p)
213  {
214    if(this == &p) return *this;
215    this->imageFile         = p.imageFile;
216    this->flagSubsection    = p.flagSubsection;
217    this->pixelSec          = p.pixelSec;
218    this->flagReconExists   = p.flagReconExists;
219    this->reconFile         = p.reconFile;     
220    this->flagSmoothExists  = p.flagSmoothExists;
221    this->smoothFile        = p.smoothFile;     
222    this->usePrevious       = p.usePrevious;
223    this->objectList        = p.objectList;
224    this->flagLog           = p.flagLog;       
225    this->logFile           = p.logFile;       
226    this->outFile           = p.outFile;       
227    this->flagSeparateHeader= p.flagSeparateHeader;
228    this->headerFile        = p.headerFile;
229    this->flagPlotSpectra   = p.flagPlotSpectra;
230    this->spectraFile       = p.spectraFile;   
231    this->flagTextSpectra   = p.flagTextSpectra;   
232    this->spectraTextFile   = p.spectraTextFile;   
233    this->flagOutputBaseline    = p.flagOutputBaseline;
234    this->fileOutputBaseline    = p.fileOutputBaseline;
235    this->flagOutputMomentMap    = p.flagOutputMomentMap;
236    this->fileOutputMomentMap    = p.fileOutputMomentMap;
237    this->flagOutputMask    = p.flagOutputMask;
238    this->fileOutputMask    = p.fileOutputMask;
239    this->flagMaskWithObjectNum = p.flagMaskWithObjectNum;
240    this->flagOutputSmooth  = p.flagOutputSmooth;
241    this->fileOutputSmooth  = p.fileOutputSmooth;
242    this->flagOutputRecon   = p.flagOutputRecon;
243    this->fileOutputRecon   = p.fileOutputRecon;
244    this->flagOutputResid   = p.flagOutputResid;
245    this->fileOutputResid   = p.fileOutputResid;
246    this->flagVOT           = p.flagVOT;         
247    this->votFile           = p.votFile;       
248    this->flagKarma         = p.flagKarma;     
249    this->karmaFile         = p.karmaFile;     
250    this->flagDS9           = p.flagDS9;     
251    this->ds9File           = p.ds9File;     
252    this->flagCasa          = p.flagCasa;     
253    this->casaFile          = p.casaFile;     
254    this->annotationType    = p.annotationType;
255    this->flagMaps          = p.flagMaps;       
256    this->detectionMap      = p.detectionMap;   
257    this->momentMap         = p.momentMap;     
258    this->flagXOutput       = p.flagXOutput;       
259    this->precFlux          = p.precFlux;
260    this->precVel           = p.precVel;
261    this->precSNR           = p.precSNR;
262    this->flagNegative      = p.flagNegative;
263    this->flagBlankPix      = p.flagBlankPix;   
264    this->blankPixValue     = p.blankPixValue; 
265    this->blankKeyword      = p.blankKeyword;   
266    this->bscaleKeyword     = p.bscaleKeyword; 
267    this->bzeroKeyword      = p.bzeroKeyword;   
268    this->newFluxUnits      = p.newFluxUnits;
269    this->flagMW            = p.flagMW;         
270    this->maxMW             = p.maxMW;         
271    this->minMW             = p.minMW;         
272    this->areaBeam          = p.areaBeam;     
273    this->fwhmBeam          = p.fwhmBeam;     
274    this->beamAsUsed        = p.beamAsUsed;
275    this->searchType        = p.searchType;
276    this->flagTrim          = p.flagTrim;   
277    this->hasBeenTrimmed    = p.hasBeenTrimmed;   
278    this->borderLeft        = p.borderLeft;     
279    this->borderRight       = p.borderRight;   
280    this->borderBottom      = p.borderBottom;   
281    this->borderTop         = p.borderTop;     
282    if(this->sizeOffsets>0) delete [] this->offsets;
283    this->sizeOffsets       = p.sizeOffsets;
284    if(this->sizeOffsets>0){
285      this->offsets           = new long[this->sizeOffsets];
286      for(int i=0;i<this->sizeOffsets;i++) this->offsets[i] = p.offsets[i];
287    }
288    this->xSubOffset        = p.xSubOffset;     
289    this->ySubOffset        = p.ySubOffset;     
290    this->zSubOffset        = p.zSubOffset;
291    this->flagBaseline      = p.flagBaseline;
292    this->flagGrowth        = p.flagGrowth;
293    this->growthCut         = p.growthCut;
294    this->growthThreshold   = p.growthThreshold;
295    this->flagUserGrowthThreshold = p.flagUserGrowthThreshold;
296    this->flagFDR           = p.flagFDR;
297    this->alphaFDR          = p.alphaFDR;
298    this->FDRnumCorChan     = p.FDRnumCorChan;
299    this->flagStatSec       = p.flagStatSec;
300    this->statSec           = p.statSec;
301    this->flagRobustStats   = p.flagRobustStats;
302    this->snrCut            = p.snrCut;
303    this->threshold         = p.threshold;
304    this->flagUserThreshold = p.flagUserThreshold;
305    this->flagSmooth        = p.flagSmooth;
306    this->smoothType        = p.smoothType;
307    this->hanningWidth      = p.hanningWidth;
308    this->kernMaj           = p.kernMaj;
309    this->kernMin           = p.kernMin;
310    this->kernPA            = p.kernPA;
311    this->flagATrous        = p.flagATrous;
312    this->reconDim          = p.reconDim;
313    this->scaleMin          = p.scaleMin;
314    this->scaleMax          = p.scaleMax;
315    this->snrRecon          = p.snrRecon;
316    this->reconConvergence  = p.reconConvergence;
317    this->filterCode        = p.filterCode;
318    this->reconFilter       = p.reconFilter;
319    this->flagAdjacent      = p.flagAdjacent;
320    this->threshSpatial     = p.threshSpatial;
321    this->threshVelocity    = p.threshVelocity;
322    this->minChannels       = p.minChannels;
323    this->minPix            = p.minPix;
324    this->minVoxels         = p.minVoxels;
325    this->flagRejectBeforeMerge = p.flagRejectBeforeMerge;
326    this->flagTwoStageMerging = p.flagTwoStageMerging;
327    this->spectralMethod    = p.spectralMethod;
328    this->spectralType      = p.spectralType;
329    this->restFrequency     = p.restFrequency;
330    this->restFrequencyUsed = p.restFrequencyUsed;
331    this->spectralUnits     = p.spectralUnits;
332    this->pixelCentre       = p.pixelCentre;
333    this->sortingParam      = p.sortingParam;
334    this->borders           = p.borders;
335    this->blankEdge         = p.blankEdge;
336    this->verbose           = p.verbose;
337    return *this;
338  }
339  //--------------------------------------------------------------------
340
341  OUTCOME Param::getopts(int argc, char ** argv, std::string progname)
342  {
343    ///   A function that reads in the command-line options, in a manner
344    ///    tailored for use with the main Duchamp program.
345    ///
346    ///   \param argc The number of command line arguments.
347    ///   \param argv The array of command line arguments.
348
349    OUTCOME returnValue = FAILURE;
350    if(argc==1){
351      if(progname=="Selavy") std::cout << SELAVY_ERR_USAGE_MSG;
352      else if(progname=="Duchamp") std::cout << ERR_USAGE_MSG;
353      else std::cout << ERR_USAGE_MSG;
354      returnValue = FAILURE;
355    }
356    else {
357      std::string file;
358      bool changeX = false;
359      this->defaultValues();
360      char c;
361      while( ( c = getopt(argc,argv,"p:f:hvx") )!=-1){
362        switch(c) {
363        case 'p':
364          file = optarg;
365          if(this->readParams(file)==FAILURE){
366            DUCHAMPERROR(progname,"Could not open parameter file " << file);
367          }
368          else returnValue = SUCCESS;
369          break;
370        case 'f':
371          file = optarg;
372          this->imageFile = file;
373          returnValue = SUCCESS;
374          break;
375        case 'v':
376          std::cout << PROGNAME << " version " << VERSION << std::endl;
377          break;
378        case 'x':
379          changeX = true;
380          break;
381        case 'h':
382        default :
383          if(progname=="Selavy") std::cout << SELAVY_ERR_USAGE_MSG;
384          else if(progname=="Duchamp") std::cout << ERR_USAGE_MSG;
385          else std::cout << ERR_USAGE_MSG;
386          break;
387        }
388      }
389      if(changeX){
390        if(returnValue == SUCCESS) this->setFlagXOutput(false);
391        else {
392          DUCHAMPERROR(progname, "You need to specify either a parameter file or FITS image.\n");
393          std::cout << "\n" << ERR_USAGE_MSG;
394        }
395      }
396    }
397    return returnValue;
398  }
399  //--------------------------------------------------------------------
400
401  bool Param::isBlank(float &value)
402  {
403    ///  Tests whether the value passed as the argument is BLANK or not.
404    ///  \param value Pixel value to be tested.
405    ///  \return False if flagBlankPix is false. Else, compare to the
406    ///  relevant FITS keywords, using integer comparison.
407
408    return this->flagBlankPix &&
409      (this->blankKeyword == int((value-this->bzeroKeyword)/this->bscaleKeyword));
410  }
411
412  bool *Param::makeBlankMask(float *array, size_t size)
413  {
414    ///  This returns an array of bools, saying whether each pixel in the
415    ///  given array is BLANK or not. If the pixel is BLANK, set mask to
416    ///  false, else set to true. The array is allocated by the function.
417
418    bool *mask = new bool[size];
419    for(size_t i=0;i<size;i++) mask[i] = !this->isBlank(array[i]);
420    return mask;
421  }
422
423
424  bool *Param::makeStatMask(float *array, size_t *dim)
425  {
426    ///  This returns an array of bools, saying whether each pixel in
427    ///  the given array is suitable for a stats calculation. It needs
428    ///  to be in the StatSec (if defined), not blank and not a MW
429    ///  channel. The array is allocated by the function with a 'new' call.
430
431    bool *mask = new bool[dim[0]*dim[1]*dim[2]];
432    for(size_t x=0;x<dim[0];x++) {
433      for(size_t y=0;y<dim[1];y++) {
434        for(size_t z=0;z<dim[2];z++) {
435          size_t i = x+y*dim[0]+z*dim[0]*dim[1];
436          mask[i] = !this->isBlank(array[i]) && !this->isInMW(z) && this->isStatOK(x,y,z);
437        }
438      }
439    }
440    return mask;
441  }
442
443
444  bool Param::isInMW(int z)
445  {
446    ///  Tests whether we are flagging Milky Way channels, and if so
447    /// whether the given channel number is in the Milky Way range. The
448    /// channels are assumed to start at number 0. 
449    /// \param z The channel number
450    /// \return True if we are flagging Milky Way channels and z is in
451    ///  the range.
452
453    return ( this->flagMW && (z>=this->getMinMW()) && (z<=this->getMaxMW()) );
454  }
455
456  bool Param::isStatOK(int x, int y, int z)
457  {
458    /// Test whether a given pixel position lies within the subsection
459    /// given by the statSec parameter. Only tested if the flagSubsection
460    /// parameter is true -- if it isn't, we just return true since all
461    /// pixels are therefore available for statstical calculations.
462    /// \param x X-value of pixel being tested.
463    /// \param y Y-value of pixel being tested.
464    /// \param z Z-value of pixel being tested.
465    /// \return True if pixel is able to be used for statistical
466    /// calculations. False otherwise.
467
468    int xval=x,yval=y,zval=z;
469    if(flagSubsection){
470      xval += pixelSec.getStart(0);
471      yval += pixelSec.getStart(1);
472      zval += pixelSec.getStart(2);
473    }
474    return !flagStatSec || statSec.isInside(xval,yval,zval);
475  }
476
477  std::vector<int> Param::getObjectRequest()
478  {
479    ///  Returns a list of the object numbers requested via the objectList parameter.
480    /// \return a vector of integers, one for each number in the objectList set.
481
482    std::stringstream ss1;
483    std::string tmp;
484    std::vector<int> tmplist;
485    ss1.str(this->objectList);
486    while(!ss1.eof()){
487      getline(ss1,tmp,',');
488      for(size_t i=0;i<tmp.size();i++) if(tmp[i]=='-') tmp[i]=' ';
489      int a,b;
490      std::stringstream ss2;
491      ss2.str(tmp);
492      ss2 >>a;
493      if(!ss2.eof()) ss2 >> b;
494      else b=a;
495      for(int n=a;n<=b;n++){
496        tmplist.push_back(n);
497      }     
498    }
499    return tmplist;
500  }
501
502  std::vector<bool> Param::getObjectChoices()
503  {
504    ///  Returns a list of bool values, indicating whether a given
505    ///  object was requested or not. The size of the vector is
506    ///  determined by the maximum value in objectList. For instance,
507    ///  if objectList="2,3,5-8", then the returned vector will be
508    ///  [0,1,1,0,1,1,1,1].
509    ///  \return Vector of bool values.
510
511    std::vector<int> objectChoices = this->getObjectRequest();
512    int maxNum = *std::max_element(objectChoices.begin(), objectChoices.end());
513    std::vector<bool> choices(maxNum,false);
514    for(std::vector<int>::iterator obj = objectChoices.begin();obj!=objectChoices.end();obj++)
515      choices[*obj-1] = true;
516    return choices;
517  }
518
519  std::vector<bool> Param::getObjectChoices(int numObjects)
520  {
521    ///  Returns a list of bool values, indicating whether a given
522    ///  object was requested or not. The size of the vector is given
523    ///  by the numObjects parameter. So, if objectList="2,3,5-8", then
524    ///  the returned vector from a getObjectChoices(10) call will be
525    ///  [0,1,1,0,1,1,1,1,0,0].
526    ///  \param numObjects How many objects there are in total.
527    ///  \return Vector of bool values.
528
529    if(this->objectList==""){
530      std::vector<bool> choices(numObjects,true);
531      return choices;
532    }
533    else{
534      std::vector<int> objectChoices = this->getObjectRequest();
535      std::vector<bool> choices(numObjects,false);
536      for(std::vector<int>::iterator obj = objectChoices.begin();obj!=objectChoices.end();obj++)
537        if(*obj<=numObjects) choices[*obj-1] = true;
538      return choices;
539    }
540  }
541
542  /****************************************************************/
543  /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
544  /// / Other Functions using the  Parameter class:
545  /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// /// ///
546
547  OUTCOME Param::readParams(std::string paramfile)
548  {
549    /// The parameters are read in from a disk file, on the assumption that each
550    ///  line of the file has the format "parameter value" (eg. alphafdr 0.1)
551    ///
552    /// The case of the parameter name does not matter, nor does the
553    /// formatting of the spaces (it can be any amount of whitespace or
554    /// tabs).
555    ///
556    /// \param paramfile A std::string containing the parameter filename.
557    ///
558    /// \return FAILURE if the parameter file does not exist. SUCCESS if
559    /// it is able to read it.
560
561    if(!USE_PGPLOT){
562      // Change default values for these parameters when we don't use PGPlot
563      this->flagXOutput = false;
564      this->flagMaps = false;
565      this->flagPlotSpectra = false;
566    }
567
568    std::ifstream fin(paramfile.c_str());
569    if(!fin.is_open()) return FAILURE;
570    std::string line;
571    while( !std::getline(fin,line,'\n').eof()){
572
573      if(line[0]!='#'){
574        std::stringstream ss;
575        ss.str(line);
576        std::string arg;
577        ss >> arg;
578        arg = makelower(arg);
579        if(arg=="imagefile")       this->imageFile = readFilename(ss);
580        if(arg=="flagsubsection")  this->flagSubsection = readFlag(ss);
581        if(arg=="subsection")      this->pixelSec.setSection(readSval(ss));
582        if(arg=="flagreconexists") this->flagReconExists = readFlag(ss);
583        if(arg=="reconfile")       this->reconFile = readSval(ss);
584        if(arg=="flagsmoothexists")this->flagSmoothExists = readFlag(ss);
585        if(arg=="smoothfile")      this->smoothFile = readSval(ss);
586        if(arg=="beamarea")        this->areaBeam = readFval(ss);
587        if(arg=="beamfwhm")        this->fwhmBeam = readFval(ss);
588        if(arg=="useprevious")     this->usePrevious = readFlag(ss);
589        if(arg=="objectlist")      this->objectList = readSval(ss);
590
591        if(arg=="flaglog")         this->flagLog = readFlag(ss);
592        if(arg=="logfile")         this->logFile = readSval(ss);
593        if(arg=="outfile")         this->outFile = readSval(ss);
594        if(arg=="flagseparateheader") this->flagSeparateHeader = readFlag(ss);
595        if(arg=="headerfile")      this->headerFile = readFilename(ss);
596        if(arg=="flagplotspectra") this->flagPlotSpectra = readFlag(ss);
597        if(arg=="spectrafile")     this->spectraFile = readFilename(ss);
598        if(arg=="flagtextspectra") this->flagTextSpectra = readFlag(ss);
599        if(arg=="spectratextfile") this->spectraTextFile = readFilename(ss);
600        if(arg=="flagoutputbaseline")  this->flagOutputBaseline = readFlag(ss);
601        if(arg=="fileoutputbaseline")  this->fileOutputBaseline = readFilename(ss);
602        if(arg=="flagoutputmomentmap")  this->flagOutputMomentMap = readFlag(ss);
603        if(arg=="fileoutputmomentmap")  this->fileOutputMomentMap = readFilename(ss);
604        if(arg=="flagoutputmask")  this->flagOutputMask = readFlag(ss);
605        if(arg=="fileoutputmask")  this->fileOutputMask = readFilename(ss);
606        if(arg=="flagmaskwithobjectnum") this->flagMaskWithObjectNum = readFlag(ss);
607        if(arg=="flagoutputsmooth")this->flagOutputSmooth = readFlag(ss);
608        if(arg=="fileoutputsmooth")this->fileOutputSmooth = readFilename(ss);
609        if(arg=="flagoutputrecon") this->flagOutputRecon = readFlag(ss);
610        if(arg=="fileoutputrecon") this->fileOutputRecon = readFilename(ss);
611        if(arg=="flagoutputresid") this->flagOutputResid = readFlag(ss);
612        if(arg=="fileoutputresid") this->fileOutputResid = readFilename(ss);
613        if(arg=="flagvot")         this->flagVOT = readFlag(ss);
614        if(arg=="votfile")         this->votFile = readFilename(ss);
615        if(arg=="flagkarma")       this->flagKarma = readFlag(ss);
616        if(arg=="karmafile")       this->karmaFile = readFilename(ss);
617        if(arg=="flagds9")         this->flagDS9 = readFlag(ss);
618        if(arg=="ds9file")         this->ds9File = readFilename(ss);
619        if(arg=="flagcasa")        this->flagCasa = readFlag(ss);
620        if(arg=="casafile")        this->casaFile = readFilename(ss);
621        if(arg=="annotationtype")  this->annotationType = readSval(ss);
622        if(arg=="flagmaps")        this->flagMaps = readFlag(ss);
623        if(arg=="detectionmap")    this->detectionMap = readFilename(ss);
624        if(arg=="momentmap")       this->momentMap = readFilename(ss);
625        if(arg=="flagxoutput")     this->flagXOutput = readFlag(ss);
626        if(arg=="newfluxunits")    this->newFluxUnits = readSval(ss);
627        if(arg=="precflux")        this->precFlux = readIval(ss);
628        if(arg=="precvel")         this->precVel = readIval(ss);
629        if(arg=="precsnr")         this->precSNR = readIval(ss);
630
631        if(arg=="flagtrim")        this->flagTrim = readFlag(ss);
632        if(arg=="flagmw")          this->flagMW = readFlag(ss);
633        if(arg=="maxmw")           this->maxMW = readIval(ss);
634        if(arg=="minmw")           this->minMW = readIval(ss);
635        if(arg=="flagbaseline")    this->flagBaseline = readFlag(ss);
636        if(arg=="searchtype")      this->searchType = readSval(ss);
637
638        if(arg=="flagnegative")    this->flagNegative = readFlag(ss);
639        if(arg=="minpix")          this->minPix = readIval(ss);
640        if(arg=="flaggrowth")      this->flagGrowth = readFlag(ss);
641        if(arg=="growthcut")       this->growthCut = readFval(ss);
642        if(arg=="growththreshold"){
643          this->growthThreshold = readFval(ss);
644          this->flagUserGrowthThreshold = true;
645        }
646
647        if(arg=="flagfdr")         this->flagFDR = readFlag(ss);
648        if(arg=="alphafdr")        this->alphaFDR = readFval(ss);
649        if(arg=="fdrnumcorchan")   this->FDRnumCorChan = readIval(ss);
650        if(arg=="flagstatsec")     this->flagStatSec = readFlag(ss);
651        if(arg=="statsec")         this->statSec.setSection(readSval(ss));
652        if(arg=="flagrobuststats") this->flagRobustStats = readFlag(ss);
653        if(arg=="snrcut")          this->snrCut = readFval(ss);
654        if(arg=="threshold"){
655          this->threshold = readFval(ss);
656          this->flagUserThreshold = true;
657        }
658     
659        if(arg=="flagsmooth")      this->flagSmooth = readFlag(ss);
660        if(arg=="smoothtype")      this->smoothType = readSval(ss);
661        if(arg=="hanningwidth")    this->hanningWidth = readIval(ss);
662        if(arg=="kernmaj")         this->kernMaj = readFval(ss);
663        if(arg=="kernmin")         this->kernMin = readFval(ss);
664        if(arg=="kernpa")          this->kernPA = readFval(ss);
665
666        if(arg=="flagatrous")      this->flagATrous = readFlag(ss);
667        if(arg=="recondim")        this->reconDim = readIval(ss);
668        if(arg=="scalemin")        this->scaleMin = readIval(ss);
669        if(arg=="scalemax")        this->scaleMax = readIval(ss);
670        if(arg=="snrrecon")        this->snrRecon = readFval(ss);
671        if(arg=="reconconvergence") this->reconConvergence = readFval(ss);
672        if(arg=="filtercode")      this->filterCode = readIval(ss);
673
674        if(arg=="flagadjacent")    this->flagAdjacent = readFlag(ss);
675        if(arg=="threshspatial")   this->threshSpatial = readFval(ss);
676        if(arg=="threshvelocity")  this->threshVelocity = readFval(ss);
677        if(arg=="minchannels")     this->minChannels = readIval(ss);
678        if(arg=="minvoxels")       this->minVoxels = readIval(ss);
679        if(arg=="flagrejectbeforemerge") this->flagRejectBeforeMerge = readFlag(ss);
680        if(arg=="flagtwostagemerging") this->flagTwoStageMerging = readFlag(ss);
681
682        if(arg=="spectralmethod")  this->spectralMethod=makelower(readSval(ss));
683        if(arg=="spectraltype")    this->spectralType = readSval(ss);
684        if(arg=="restfrequency")   this->restFrequency = readFval(ss);
685        if(arg=="spectralunits")   this->spectralUnits = readSval(ss);
686        if(arg=="pixelcentre")     this->pixelCentre = makelower(readSval(ss));
687        if(arg=="sortingparam")    this->sortingParam = makelower(readSval(ss));
688        if(arg=="drawborders")     this->borders = readFlag(ss);
689        if(arg=="drawblankedges")  this->blankEdge = readFlag(ss);
690        if(arg=="verbose")         this->verbose = readFlag(ss);
691
692        // Dealing with deprecated parameters.
693        if(arg=="flagblankpix"){
694          this->flagTrim = readFlag(ss);
695          DUCHAMPWARN("Reading parameters","The parameter flagBlankPix is deprecated. Please use the flagTrim parameter in future.");
696          DUCHAMPWARN("Reading parameters","Setting flagTrim = " << stringize(this->flagTrim));
697        }
698        if(arg=="blankpixvalue"){
699          DUCHAMPWARN("Reading parameters","The parameter blankPixValue is deprecated. This value is only taken from the FITS header.");
700        }
701        if(arg=="beamsize"){
702          this->areaBeam = readFval(ss);
703          DUCHAMPWARN("Reading parameters","The parameter beamSize is deprecated. You can specify the beam size by beamArea or beamFWHM.");
704          DUCHAMPWARN("Reading parameters","Setting beamArea = " << this->areaBeam);
705        }
706
707      }
708    }
709
710    this->checkPars();
711
712    return SUCCESS;
713
714  }
715 
716  void Param::checkPars()
717  {
718
719    // If flagSubsection is false, but the parset had a subsection string in it, we want to set this back to the default.
720    if(!this->flagSubsection){
721      this->pixelSec.setSection(defaultSection);
722    }
723    if(!this->flagStatSec){
724      this->statSec.setSection(defaultSection);
725    }
726
727    // If we have usePrevious=false, set the objectlist to blank so that we use all of them
728    if(!this->usePrevious) this->objectList = "";
729
730    // If pgplot was not included in the compilation, need to set flagXOutput to false
731    if(!USE_PGPLOT){
732      if(this->flagXOutput || this->flagMaps || this->flagPlotSpectra)
733        DUCHAMPWARN("Reading parameters","PGPlot has not been enabled, so setting flagXOutput, flagMaps and flagPlotSpectra to false.");
734      this->flagXOutput = false;
735      this->flagMaps = false;
736      this->flagPlotSpectra = false;
737    }
738
739    // Correcting bad precision values -- if negative, set to 0
740    if(this->precFlux<0) this->precFlux = 0;
741    if(this->precVel<0)  this->precVel = 0;
742    if(this->precSNR<0)  this->precSNR = 0;
743
744    // Can only have "spatial" or "spectral" as search types
745    if(this->searchType != "spatial" && this->searchType != "spectral"){
746      DUCHAMPWARN("Reading parameters","You have requested a search type of \""<<this->searchType<<"\" -- Only \"spectral\" and \"spatial\" are accepted, so setting to \"spatial\".");
747      this->searchType = "spatial";
748    }
749
750    // The wavelet reconstruction takes precendence over the smoothing.
751    if(this->flagATrous) this->flagSmooth = false;
752
753    // Check validity of recon parameters
754    if(this->flagATrous){
755      if(this->reconConvergence < 0.){
756        DUCHAMPWARN("Reading Parameters","Your reconConvergence value is negative ("<<this->reconConvergence<<") - setting to " << -this->reconConvergence <<".");
757        this->reconConvergence *= -1.;
758      }
759
760      this->reconFilter.define(this->filterCode);
761
762      if((this->scaleMax) > 0 && (this->scaleMax < this->scaleMin)){
763        DUCHAMPWARN("Reading Parameters","Reconstruction scaleMax ("<<this->scaleMax<<") is less than scaleMin ("<<this->scaleMin<<"): setting both to "<<this->scaleMin);
764        this->scaleMax = this->scaleMin;
765      }
766
767      if( (this->reconDim < 1) || (this->reconDim > 3) ){
768        DUCHAMPWARN("Reading Parameters", "You requested a " << this->reconDim << " dimensional reconstruction. Setting reconDim to 1");
769        this->reconDim = 1;
770      }
771
772      if( this->snrRecon < 0.){
773        DUCHAMPWARN("Reading Parameters", "Your snrRecon value is negative (" << this->snrRecon<<"). Turning reconstruction off -- fix your parameter file!");
774        this->flagATrous = false;
775      }
776
777    }
778
779    if(this->flagUserThreshold){
780
781      // If we specify a manual threshold, need to also specify a manual growth threshold
782      // If we haven't done so, turn growing off
783      if(this->flagGrowth && !this->flagUserGrowthThreshold){
784        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.");
785        DUCHAMPWARN("Reading parameters","The growth function is being turned off.");
786        this->flagGrowth = false;
787      }
788
789      // If we specify a manual threshold, we don't need the FDR method, so turn it off if requested.
790      if(this->flagFDR){
791        DUCHAMPWARN("Reading parameters","You have specified a manual search threshold, so we don't need to use the FDR method. Setting \"flagFDR=false\".");
792        this->flagFDR = false;
793      }
794
795    }   
796
797    // Make sure the growth level is less than the detection level. Else turn off growing.
798    if(this->flagGrowth){
799      std::stringstream errmsg;
800      bool doWarn = false;
801      if(this->flagUserThreshold &&
802         ( (this->threshold < this->growthThreshold)
803           || (this->snrCut < this->growthCut) ) ){
804        errmsg << "Your \"growthThreshold\" parameter" << this->growthThreshold <<" is larger than your \"threshold\"" << this->threshold;
805        doWarn = true;
806      }
807     
808      if(!this->flagUserThreshold &&
809         (this->snrCut < this->growthCut)) {
810        errmsg << "Your \"growthCut\" parameter " << this->growthCut << " is larger than your \"snrCut\"" << this->snrCut;
811        doWarn = true;
812      }
813
814      if(doWarn){
815        DUCHAMPWARN("Reading parameters",errmsg);
816        DUCHAMPWARN("Reading parameters","The growth function is being turned off.");
817
818      }
819    }
820
821    // Make sure the annnotationType is an acceptable option -- default is "borders"
822    if((this->annotationType != "borders") && (this->annotationType!="circles") && (this->annotationType!="ellipses")){
823      DUCHAMPWARN("Reading parameters","The requested value of the parameter annotationType, \"" << this->annotationType << "\", is invalid -- changing to \"borders\".");
824      this->annotationType = "borders";
825    }
826     
827    // Make sure smoothType is an acceptable type -- default is "spectral"
828    if((this->smoothType!="spectral")&&
829       (this->smoothType!="spatial")){
830      DUCHAMPWARN("Reading parameters","The requested value of the parameter smoothType, \"" << this->smoothType << "\", is invalid -- changing to \"spectral\".");
831      this->smoothType = "spectral";
832    }
833    // If kernMin has not been given, or is negative, make it equal to kernMaj
834    if(this->kernMin < 0) this->kernMin = this->kernMaj;
835
836    // Make sure spectralMethod is an acceptable type -- default is "peak"
837    if((this->spectralMethod!="peak")&&
838       (this->spectralMethod!="sum")){
839      DUCHAMPWARN("Reading parameters","The requested value of the parameter spectralMethod, \"" << this->spectralMethod << "\", is invalid -- changing to \"peak\".");
840      this->spectralMethod = "peak";
841    }
842
843    // make sure pixelCentre is an acceptable type -- default is "peak"
844    if((this->pixelCentre!="centroid")&&
845       (this->pixelCentre!="average") &&
846       (this->pixelCentre!="peak")       ){
847      DUCHAMPWARN("Reading parameters","The requested value of the parameter pixelCentre, \"" << this->pixelCentre << "\", is invalid -- changing to \"centroid\".");
848      this->pixelCentre = "centroid";
849    }
850
851    // Make sure sortingParam is an acceptable type -- default is "vel"
852    bool OK = false;
853    int loc=(this->sortingParam[0]=='-') ? 1 : 0;
854    for(int i=0;i<numSortingParamOptions;i++)
855      OK = OK || this->sortingParam.substr(loc)==sortingParamOptions[i];
856    if(!OK){
857      DUCHAMPWARN("Reading parameters","The requested value of the parameter sortingParam, \"" << this->sortingParam << "\", is invalid. -- changing to \"vel\".");
858      this->sortingParam = "vel";
859    }
860
861    // Make sure minVoxels is appropriate given minChannels & minPixels
862    if(this->minVoxels < (this->minPix + this->minChannels - 1) ){
863      DUCHAMPWARN("Reading parameters","Changing minVoxels to " << this->minPix + this->minChannels - 1 << " given minPix="<<this->minPix << " and minChannels="<<this->minChannels);
864      this->minVoxels = this->minPix + this->minChannels - 1;
865    }
866     
867  }
868
869  OUTCOME Param::checkImageExists()
870  {
871    /// A simple check to see whether the image actually exists or not, using the cfitsio interface.
872    /// If it does, we return SUCCESS, otherwise we throw an exception.
873
874    int exists,status = 0;  /* MUST initialize status */
875    fits_file_exists(this->imageFile.c_str(),&exists,&status);
876    if(exists<=0){
877      fits_report_error(stderr, status);
878      DUCHAMPTHROW("Cube Reader","Requested image " << this->imageFile << " does not exist!");
879      return FAILURE;
880    }
881    return SUCCESS;
882  }
883
884
885  void recordParameters(std::ostream& theStream, Param &par, std::string paramName, std::string paramDesc, std::string paramValue)
886  {
887   
888    const int width = 56;
889    int widthText = width - paramName.size();
890
891    theStream << par.commentString()
892              << std::setw(widthText) << paramDesc
893              << setiosflags(std::ios::right) << paramName
894              << "  =  " << resetiosflags(std::ios::right) << paramValue
895              <<std::endl;
896  }
897
898  std::string fileOption(bool flag, std::string file)
899  {
900    std::ostringstream ss;
901    ss << stringize(flag);
902    if(flag) ss << " --> " << file;
903    return ss.str();
904   
905  }
906
907  std::ostream& operator<< ( std::ostream& theStream, Param& par)
908  {
909    /// Print out the parameter set in a formatted, easy to read style.
910    /// Lists the parameters, a description of them, and their value.
911
912    // BUG -- can get error: `boolalpha' is not a member of type `ios' -- old compilers: gcc 2.95.3?
913    //   theStream.setf(std::ios::boolalpha);
914    theStream.setf(std::ios::left);
915    theStream  <<par.commentString()<<"\n"<<par.commentString()<<"---- Parameters ----"<<std::endl;
916    theStream  << std::setfill('.');
917    if(par.getFlagSubsection())
918      recordParam(theStream, par, "[imageFile]", "Image to be analysed", par.getImageFile()<<par.getSubsection());
919    else
920      recordParam(theStream, par, "[imageFile]", "Image to be analysed", par.getImageFile());
921    if(par.getFlagRestFrequencyUsed()){
922      recordParam(theStream, par, "[restFrequency]","Rest frequency as used", par.getRestFrequency());
923    }
924    if(par.getFlagReconExists() && par.getFlagATrous()){
925      recordParam(theStream, par, "[reconExists]", "Reconstructed array exists?", stringize(par.getFlagReconExists()));
926      recordParam(theStream, par, "[reconFile]", "FITS file containing reconstruction", par.getReconFile());
927    }
928    if(par.getFlagSmoothExists() && par.getFlagSmooth()){
929      recordParam(theStream, par, "[smoothExists]", "Smoothed array exists?", stringize(par.getFlagSmoothExists()));
930      recordParam(theStream, par, "[smoothFile]", "FITS file containing smoothed array", par.getSmoothFile());
931    }
932    recordParam(theStream, par, "[logFile]", "Intermediate Logfile", par.logFile);
933    recordParam(theStream, par, "[outFile]", "Final Results file", par.getOutFile());
934    if(par.getFlagSeparateHeader()){
935      recordParam(theStream, par, "[headerFile]", "Header for results file", par.getHeaderFile());
936    }
937    if(USE_PGPLOT && par.getFlagPlotSpectra()){
938      recordParam(theStream, par, "[spectraFile]", "Spectrum file", par.getSpectraFile());
939    }
940    if(par.getFlagTextSpectra()){
941      recordParam(theStream, par, "[spectraTextFile]", "Text file with ascii spectral data", par.getSpectraTextFile());
942    }
943    if(par.getFlagVOT()){
944      recordParam(theStream, par, "[votFile]", "VOTable file", par.getVOTFile());
945    }
946    if(par.getFlagKarma()){
947      recordParam(theStream, par, "[karmaFile]", "Karma annotation file" , par.getKarmaFile());
948    }
949    if(par.getFlagDS9()){
950      recordParam(theStream, par, "[ds9File]", "DS9 annotation file" , par.getDS9File());
951    }
952    if(par.getFlagCasa()){
953      recordParam(theStream, par, "[casaFile]", "CASA annotation file" , par.getCasaFile());
954    }
955    if(USE_PGPLOT && par.getFlagMaps()){
956      recordParam(theStream, par, "[momentMap]", "0th Moment Map", par.getMomentMap());
957      recordParam(theStream, par, "[detectionMap]", "Detection Map", par.getDetectionMap());
958    }
959    if(USE_PGPLOT){
960      recordParam(theStream, par, "[flagXOutput]", "Display a map in a pgplot xwindow?", stringize(par.getFlagXOutput()));
961    }
962    if(par.getFlagATrous()){
963      recordParam(theStream, par, "[flagOutputRecon]", "Saving reconstructed cube?", fileOption(par.getFlagOutputRecon(),par.outputReconFile()));
964      recordParam(theStream, par, "[flagOutputResid]", "Saving residuals from reconstruction?", fileOption(par.getFlagOutputResid(),par.outputResidFile()));
965    }                                                 
966    if(par.getFlagSmooth()){   
967      recordParam(theStream, par, "[flagOutputSmooth]", "Saving smoothed cube?", fileOption(par.getFlagOutputSmooth(),par.outputSmoothFile()));
968    }                                                 
969    recordParam(theStream, par, "[flagOutputMask]", "Saving mask cube?", fileOption(par.getFlagOutputMask(),par.outputMaskFile()));
970    recordParam(theStream, par, "[flagOutputMomentMap]", "Saving 0th moment to FITS file?", fileOption(par.getFlagOutputMomentMap(),par.outputMomentMapFile()));
971    recordParam(theStream, par, "[flagOutputBaseline]", "Saving baseline values to FITS file?", fileOption(par.getFlagOutputBaseline(),par.outputBaselineFile()));
972
973    theStream  << par.commentString() <<"------"<<std::endl;
974
975    recordParam(theStream, par, "[searchType]", "Type of searching performed", par.getSearchType());
976    if(par.getFlagBlankPix()){
977      recordParam(theStream, par, "", "Blank Pixel Value", par.getBlankPixVal());
978    }
979    recordParam(theStream, par, "[flagTrim]", "Trimming Blank Pixels?", stringize(par.getFlagTrim()));
980    recordParam(theStream, par, "[flagNegative]", "Searching for Negative features?", stringize(par.getFlagNegative()));
981    recordParam(theStream, par, "[flagMW]", "Removing Milky Way channels?", stringize(par.getFlagMW()));
982    if(par.getFlagMW()){
983      // need to remove the offset correction, as we want to report the parameters actually entered
984      recordParam(theStream, par, "[minMW - maxMW]", "Milky Way Channels", par.getMinMW()+par.getZOffset()<<"-"<<par.getMaxMW()+par.getZOffset());
985    }
986    if(par.beamAsUsed.origin()==EMPTY){  // No beam in FITS file and no information provided
987      recordParam(theStream, par, "", "Area of Beam", "No beam");
988    }
989    else if(par.beamAsUsed.origin()==HEADER){ // Report beam size from FITS file
990      recordParam(theStream, par, "", "Area of Beam (pixels)", par.beamAsUsed.area() << "   (beam: " << par.beamAsUsed.maj() << " x " << par.beamAsUsed.min() <<" pixels)");
991    }
992    else if(par.beamAsUsed.origin()==PARAM){ // Report beam size requested in parameter set input
993      if(par.fwhmBeam>0.) recordParam(theStream, par, "[beamFWHM]", "FWHM of Beam (pixels)", par.beamAsUsed.maj() << "   (beam area = " << par.beamAsUsed.area() <<" pixels)");
994      else  recordParam(theStream, par, "[beamArea]", "Area of Beam (pixels)", par.beamAsUsed.area());
995    }
996    else{
997      recordParam(theStream, par, "[beam info]", "Size & shape of beam", "No information available!");
998    }
999    recordParam(theStream, par, "[flagBaseline]", "Removing baselines before search?", stringize(par.getFlagBaseline()));
1000    recordParam(theStream, par, "[flagSmooth]", "Smoothing data prior to searching?", stringize(par.getFlagSmooth()));
1001    if(par.getFlagSmooth()){           
1002      recordParam(theStream, par, "[smoothType]", "Type of smoothing", par.getSmoothType());
1003      if(par.getSmoothType()=="spectral")
1004        recordParam(theStream, par, "[hanningWidth]", "Width of hanning filter", par.getHanningWidth());
1005      else{
1006        recordParam(theStream, par, "[kernMaj]", "Gaussian kernel semi-major axis [pix]", par.getKernMaj());
1007        recordParam(theStream, par, "[kernMin]", "Gaussian kernel semi-minor axis [pix]", par.getKernMin());
1008        recordParam(theStream, par, "[kernPA]",  "Gaussian kernel position angle [deg]",  par.getKernPA());
1009      }
1010    }
1011    recordParam(theStream, par, "[flagATrous]", "Using A Trous reconstruction?", stringize(par.getFlagATrous()));
1012    if(par.getFlagATrous()){                           
1013      recordParam(theStream, par, "[reconDim]", "Number of dimensions in reconstruction", par.getReconDim());
1014      if(par.getMaxScale()>0){
1015        recordParam(theStream, par, "[scaleMin-scaleMax]", "Scales used in reconstruction", par.getMinScale()<<"-"<<par.getMaxScale());
1016      }
1017      else{
1018        recordParam(theStream, par, "[scaleMin]", "Minimum scale in reconstruction", par.getMinScale());
1019      }
1020      recordParam(theStream, par, "[snrRecon]", "SNR Threshold within reconstruction", par.getAtrousCut());
1021      recordParam(theStream, par, "[reconConvergence]", "Residual convergence criterion", par.getReconConvergence());
1022      recordParam(theStream, par, "[filterCode]", "Filter being used for reconstruction", par.getFilterCode()<<" ("<<par.getFilterName()<<")");
1023    }                                                 
1024    recordParam(theStream, par, "[flagRobustStats]", "Using Robust statistics?", stringize(par.getFlagRobustStats()));
1025    if(par.getFlagStatSec()){
1026      recordParam(theStream, par, "[statSec]", "Section used by statistics calculation", par.statSec.getSection());
1027    }
1028    recordParam(theStream, par, "[flagFDR]", "Using FDR analysis?", stringize(par.getFlagFDR()));
1029    if(par.getFlagFDR()){                                     
1030      recordParam(theStream, par, "[alphaFDR]", "Alpha value for FDR analysis", par.getAlpha());
1031      recordParam(theStream, par, "[FDRnumCorChan]", "Number of correlated channels for FDR", par.getFDRnumCorChan());
1032    }                                                 
1033    else {
1034      if(par.getFlagUserThreshold()){
1035        recordParam(theStream, par, "[threshold]", "Detection Threshold", par.getThreshold());
1036      }
1037      else{
1038        recordParam(theStream, par, "[snrCut]", "SNR Threshold (in sigma)", par.getCut());
1039      }
1040    }
1041    recordParam(theStream, par, "[minPix]", "Minimum # Pixels in a detection", par.getMinPix());
1042    recordParam(theStream, par, "[minChannels]", "Minimum # Channels in a detection", par.getMinChannels());
1043    recordParam(theStream, par, "[minVoxels]", "Minimum # Voxels in a detection", par.getMinVoxels());
1044    recordParam(theStream, par, "[flagGrowth]", "Growing objects after detection?", stringize(par.getFlagGrowth()));
1045    if(par.getFlagGrowth()) {                         
1046      if(par.getFlagUserGrowthThreshold()){
1047        recordParam(theStream, par, "[growthThreshold]", "Threshold for growth", par.getGrowthThreshold());
1048      }
1049      else{
1050        recordParam(theStream, par, "[growthCut]", "SNR Threshold for growth", par.getGrowthCut());
1051      }
1052    }
1053    recordParam(theStream, par, "[flagAdjacent]", "Using Adjacent-pixel criterion?", stringize(par.getFlagAdjacent()));
1054    if(!par.getFlagAdjacent()){
1055      recordParam(theStream, par, "[threshSpatial]", "Max. spatial separation for merging", par.getThreshS());
1056    }
1057    recordParam(theStream, par, "[threshVelocity]", "Max. velocity separation for merging", par.getThreshV());
1058    recordParam(theStream, par, "[flagRejectBeforeMerge]", "Reject objects before merging?", stringize(par.getFlagRejectBeforeMerge()));
1059    recordParam(theStream, par, "[flagTwoStageMerging]", "Merge objects in two stages?", stringize(par.getFlagTwoStageMerging()));
1060    recordParam(theStream, par, "[spectralMethod]", "Method of spectral plotting", par.getSpectralMethod());
1061    recordParam(theStream, par, "[pixelCentre]", "Type of object centre used in results", par.getPixelCentre());
1062
1063    theStream  << par.commentString() <<"--------------------\n";
1064    theStream  << std::setfill(' ');
1065    theStream.unsetf(std::ios::left);
1066    //  theStream.unsetf(std::ios::boolalpha);
1067    return theStream;
1068  }
1069
1070  std::vector<VOParam> Param::getVOParams()
1071  {
1072    std::vector<VOParam> vopars;
1073    vopars.push_back(VOParam("imageFile","meta.file;meta.fits","char",this->imageFile,this->imageFile.size(),""));
1074    vopars.push_back(VOParam("flagSubsection","meta.code","boolean",this->flagSubsection,0,""));
1075    if(this->flagSubsection)
1076      vopars.push_back(VOParam("subsection","","char",this->pixelSec.getSection(),this->pixelSec.getSection().size(),""));
1077    vopars.push_back(VOParam("flagStatSec","meta.code","boolean",this->flagStatSec,0,""));
1078    if(this->flagSubsection)
1079      vopars.push_back(VOParam("StatSec","","char",this->statSec.getSection(),this->statSec.getSection().size(),""));
1080    if(this->flagReconExists)
1081      vopars.push_back(VOParam("reconfile","meta.file;meta.fits","char",this->reconFile, this->reconFile.size(),""));
1082    if(this->flagSmoothExists)
1083      vopars.push_back(VOParam("smoothfile","meta.file;meta.fits","char",this->smoothFile, this->smoothFile.size(),""));
1084    if(this->usePrevious)
1085      vopars.push_back(VOParam("objectlist","","char",this->objectList,this->objectList.size(),""));
1086
1087    vopars.push_back(VOParam("searchType","meta.note","char",this->searchType,this->searchType.size(),""));
1088    vopars.push_back(VOParam("flagNegative","meta.code","boolean",this->flagNegative,0,""));
1089    vopars.push_back(VOParam("flagBaseline","meta.code","boolean",this->flagBaseline,0,""));
1090    vopars.push_back(VOParam("flagRobustStats","meta.code","boolean",this->flagRobustStats,0,""));
1091    vopars.push_back(VOParam("flagFDR","meta.code","boolean",this->flagFDR,0,""));
1092    if(this->flagFDR){
1093      vopars.push_back(VOParam("alphaFDR","stat.param","float",this->alphaFDR,0,""));
1094      vopars.push_back(VOParam("FDRnumCorChan","stat.param","int",this->FDRnumCorChan,0,""));
1095    }
1096    else{
1097      if(this->flagUserThreshold)
1098            vopars.push_back(VOParam("threshold","phot.flux;stat.min","float",this->threshold,0,""));
1099      else
1100        vopars.push_back(VOParam("snrCut","stat.snr;phot;stat.min","float",this->snrCut,0,""));
1101    }
1102    vopars.push_back(VOParam("flagGrowth","meta.code","boolean",this->flagGrowth,0,""));
1103    if(this->flagGrowth){
1104      if(this->flagUserGrowthThreshold)
1105        vopars.push_back(VOParam("growthThreshold","phot.flux;stat.min","float",this->growthThreshold,0,""));
1106      else
1107        vopars.push_back(VOParam("growthCut","stat.snr;phot;stat.min","float",this->growthCut,0,""));
1108    }
1109    vopars.push_back(VOParam("minVoxels","","int",minVoxels,0,""));
1110    vopars.push_back(VOParam("minPix","","int",minPix,0,""));
1111    vopars.push_back(VOParam("minChannels","","int",minChannels,0,""));
1112    vopars.push_back(VOParam("flagAdjacent","meta.code","boolean",this->flagAdjacent,0,""));
1113    if(!this->flagAdjacent)
1114      vopars.push_back(VOParam("threshSpatial","","float",this->threshSpatial,0,""));
1115    vopars.push_back(VOParam("threshVelocity","","float",this->threshSpatial,0,""));
1116    vopars.push_back(VOParam("flagRejectBeforeMerge","","boolean",this->flagRejectBeforeMerge,0,""));
1117    vopars.push_back(VOParam("flagTwoStageMerging","","boolean",this->flagTwoStageMerging,0,""));
1118    vopars.push_back(VOParam("pixelCentre","","char",this->pixelCentre,this->pixelCentre.size(),""));
1119    vopars.push_back(VOParam("flagSmooth","meta.code","boolean",this->flagSmooth,0,""));
1120    if(this->flagSmooth){
1121      vopars.push_back(VOParam("smoothType","","char",this->smoothType,this->smoothType.size(),""));
1122      if(this->smoothType=="spectral")
1123        vopars.push_back(VOParam("hanningWidth","","int",this->hanningWidth,0,""));
1124      else{
1125        vopars.push_back(VOParam("kernMaj","","float",this->kernMaj,0,""));
1126        vopars.push_back(VOParam("kernMin","","float",this->kernMin,0,""));
1127        vopars.push_back(VOParam("kernPA","","float",this->kernPA,0,""));
1128      }
1129    }
1130    vopars.push_back(VOParam("flagATrous","meta.code","boolean",this->flagATrous,0,""));
1131    if(this->flagATrous){
1132      vopars.push_back(VOParam("reconDim","","int",this->reconDim,0,""));
1133      vopars.push_back(VOParam("scaleMin","","int",this->scaleMin,0,""));
1134      if(this->scaleMax>0)
1135        vopars.push_back(VOParam("scaleMax","","int",this->scaleMax,0,""));
1136      vopars.push_back(VOParam("snrRecon","","float",this->snrRecon,0,""));
1137      vopars.push_back(VOParam("reconConvergence","","float",this->reconConvergence,0,""));
1138      vopars.push_back(VOParam("filterCode","","int",this->filterCode,0,""));
1139    }
1140    if(this->beamAsUsed.origin()==PARAM){
1141      if(this->fwhmBeam>0)
1142        vopars.push_back(VOParam("beamFWHM","","float",this->fwhmBeam,0,""));
1143      else
1144        vopars.push_back(VOParam("beamArea","","float",this->areaBeam,0,""));
1145    }
1146    if(this->restFrequencyUsed){
1147      vopars.push_back(VOParam("restFrequency","em.freq","float",this->restFrequency,0,"Hz"));
1148    }
1149
1150    return vopars;
1151
1152  }
1153
1154
1155
1156  void Param::copyHeaderInfo(FitsHeader &head)
1157  {
1158    ///  A function to copy across relevant header keywords from the
1159    ///  FitsHeader class to the Param class, as they are needed by
1160    ///  functions in the Param class.
1161    ///  The parameters are the keywords BLANK, BSCALE, BZERO, and the beam size.
1162
1163    this->blankKeyword  = head.getBlankKeyword();
1164    this->bscaleKeyword = head.getBscaleKeyword();
1165    this->bzeroKeyword  = head.getBzeroKeyword();
1166    this->blankPixValue = this->blankKeyword * this->bscaleKeyword +
1167      this->bzeroKeyword;
1168  }
1169
1170  std::string Param::outputMaskFile()
1171  {
1172    ///  This function produces the required filename in which to save
1173    ///  the mask image, indicating which pixels have been detected as
1174    ///  part of an object. If the input image is image.fits, then the
1175    ///  output will be image.MASK.fits.
1176
1177    if(this->fileOutputMask==""){
1178      std::string inputName = this->imageFile;
1179      std::string outputName = inputName;
1180      if(inputName.substr(inputName.size()-5,5)==".fits")
1181        outputName = inputName.substr(0,inputName.size()-5); 
1182      // remove the ".fits" on the end.
1183      outputName += ".MASK.fits";
1184      return outputName;
1185    }
1186    else return this->fileOutputMask;
1187  }
1188
1189  std::string Param::outputMomentMapFile()
1190  {
1191    ///  This function produces the required filename in which to save
1192    ///  the moment-0 FITS image. If the input image is image.fits, then the
1193    ///  output will be image.MOM0.fits.
1194
1195    if(this->fileOutputMomentMap==""){
1196      std::string inputName = this->imageFile;
1197      std::string outputName = inputName;
1198      if(inputName.substr(inputName.size()-5,5)==".fits")
1199        outputName = inputName.substr(0,inputName.size()-5); 
1200      // remove the ".fits" on the end.
1201      outputName += ".MOM0.fits";
1202      return outputName;
1203    }
1204    else return this->fileOutputMomentMap;
1205  }
1206
1207  std::string Param::outputBaselineFile()
1208  {
1209    ///  This function produces the required filename in which to save
1210    ///  the baseline FITS image. If the input image is image.fits, then the
1211    ///  output will be image.BASE.fits.
1212
1213    if(this->fileOutputBaseline==""){
1214      std::string inputName = this->imageFile;
1215      std::string outputName = inputName;
1216      if(inputName.substr(inputName.size()-5,5)==".fits")
1217        outputName = inputName.substr(0,inputName.size()-5); 
1218      // remove the ".fits" on the end.
1219      outputName += ".BASE.fits";
1220      return outputName;
1221    }
1222    else return this->fileOutputBaseline;
1223  }
1224
1225  std::string Param::outputSmoothFile()
1226  {
1227    ///  This function produces the required filename in which to save
1228    ///   the smoothed array. If the input image is image.fits, then
1229    ///   the output will be:
1230    ///    <ul><li> Spectral smoothing: image.SMOOTH-1D-3.fits, where the
1231    ///             width of the Hanning filter was 3 pixels.
1232    ///        <li> Spatial smoothing : image.SMOOTH-2D-3-2-20.fits, where
1233    ///             kernMaj=3, kernMin=2 and kernPA=20 degrees.
1234    ///    </ul>
1235
1236    if(this->fileOutputSmooth==""){
1237      std::string inputName = this->imageFile;
1238      std::stringstream ss;
1239      if(inputName.substr(inputName.size()-5,5)==".fits")
1240        ss << inputName.substr(0,inputName.size()-5); 
1241      else
1242        ss << inputName;
1243      // remove the ".fits" on the end if necessary.
1244      if(this->flagSubsection) ss<<".sub";
1245      if(this->smoothType=="spectral")
1246        ss << ".SMOOTH-1D-" << this->hanningWidth << ".fits";
1247      else if(this->smoothType=="spatial")
1248        ss << ".SMOOTH-2D-"
1249           << this->kernMaj << "-"
1250           << this->kernMin << "-"
1251           << this->kernPA  << ".fits";
1252      return ss.str();
1253    }
1254    else return this->fileOutputSmooth;
1255  }
1256
1257  std::string Param::outputReconFile()
1258  {
1259    /// This function produces the required filename in which to save
1260    ///  the reconstructed array. If the input image is image.fits, then
1261    ///  the output will be eg. image.RECON-3-2-4-1.fits, where the numbers are
1262    ///  3=reconDim, 2=filterCode, 4=snrRecon, 1=minScale
1263
1264    if(this->fileOutputRecon==""){
1265      std::string inputName = this->imageFile;
1266      std::stringstream ss;
1267      // First we remove the ".fits" from the end of the filename.
1268      ss << inputName.substr(0,inputName.size()-5); 
1269      if(this->flagSubsection) ss<<".sub";
1270      ss << ".RECON-" << this->reconDim
1271         << "-"       << this->filterCode
1272         << "-"       << this->snrRecon
1273         << "-"       << this->scaleMin
1274         << "-"       << this->scaleMax
1275         << "-"       << this->reconConvergence
1276         << ".fits";
1277      return ss.str();
1278    }
1279    else return this->fileOutputRecon;
1280  }
1281
1282  std::string Param::outputResidFile()
1283  {
1284    /// This function produces the required filename in which to save
1285    ///  the reconstructed array. If the input image is image.fits, then
1286    ///  the output will be eg. image.RESID-3-2-4-1.fits, where the numbers are
1287    ///  3=reconDim, 2=filterCode, 4=snrRecon, 1=scaleMin
1288
1289    if(this->fileOutputResid==""){
1290      std::string inputName = this->imageFile;
1291      std::stringstream ss;
1292      // First we remove the ".fits" from the end of the filename.
1293      ss << inputName.substr(0,inputName.size()-5);
1294      if(this->flagSubsection) ss<<".sub";
1295      ss << ".RESID-" << this->reconDim
1296         << "-"       << this->filterCode
1297         << "-"       << this->snrRecon
1298         << "-"       << this->scaleMin
1299         << "-"       << this->scaleMax
1300         << "-"       << this->reconConvergence
1301         << ".fits";
1302      return ss.str();
1303    }
1304    else return this->fileOutputResid;
1305  }
1306
1307}
Note: See TracBrowser for help on using the repository browser.