source: tags/release-1.1.12/src/param.cc

Last change on this file was 839, checked in by MatthewWhiting, 13 years ago

Changing the default values for some parameters in the case of PGPlot not being available.

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