source: trunk/src/param.cc @ 716

Last change on this file since 716 was 716, checked in by MatthewWhiting, 14 years ago

Fixing formatting for the printing of parameters, so that the larger parameter names actually fit.

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