source: trunk/src/param.cc @ 1077

Last change on this file since 1077 was 1077, checked in by MatthewWhiting, 12 years ago

Enabling the output of DS9 region files in addition to the Karma annotation files. Also adding this to the verification script. Still to do documentation.

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