source: trunk/src/param.cc @ 684

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

Changes to make the use of the new beam parameters more transparent. All seems to work fine.

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