source: trunk/src/Cubes/detectionIO.cc @ 1126

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

Enabling the output of CASA region files. These include a box (acting as a region), plus annotation lines and text in the same manner as the other annotation files. Annotations are currently not supported by casaviewer (even the new v4.0.0!!!), but the region boxes will get picked up.

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