source: trunk/src/param.cc @ 1120

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

Ticket #170, #105 - The bulk of the work allowing this to happen. Have implemented different classes for each of the output types, including the baselines (which required new parameters etc.) Not yet implemented in mainDuchamp, so needs testing.

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