source: tags/release-1.2.2/src/Cubes/detectionIO.cc

Last change on this file was 1077, checked in by MatthewWhiting, 12 years ago

Enabling the output of DS9 region files in addition to the Karma annotation files. Also adding this to the verification script. Still to do documentation.

File size: 11.6 KB
Line 
1// -----------------------------------------------------------------------
2// detectionIO.cc: Screen and File output of the detected objects.
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 <sstream>
30#include <fstream>
31#include <iomanip>
32#include <string>
33#include <vector>
34#include <time.h>
35#include <duchamp/param.hh>
36#include <duchamp/fitsHeader.hh>
37#include <duchamp/Cubes/cubes.hh>
38#include <duchamp/PixelMap/Object3D.hh>
39#include <duchamp/Detection/detection.hh>
40#include <duchamp/Outputs/columns.hh>
41#include <duchamp/Utils/utils.hh>
42#include <duchamp/Utils/Statistics.hh>
43#include <duchamp/Outputs/ASCIICatalogueWriter.hh>
44#include <duchamp/Outputs/VOTableCatalogueWriter.hh>
45#include <duchamp/Outputs/KarmaAnnotationWriter.hh>
46#include <duchamp/Outputs/DS9AnnotationWriter.hh>
47 
48using std::endl;
49using std::setw;
50using std::setprecision;
51using namespace PixelInfo;
52using namespace Statistics;
53
54namespace duchamp
55{
56
57  void Cube::outputAnnotations()
58  {
59    if(this->pars().getFlagKarma()) this->outputDetectionsKarma();
60    if(this->pars().getFlagDS9())   this->outputDetectionsDS9();
61  }
62
63  void Cube::outputDetectionsKarma()
64  {
65    KarmaAnnotationWriter writer(this->pars().getKarmaFile());
66    writer.setup(this);
67    writer.openCatalogue();
68    writer.writeHeader();
69    writer.writeParameters();
70    writer.writeStats();
71    writer.writeTableHeader();
72    writer.writeEntries();
73    writer.writeFooter();
74    writer.closeCatalogue();
75
76  }
77
78  void Cube::outputDetectionsDS9()
79  {
80    DS9AnnotationWriter writer(this->pars().getDS9File());
81    writer.setup(this);
82    writer.openCatalogue();
83    writer.writeHeader();
84    writer.writeParameters();
85    writer.writeStats();
86    writer.writeTableHeader();
87    writer.writeEntries();
88    writer.writeFooter();
89    writer.closeCatalogue();
90
91  }
92
93  void Cube::outputCatalogue()
94  {
95    this->setupColumns();
96
97    ASCIICatalogueWriter catWriter(this->par.getOutFile(),Catalogues::FILE);
98    catWriter.setup(this);
99    ASCIICatalogueWriter headerWriter(this->par.getHeaderFile(),Catalogues::FILE);
100    headerWriter.setup(this);
101    ASCIICatalogueWriter screenWriter(Catalogues::SCREEN);
102    screenWriter.setup(this);
103    ASCIICatalogueWriter *writer;
104
105    // write the header information
106    if(this->par.getFlagSeparateHeader()) writer = &headerWriter;
107    else writer=&catWriter;
108
109    writer->openCatalogue();
110    writer->writeHeader();
111    writer->writeParameters();
112    writer->writeStats();
113
114    if(this->par.getFlagSeparateHeader()){
115      writer->closeCatalogue();
116      writer = &catWriter;
117      writer->openCatalogue();
118    }
119
120    // write the catalogue
121    writer->writeTableHeader();
122    writer->writeEntries();
123    writer->closeCatalogue();
124
125    screenWriter.openCatalogue();
126    screenWriter.writeTableHeader();
127    screenWriter.writeEntries();
128    screenWriter.closeCatalogue();
129
130  }
131
132
133  void Cube::outputDetectionsVOTable()
134  {
135    VOTableCatalogueWriter writer(this->pars().getVOTFile());
136    writer.setup(this);
137    writer.setTableName("Detections");
138    writer.setTableDescription("Detected sources and parameters from running the Duchamp source finder.");
139    writer.openCatalogue();
140    writer.writeHeader();
141    writer.writeParameters();
142    writer.writeStats();
143    writer.writeTableHeader();
144    writer.writeEntries();
145    writer.writeFooter();
146    writer.closeCatalogue();
147
148  }
149
150
151  void Cube::prepareOutputFile()
152  {
153    ///  @details
154    ///  A function to write the paramters, time of execution, and
155    ///  statistical information to the output file.
156
157    std::string outfile;
158    if(this->par.getFlagSeparateHeader()) outfile = this->par.getHeaderFile();
159    else outfile = this->par.getOutFile();
160    std::ofstream output(outfile.c_str());
161    output<<"Results of the Duchamp source finder v."<<VERSION<<": ";
162    time_t now = time(NULL);
163    output << asctime( localtime(&now) );
164    this->showParam(output);
165    output<<"--------------------\n";
166    output.close();
167    this->outputStats();
168 
169  }
170
171  void Cube::outputStats()
172  {
173    ///  @details
174    ///  A function to write the statistical information to the output
175    ///  file. This writes the threshold, its equivalent S/N ratio, and
176    ///  the noise level and spread.
177    ///
178    ///  If smoothing has been done, the noise level & spread for the
179    ///  original array are calculated and printed as well.
180
181    std::string outfile;
182    if(this->par.getFlagSeparateHeader()) outfile = this->par.getHeaderFile();
183    else outfile = this->par.getOutFile();
184    std::ofstream output(outfile.c_str(),std::ios::app);
185    output<<"Summary of statistics:\n";
186    output<<"Detection threshold = " << this->Stats.getThreshold()
187          <<" " << this->head.getFluxUnits();
188    if(this->par.getFlagFDR())
189      output<<" (or S/N=" << this->Stats.getThresholdSNR()<<")";
190    if(this->par.getFlagSmooth()){
191      output << " in smoothed cube.";
192      if(!this->par.getFlagUserThreshold())
193        output<<"\nNoise level = " << this->Stats.getMiddle()
194              <<", Noise spread = " << this->Stats.getSpread()
195              <<" in smoothed cube.";
196   
197      // calculate the stats for the original array, so that we can
198      // quote S/N values correctly.
199      this->par.setFlagSmooth(false);
200      bool verb=this->par.isVerbose();
201      bool fdrflag=this->par.getFlagFDR();
202      this->par.setVerbosity(false);
203      this->par.setFlagFDR(false);
204      this->setCubeStats();
205      this->par.setVerbosity(verb);
206      this->par.setFlagFDR(fdrflag);
207      this->par.setFlagSmooth(true);
208     
209      output << "\nNoise properties for the original cube are:";
210    }
211     
212    if(!this->par.getFlagUserThreshold())
213      output<<"\nNoise level = " << this->Stats.getMiddle()
214            <<", Noise spread = " << this->Stats.getSpread();
215
216    if(this->par.getFlagGrowth()){
217      StatsContainer<float> growthStats = this->Stats;
218      if(this->par.getFlagUserGrowthThreshold())
219        growthStats.setThreshold(this->par.getGrowthThreshold());
220      else
221        growthStats.setThresholdSNR(this->par.getGrowthCut());
222      growthStats.setUseFDR(false);
223      output<<"\nDetections grown down to threshold of "
224            << growthStats.getThreshold() << " "
225            << this->head.getFluxUnits();
226    }
227
228    if(!this->par.getFlagUserThreshold())
229      output << "\nFull stats:\n" << this->Stats;
230    else
231      output << "\n\nNot calculating full stats since threshold was provided directly.\n";
232
233    output<<"--------------------\n";
234    output.close();
235  }
236
237  void Cube::prepareLogFile(int argc, char *argv[])
238  {
239    /// @details
240    ///  Opens the log file so that it can be written to, and writes
241    ///  the parameter summary as well as the time of execution to the
242    ///  file.
243    ///
244    ///  It also writes the command-line statement, hence the need for
245    ///  argv and argc.
246
247    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
248    logwriter.setup(this);
249    logwriter.openCatalogue();
250    logwriter.writeHeader();
251    logwriter.writeCommandLineEntry(argc,argv);
252    logwriter.writeParameters();
253    logwriter.closeCatalogue();
254  }
255
256
257  void Cube::logDetectionList(bool calcFluxes)
258  {
259    /// @details
260    ///  A front-end to writing a list of detected objects to the log file.
261    ///  Does not assume WCS is present.
262    ///  Designed to be used by searching routines before returning their
263    ///   final list.
264    ///  @param[in] calcFluxes If true (the default), calculate the various flux parameters for each object.
265
266    if(this->objectList->size()>0){
267
268      ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
269      logwriter.setup(this);
270      logwriter.openCatalogue(std::ios::app);
271
272      long left = this->par.getBorderLeft();
273      long bottom = this->par.getBorderBottom();
274
275      // std::ofstream fout(this->par.getLogFile().c_str(),std::ios::app);
276      if(calcFluxes) this->calcObjectFluxes();
277      this->setupColumns();
278      // outputTableHeader(fout,this->fullCols,Catalogues::LOG,this->head.isWCS());
279      logwriter.writeTableHeader();
280
281      if(this->par.getFlagBaseline()){
282        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
283          this->array[i] += this->baseline[i];
284      }
285
286      for(size_t objCtr=0;objCtr<this->objectList->size();objCtr++){
287        Detection obj = this->objectList->at(objCtr);
288        obj.setOffsets(par);
289        if(this->par.getFlagCubeTrimmed()){
290          obj.addOffsets(left,bottom,0);
291        }
292        if(calcFluxes) obj.calcFluxes(this->array, this->axisDim);
293        obj.setID(objCtr+1);
294        //      obj.printTableRow(fout,this->fullCols,Catalogues::LOG);
295        logwriter.writeEntry(&obj);
296      }
297
298      if(this->par.getFlagBaseline()){
299        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
300          this->array[i] -= this->baseline[i];
301      }
302      //      fout.close();
303      logwriter.closeCatalogue();
304 
305    }
306
307  }
308
309  void Cube::logSummary()
310  {
311    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
312    logwriter.setup(this);
313    logwriter.openCatalogue(std::ios::app);
314    logwriter.writeCubeSummary();
315    logwriter.closeCatalogue();
316  }
317
318  void Cube::writeSpectralData()
319  {
320    /// @details
321    ///  A function to write, in ascii form, the spectra of each
322    ///  detected object to a file. The file consists of a column for
323    ///  the spectral coordinates, and one column for each object
324    ///  showing the flux at that spectral position. The units are the
325    ///  same as those shown in the graphical output. The filename is
326    ///  given by the Param::spectraTextFile parameter in the Cube::par
327    ///  parameter set.
328
329    const int zdim = this->axisDim[2];
330    const int numObj = this->objectList->size();
331    float *specxOut = new float[zdim];
332    float *spectra = new float[numObj*zdim];
333   
334    for(int obj=0; obj<numObj; obj++){
335      float *temp = new float[zdim];
336      float *specx = new float[zdim];
337      float *recon = new float[zdim];
338      float *base = new float[zdim];
339      this->getSpectralArrays(obj, specx, temp, recon, base);
340      for(int z=0;z<zdim;z++) spectra[obj*zdim+z] = temp[z];
341      if(obj==0) for(int z=0;z<zdim;z++) specxOut[z] = specx[z];
342      delete [] specx;
343      delete [] recon;
344      delete [] base;
345      delete [] temp;
346    }
347   
348    std::ofstream fspec(this->par.getSpectraTextFile().c_str());
349    fspec.setf(std::ios::fixed);
350
351    for(int z=0;z<zdim;z++){
352     
353      fspec << std::setprecision(8);
354      fspec << specxOut[z] << "  ";
355      for(int obj=0;obj<numObj; obj++) {
356        fspec << spectra[obj*zdim+z] << "  ";
357      }
358      fspec << "\n";
359
360    }
361    fspec.close();
362
363    delete [] spectra;
364    delete [] specxOut;
365
366  }
367  //--------------------------------------------------------------------
368
369
370}
Note: See TracBrowser for help on using the repository browser.