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

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

Adding a check for the detectMap existing.

File size: 15.2 KB
RevLine 
[299]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// -----------------------------------------------------------------------
[3]28#include <iostream>
29#include <sstream>
30#include <fstream>
31#include <iomanip>
32#include <string>
[258]33#include <vector>
[80]34#include <time.h>
[393]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>
[1061]40#include <duchamp/Outputs/columns.hh>
[393]41#include <duchamp/Utils/utils.hh>
42#include <duchamp/Utils/Statistics.hh>
[1049]43#include <duchamp/Outputs/ASCIICatalogueWriter.hh>
[1066]44#include <duchamp/Outputs/VOTableCatalogueWriter.hh>
[1074]45#include <duchamp/Outputs/KarmaAnnotationWriter.hh>
[1077]46#include <duchamp/Outputs/DS9AnnotationWriter.hh>
[1126]47#include <duchamp/Outputs/CasaAnnotationWriter.hh>
[103]48 
[3]49using std::endl;
50using std::setw;
51using std::setprecision;
[258]52using namespace PixelInfo;
[298]53using namespace Statistics;
[3]54
[378]55namespace duchamp
[20]56{
57
[1077]58  void Cube::outputAnnotations()
59  {
[1127]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;
[1185]72      case 2://CASA
[1127]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
[1077]92  }
93
[1074]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
[1077]109  void Cube::outputDetectionsDS9()
[378]110  {
[1077]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();
[378]121
122  }
[20]123
[1126]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
[1049]139  void Cube::outputCatalogue()
140  {
141    this->setupColumns();
142
[1061]143    ASCIICatalogueWriter catWriter(this->par.getOutFile(),Catalogues::FILE);
[1049]144    catWriter.setup(this);
[1061]145    ASCIICatalogueWriter headerWriter(this->par.getHeaderFile(),Catalogues::FILE);
[1049]146    headerWriter.setup(this);
[1061]147    ASCIICatalogueWriter screenWriter(Catalogues::SCREEN);
[1049]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;
[1055]163      writer->openCatalogue();
[1049]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
[1066]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
[378]197  void Cube::prepareOutputFile()
198  {
[528]199    ///  @details
200    ///  A function to write the paramters, time of execution, and
201    ///  statistical information to the output file.
[3]202
[378]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());
[749]207    output<<"Results of the Duchamp source finder v."<<VERSION<<": ";
[378]208    time_t now = time(NULL);
209    output << asctime( localtime(&now) );
210    this->showParam(output);
211    output<<"--------------------\n";
212    output.close();
213    this->outputStats();
[275]214 
[378]215  }
[275]216
[378]217  void Cube::outputStats()
218  {
[528]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.
[275]226
[378]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";
[385]232    output<<"Detection threshold = " << this->Stats.getThreshold()
[378]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())
[385]239        output<<"\nNoise level = " << this->Stats.getMiddle()
[378]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     
[385]255      output << "\nNoise properties for the original cube are:";
[378]256    }
257     
[275]258    if(!this->par.getFlagUserThreshold())
[385]259      output<<"\nNoise level = " << this->Stats.getMiddle()
[461]260            <<", Noise spread = " << this->Stats.getSpread();
[275]261
[378]262    if(this->par.getFlagGrowth()){
263      StatsContainer<float> growthStats = this->Stats;
[461]264      if(this->par.getFlagUserGrowthThreshold())
265        growthStats.setThreshold(this->par.getGrowthThreshold());
266      else
267        growthStats.setThresholdSNR(this->par.getGrowthCut());
[378]268      growthStats.setUseFDR(false);
[461]269      output<<"\nDetections grown down to threshold of "
270            << growthStats.getThreshold() << " "
271            << this->head.getFluxUnits();
[378]272    }
273
[422]274    if(!this->par.getFlagUserThreshold())
275      output << "\nFull stats:\n" << this->Stats;
276    else
[461]277      output << "\n\nNot calculating full stats since threshold was provided directly.\n";
[385]278
[378]279    output<<"--------------------\n";
280    output.close();
[298]281  }
282
[418]283  void Cube::prepareLogFile(int argc, char *argv[])
284  {
[528]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
[1061]293    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
[1049]294    logwriter.setup(this);
295    logwriter.openCatalogue();
296    logwriter.writeHeader();
297    logwriter.writeCommandLineEntry(argc,argv);
298    logwriter.writeParameters();
299    logwriter.closeCatalogue();
[418]300  }
301
302
[659]303  void Cube::logDetectionList(bool calcFluxes)
[378]304  {
[528]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.
[659]310    ///  @param[in] calcFluxes If true (the default), calculate the various flux parameters for each object.
[3]311
[378]312    if(this->objectList->size()>0){
[3]313
[378]314      long left = this->par.getBorderLeft();
315      long bottom = this->par.getBorderBottom();
[258]316
[659]317      if(calcFluxes) this->calcObjectFluxes();
[378]318      this->setupColumns();
[1137]319
320      ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
321      logwriter.setup(this);
322      logwriter.openCatalogue(std::ios::app);
[1049]323      logwriter.writeTableHeader();
[258]324
[378]325      if(this->par.getFlagBaseline()){
[894]326        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
[378]327          this->array[i] += this->baseline[i];
328      }
[258]329
[623]330      for(size_t objCtr=0;objCtr<this->objectList->size();objCtr++){
[577]331        Detection obj = this->objectList->at(objCtr);
[570]332        obj.setOffsets(par);
[378]333        if(this->par.getFlagCubeTrimmed()){
[570]334          obj.addOffsets(left,bottom,0);
[378]335        }
[659]336        if(calcFluxes) obj.calcFluxes(this->array, this->axisDim);
[570]337        obj.setID(objCtr+1);
[1049]338        logwriter.writeEntry(&obj);
[378]339      }
[348]340
[378]341      if(this->par.getFlagBaseline()){
[894]342        for(size_t i=0;i<this->axisDim[0]*this->axisDim[1]*this->axisDim[2];i++)
[378]343          this->array[i] -= this->baseline[i];
[348]344      }
[1137]345
[1049]346      logwriter.closeCatalogue();
[378]347 
[348]348    }
349
[3]350  }
[258]351
[1049]352  void Cube::logSummary()
353  {
[1061]354    ASCIICatalogueWriter logwriter(this->par.getLogFile(),Catalogues::LOG);
[1049]355    logwriter.setup(this);
356    logwriter.openCatalogue(std::ios::app);
357    logwriter.writeCubeSummary();
358    logwriter.closeCatalogue();
359  }
[783]360
[1146]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);
[1157]366      writeStringToBinaryFile(bincat,PACKAGE_VERSION);
[1146]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    }
[1157]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
[1146]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
[1337]429    if(this->arrayAllocated)
430        this->updateDetectMap();
[1146]431
432    return SUCCESS;
433
434  }
435
436
[783]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];
[1148]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
[783]455    float *spectra = new float[numObj*zdim];
456   
[1148]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      }
[783]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] << "  ";
[1148]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        }
[783]488      }
489      fspec << "\n";
490
491    }
492    fspec.close();
493
494    delete [] spectra;
495    delete [] specxOut;
496
497  }
498  //--------------------------------------------------------------------
499
500
[3]501}
Note: See TracBrowser for help on using the repository browser.