source: trunk/src/param.cc @ 438

Last change on this file since 438 was 438, checked in by MatthewWhiting, 16 years ago

Enabled the user to specify desired decimal precisions for the flux, velocity and SNR columns via new input parameters precFlux, precVel and precSNR (ticket #34).

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