source: trunk/src/param.cc @ 793

Last change on this file since 793 was 791, checked in by MatthewWhiting, 13 years ago

Making sure it works with the redesigned needBeamSize function (ie. not using it before reading beam from file). Also removing a lot of redundant code.

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