source: trunk/src/param.cc @ 348

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