source: tags/release-1.6.1/src/Cubes/detectionIO.cc @ 1441

Last change on this file since 1441 was 1337, checked in by MatthewWhiting, 10 years ago

Adding a check for the detectMap existing.

File size: 15.2 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   
61    for(int i=0;i<3;i++){
62      AnnotationWriter *writer=0;
63      switch(i){
64      case 0: //Karma
65        if(this->par.getFlagKarma())
66          writer = new KarmaAnnotationWriter(this->par.getKarmaFile());
67        break;
68      case 1://DS9
69        if(this->par.getFlagDS9())
70          writer = new DS9AnnotationWriter(this->par.getDS9File());
71        break;
72      case 2://CASA
73        if(this->par.getFlagCasa())
74          writer = new CasaAnnotationWriter(this->par.getCasaFile());
75        break; 
76      }
77      if(writer!=0){
78        writer->setup(this);
79        writer->openCatalogue();
80        writer->writeHeader();
81        writer->writeParameters();
82        writer->writeStats();
83        writer->writeTableHeader();
84        writer->writeEntries();
85        writer->writeFooter();
86        writer->closeCatalogue();
87      }
88
89      delete writer;
90    }
91
92  }
93
94  void Cube::outputDetectionsKarma()
95  {
96    KarmaAnnotationWriter writer(this->pars().getKarmaFile());
97    writer.setup(this);
98    writer.openCatalogue();
99    writer.writeHeader();
100    writer.writeParameters();
101    writer.writeStats();
102    writer.writeTableHeader();
103    writer.writeEntries();
104    writer.writeFooter();
105    writer.closeCatalogue();
106
107  }
108
109  void Cube::outputDetectionsDS9()
110  {
111    DS9AnnotationWriter writer(this->pars().getDS9File());
112    writer.setup(this);
113    writer.openCatalogue();
114    writer.writeHeader();
115    writer.writeParameters();
116    writer.writeStats();
117    writer.writeTableHeader();
118    writer.writeEntries();
119    writer.writeFooter();
120    writer.closeCatalogue();
121
122  }
123
124  void Cube::outputDetectionsCasa()
125  {
126    CasaAnnotationWriter writer(this->pars().getCasaFile());
127    writer.setup(this);
128    writer.openCatalogue();
129    writer.writeHeader();
130    writer.writeParameters();
131    writer.writeStats();
132    writer.writeTableHeader();
133    writer.writeEntries();
134    writer.writeFooter();
135    writer.closeCatalogue();
136
137  }
138
139  void Cube::outputCatalogue()
140  {
141    this->setupColumns();
142
143    ASCIICatalogueWriter catWriter(this->par.getOutFile(),Catalogues::FILE);
144    catWriter.setup(this);
145    ASCIICatalogueWriter headerWriter(this->par.getHeaderFile(),Catalogues::FILE);
146    headerWriter.setup(this);
147    ASCIICatalogueWriter screenWriter(Catalogues::SCREEN);
148    screenWriter.setup(this);
149    ASCIICatalogueWriter *writer;
150
151    // write the header information
152    if(this->par.getFlagSeparateHeader()) writer = &headerWriter;
153    else writer=&catWriter;
154
155    writer->openCatalogue();
156    writer->writeHeader();
157    writer->writeParameters();
158    writer->writeStats();
159
160    if(this->par.getFlagSeparateHeader()){
161      writer->closeCatalogue();
162      writer = &catWriter;
163      writer->openCatalogue();
164    }
165
166    // write the catalogue
167    writer->writeTableHeader();
168    writer->writeEntries();
169    writer->closeCatalogue();
170
171    screenWriter.openCatalogue();
172    screenWriter.writeTableHeader();
173    screenWriter.writeEntries();
174    screenWriter.closeCatalogue();
175
176  }
177
178
179  void Cube::outputDetectionsVOTable()
180  {
181    VOTableCatalogueWriter writer(this->pars().getVOTFile());
182    writer.setup(this);
183    writer.setTableName("Detections");
184    writer.setTableDescription("Detected sources and parameters from running the Duchamp source finder.");
185    writer.openCatalogue();
186    writer.writeHeader();
187    writer.writeParameters();
188    writer.writeStats();
189    writer.writeTableHeader();
190    writer.writeEntries();
191    writer.writeFooter();
192    writer.closeCatalogue();
193
194  }
195
196
197  void Cube::prepareOutputFile()
198  {
199    ///  @details
200    ///  A function to write the paramters, time of execution, and
201    ///  statistical information to the output file.
202
203    std::string outfile;
204    if(this->par.getFlagSeparateHeader()) outfile = this->par.getHeaderFile();
205    else outfile = this->par.getOutFile();
206    std::ofstream output(outfile.c_str());
207    output<<"Results of the Duchamp source finder v."<<VERSION<<": ";
208    time_t now = time(NULL);
209    output << asctime( localtime(&now) );
210    this->showParam(output);
211    output<<"--------------------\n";
212    output.close();
213    this->outputStats();
214 
215  }
216
217  void Cube::outputStats()
218  {
219    ///  @details
220    ///  A function to write the statistical information to the output
221    ///  file. This writes the threshold, its equivalent S/N ratio, and
222    ///  the noise level and spread.
223    ///
224    ///  If smoothing has been done, the noise level & spread for the
225    ///  original array are calculated and printed as well.
226
227    std::string outfile;
228    if(this->par.getFlagSeparateHeader()) outfile = this->par.getHeaderFile();
229    else outfile = this->par.getOutFile();
230    std::ofstream output(outfile.c_str(),std::ios::app);
231    output<<"Summary of statistics:\n";
232    output<<"Detection threshold = " << this->Stats.getThreshold()
233          <<" " << this->head.getFluxUnits();
234    if(this->par.getFlagFDR())
235      output<<" (or S/N=" << this->Stats.getThresholdSNR()<<")";
236    if(this->par.getFlagSmooth()){
237      output << " in smoothed cube.";
238      if(!this->par.getFlagUserThreshold())
239        output<<"\nNoise level = " << this->Stats.getMiddle()
240              <<", Noise spread = " << this->Stats.getSpread()
241              <<" in smoothed cube.";
242   
243      // calculate the stats for the original array, so that we can
244      // quote S/N values correctly.
245      this->par.setFlagSmooth(false);
246      bool verb=this->par.isVerbose();
247      bool fdrflag=this->par.getFlagFDR();
248      this->par.setVerbosity(false);
249      this->par.setFlagFDR(false);
250      this->setCubeStats();
251      this->par.setVerbosity(verb);
252      this->par.setFlagFDR(fdrflag);
253      this->par.setFlagSmooth(true);
254     
255      output << "\nNoise properties for the original cube are:";
256    }
257     
258    if(!this->par.getFlagUserThreshold())
259      output<<"\nNoise level = " << this->Stats.getMiddle()
260            <<", Noise spread = " << this->Stats.getSpread();
261
262    if(this->par.getFlagGrowth()){
263      StatsContainer<float> growthStats = this->Stats;
264      if(this->par.getFlagUserGrowthThreshold())
265        growthStats.setThreshold(this->par.getGrowthThreshold());
266      else
267        growthStats.setThresholdSNR(this->par.getGrowthCut());
268      growthStats.setUseFDR(false);
269      output<<"\nDetections grown down to threshold of "
270            << growthStats.getThreshold() << " "
271            << this->head.getFluxUnits();
272    }
273
274    if(!this->par.getFlagUserThreshold())
275      output << "\nFull stats:\n" << this->Stats;
276    else
277      output << "\n\nNot calculating full stats since threshold was provided directly.\n";
278
279    output<<"--------------------\n";
280    output.close();
281  }
282
283  void Cube::prepareLogFile(int argc, char *argv[])
284  {
285    /// @details
286    ///  Opens the log file so that it can be written to, and writes
287    ///  the parameter summary as well as the time of execution to the
288    ///  file.
289    ///
290    ///  It also writes the command-line statement, hence the need for
291    ///  argv and argc.
292
293    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
294    logwriter.setup(this);
295    logwriter.openCatalogue();
296    logwriter.writeHeader();
297    logwriter.writeCommandLineEntry(argc,argv);
298    logwriter.writeParameters();
299    logwriter.closeCatalogue();
300  }
301
302
303  void Cube::logDetectionList(bool calcFluxes)
304  {
305    /// @details
306    ///  A front-end to writing a list of detected objects to the log file.
307    ///  Does not assume WCS is present.
308    ///  Designed to be used by searching routines before returning their
309    ///   final list.
310    ///  @param[in] calcFluxes If true (the default), calculate the various flux parameters for each object.
311
312    if(this->objectList->size()>0){
313
314      long left = this->par.getBorderLeft();
315      long bottom = this->par.getBorderBottom();
316
317      if(calcFluxes) this->calcObjectFluxes();
318      this->setupColumns();
319
320      ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
321      logwriter.setup(this);
322      logwriter.openCatalogue(std::ios::app);
323      logwriter.writeTableHeader();
324
325      if(this->par.getFlagBaseline()){
326        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
327          this->array[i] += this->baseline[i];
328      }
329
330      for(size_t objCtr=0;objCtr<this->objectList->size();objCtr++){
331        Detection obj = this->objectList->at(objCtr);
332        obj.setOffsets(par);
333        if(this->par.getFlagCubeTrimmed()){
334          obj.addOffsets(left,bottom,0);
335        }
336        if(calcFluxes) obj.calcFluxes(this->array, this->axisDim);
337        obj.setID(objCtr+1);
338        logwriter.writeEntry(&obj);
339      }
340
341      if(this->par.getFlagBaseline()){
342        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
343          this->array[i] -= this->baseline[i];
344      }
345
346      logwriter.closeCatalogue();
347 
348    }
349
350  }
351
352  void Cube::logSummary()
353  {
354    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
355    logwriter.setup(this);
356    logwriter.openCatalogue(std::ios::app);
357    logwriter.writeCubeSummary();
358    logwriter.closeCatalogue();
359  }
360
361  void Cube::writeBinaryCatalogue()
362  {
363    if(this->par.getFlagWriteBinaryCatalogue()){
364     
365      std::ofstream bincat(this->par.getBinaryCatalogue().c_str(), std::ios::out | std::ios::binary);
366      writeStringToBinaryFile(bincat,PACKAGE_VERSION);
367      time_t now = time(NULL);
368      std::string nowstr(asctime(localtime(&now)));
369      writeStringToBinaryFile(bincat,nowstr);
370      bincat.close();
371      this->par.writeToBinaryFile();
372
373      this->Stats.writeToBinaryFile(this->par.getBinaryCatalogue());
374 
375      bincat.open(this->par.getBinaryCatalogue().c_str(), std::ios::out | std::ios::binary | std::ios::app);
376      size_t numObj=this->objectList->size();
377      bincat.write(reinterpret_cast<const char*>(&numObj), sizeof numObj);
378      bincat.close();
379
380      for(size_t i=0;i<numObj;i++)
381        this->objectList->at(i).write(this->par.getBinaryCatalogue());
382
383    }
384  }
385
386  OUTCOME Cube::readBinaryCatalogue()
387  {
388    std::ifstream bincat(this->par.getBinaryCatalogue().c_str(), std::ios::in | std::ios::binary);
389    if(!bincat.is_open()){
390      DUCHAMPERROR("read binary catalogue", "Could not open binary catalogue \""<<this->par.getBinaryCatalogue()<<"\".");
391      return FAILURE;
392    }
393    std::string bincatVersion = readStringFromBinaryFile(bincat);
394    if(bincatVersion != std::string(PACKAGE_VERSION))
395        DUCHAMPWARN("read binary catalogue","Duchamp versions don't match: Binary catalogue has " << bincatVersion << " compared to " << PACKAGE_VERSION<<". Attempting to continue, but beware!");
396
397    std::string nowstr=readStringFromBinaryFile(bincat);
398    if(this->par.isVerbose()) std::cout << "  Reading from binary catalogue " << this->par.getBinaryCatalogue() << " made on " << nowstr << std::flush;
399    std::streampos loc=bincat.tellg();
400    bincat.close();
401
402    loc = this->par.readFromBinaryFile(loc);
403    if(loc<0) {
404      DUCHAMPERROR("read binary catalogue","Error reading catalogue");
405      return FAILURE;
406    }
407
408    loc=this->Stats.readFromBinaryFile(this->par.getBinaryCatalogue(),loc);
409    if(loc<0) {
410      DUCHAMPERROR("read binary catalogue","Error reading catalogue");
411      return FAILURE;
412    }
413
414    bincat.open(this->par.getBinaryCatalogue().c_str(), std::ios::in | std::ios::binary);
415    bincat.seekg(loc);
416    size_t numObj;
417    bincat.read(reinterpret_cast<char*>(&numObj), sizeof numObj);
418    loc=bincat.tellg();
419    bincat.close();
420
421    for(size_t i=0;i<numObj;i++){
422      Object3D obj;
423      loc=obj.read(this->par.getBinaryCatalogue(),loc);
424      this->objectList->push_back(obj);
425    }
426
427    if(this->par.isVerbose()) std::cout << "  Successfully read " << numObj << " objects from the binary catalogue.\n";
428
429    if(this->arrayAllocated)
430        this->updateDetectMap();
431
432    return SUCCESS;
433
434  }
435
436
437  void Cube::writeSpectralData()
438  {
439    /// @details
440    ///  A function to write, in ascii form, the spectra of each
441    ///  detected object to a file. The file consists of a column for
442    ///  the spectral coordinates, and one column for each object
443    ///  showing the flux at that spectral position. The units are the
444    ///  same as those shown in the graphical output. The filename is
445    ///  given by the Param::spectraTextFile parameter in the Cube::par
446    ///  parameter set.
447
448    const int zdim = this->axisDim[2];
449    float *specxOut = new float[zdim];
450
451    std::vector<bool> objectChoice = this->par.getObjectChoices(this->objectList->size());
452    size_t numObj = 0;
453    for(size_t i=0;i<this->objectList->size();i++) if(objectChoice[i]) numObj++;
454
455    float *spectra = new float[numObj*zdim];
456   
457    size_t obj=0;
458    for(size_t i=0;i<this->objectList->size();i++){
459      if(objectChoice[i]){
460        float *temp = new float[zdim];
461        float *specx = new float[zdim];
462        float *recon = new float[zdim];
463        float *base = new float[zdim];
464        this->getSpectralArrays(i, specx, temp, recon, base);
465        for(int z=0;z<zdim;z++) spectra[obj*zdim+z] = temp[z];
466        if(obj==0) for(int z=0;z<zdim;z++) specxOut[z] = specx[z];
467        obj++;
468        delete [] specx;
469        delete [] recon;
470        delete [] base;
471        delete [] temp;
472      }
473    }
474   
475    std::ofstream fspec(this->par.getSpectraTextFile().c_str());
476    fspec.setf(std::ios::fixed);
477
478    for(int z=0;z<zdim;z++){
479     
480      fspec << std::setprecision(8);
481      fspec << specxOut[z] << "  ";
482      obj=0;
483      for(size_t i=0;i<this->objectList->size();i++){
484        if(objectChoice[i]){
485          fspec << spectra[obj*zdim+z] << "  ";
486          obj++;
487        }
488      }
489      fspec << "\n";
490
491    }
492    fspec.close();
493
494    delete [] spectra;
495    delete [] specxOut;
496
497  }
498  //--------------------------------------------------------------------
499
500
501}
Note: See TracBrowser for help on using the repository browser.