source: trunk/src/param.cc @ 948

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

Second part of the solution for #146. The user can supply a spectral CTYPE and, optionally, a rest frequency, and the FITS file's ctype is translated accordingly. If the
user's rest frequency is used, it is written out with the parameter information (in both text and votable formats). A check is made to see whether the CTYPE provided is
valid.

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