source: tags/release-1.0.5/src/Cubes/detectionIO.cc @ 1455

Last change on this file since 1455 was 156, checked in by Matthew Whiting, 18 years ago

Improved Karma annotation file output -- now able to correctly deal with
cubes that do not have a good WCS.

File size: 14.1 KB
Line 
1#include <iostream>
2#include <sstream>
3#include <fstream>
4#include <iomanip>
5#include <string>
6#include <time.h>
7#include <Cubes/cubes.hh>
8#include <Detection/detection.hh>
9#include <Detection/columns.hh>
10#include <Utils/utils.hh>
11 
12using std::endl;
13using std::setw;
14using std::setprecision;
15using namespace Column;
16
17void Cube::outputDetectionsKarma(std::ostream &stream)
18{
19  /**
20   * outputDetectionsKarma
21   *  Prints to a stream (provided) the list of detected objects in the cube
22   *   in the format of an annotation file for the Karma suite of programs.
23   *  Annotation file draws a box enclosing the detection, and writes the
24   *   ID number of the detection to the right of the box.
25   */
26
27  string fname = this->par.getImageFile();
28  if(this->par.getFlagSubsection()) fname+=this->par.getSubsection();
29  stream << "# Duchamp Source Finder results for FITS file: " << fname << endl;
30  if(this->par.getFlagFDR())
31    stream<<"# FDR Significance = " << this->par.getAlpha() << endl;
32  else
33    stream<<"# Threshold = " << this->par.getCut() << endl;
34  if(this->par.getFlagATrous()){
35    stream<<"# The a trous reconstruction method was used, with the following parameters." << endl;
36    stream<<"#  ATrous Dimension = " << this->par.getReconDim() << endl;
37    stream<<"#  ATrous Threshold = " << this->par.getAtrousCut() << endl;
38    stream<<"#  ATrous Minimum Scale =" << this->par.getMinScale() << endl;
39    stream<<"#  ATrous Filter = " << this->par.getFilterName() << endl;
40  }
41  else stream << "# No ATrous reconstruction done." << endl;
42  stream << "#\n";
43  stream << "COLOR RED" << endl;
44  stream << "COORD W" << endl;
45  for(int i=0;i<this->objectList.size();i++){
46    if(this->head.isWCS()){
47      float radius = this->objectList[i].getRAWidth()/120.;
48      if(this->objectList[i].getDecWidth()/120.>radius)
49        radius = this->objectList[i].getDecWidth()/120.;
50      stream << "CIRCLE "
51             << this->objectList[i].getRA() << " "
52             << this->objectList[i].getDec() << " "
53             << radius << endl;
54      stream << "TEXT "
55             << this->objectList[i].getRA() << " "
56             << this->objectList[i].getDec() << " "
57             << this->objectList[i].getID() << endl;
58    }
59    else{
60      float radius = this->objectList[i].getXmax() -
61        this->objectList[i].getXmin() + 1;
62      if(this->objectList[i].getYmax()-this->objectList[i].getYmin() + 1
63         > radius)
64        radius = this->objectList[i].getYmax() -
65          this->objectList[i].getYmin() + 1;
66      stream << "CIRCLE "
67             << this->objectList[i].getXcentre() << " "
68             << this->objectList[i].getYcentre() << " "
69             << radius << endl;
70      stream << "TEXT "
71             << this->objectList[i].getXcentre() << " "
72             << this->objectList[i].getYcentre() << " "
73             << this->objectList[i].getID() << endl;
74    }
75  }     
76
77}
78
79void Cube::outputDetectionsVOTable(std::ostream &stream)
80{
81  /**
82   * outputDetectionsVOTable
83   *  Prints to a stream (provided) the list of detected objects in the cube
84   *   in a VOTable format.
85   *  Uses WCS information and assumes WCS parameters have been calculated for each
86   *   detected object.
87   *  If they have not (given by the isWCS() function), then those objects are not written...
88   */
89
90  // Set up Column definitions here
91  vector<Col> localCol;
92  string posUCD[4];
93  localCol.push_back(this->fullCols[NUM]);  // objID
94  localCol.push_back(this->fullCols[NAME]);  // name
95  localCol.push_back(this->fullCols[RA]);  // ra
96  if(makelower(localCol[2].getName())=="ra"){
97    posUCD[0] = "pos.eq.ra;meta.main";
98    posUCD[2] = "phys.angSize;pos.eq.ra";
99  }
100  else{
101    posUCD[0] = "pos.galactic.lat;meta.main";
102    posUCD[2] = "phys.angSize;pos.galactic.lat";
103  }
104  localCol.push_back(this->fullCols[DEC]);  // dec
105  if(makelower(localCol[2].getName())=="dec"){
106    posUCD[1] = "pos.eq.dec;meta.main";
107    posUCD[3] = "phys.angSize;pos.eq.dec";
108  }
109  else{
110    posUCD[1] = "pos.galactic.lon;meta.main";
111    posUCD[3] = "phys.angSize;pos.galactic.lon";
112  }
113  localCol.push_back(this->fullCols[WRA]);  // w_ra
114  localCol.push_back(this->fullCols[WDEC]);  // w_dec
115  localCol.push_back(this->fullCols[VEL]);  // vel
116  localCol.push_back(this->fullCols[WVEL]); // w_vel
117  localCol.push_back(this->fullCols[FINT]); // f_int
118  localCol.push_back(this->fullCols[FPEAK]); // f_peak
119  localCol.push_back(this->fullCols[FLAG]); // flag
120
121  stream<<"<?xml version=\"1.0\"?>"<<endl;
122  stream<<"<VOTABLE version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""<<endl;
123  stream<<" xsi:noNamespaceSchemaLocation=\"http://www.ivoa.net/xml/VOTable/VOTable/v1.1\">"<<endl;
124
125  stream<<"  <COOSYS ID=\"J2000\" equinox=\"J2000.\" epoch=\"J2000.\" system=\"eq_FK5\"/>"<<endl;
126  stream<<"  <RESOURCE name=\"Duchamp Output\">"<<endl;
127  stream<<"    <TABLE name=\"Detections\">"<<endl;
128  stream<<"      <DESCRIPTION>Detected sources and parameters from running the Duchamp source finder.</DESCRIPTION>"<<endl;
129
130  // PARAM section -- parts that are not entry-specific ie. apply to whole dataset
131  string fname = this->par.getImageFile();
132  if(this->par.getFlagSubsection()) fname+=this->par.getSubsection();
133  stream<<"      <PARAM name=\"FITS file\" datatype=\"char\" ucd=\"meta.file;meta.fits\" value=\"" << fname << "\"/>"<<endl;
134  if(this->par.getFlagFDR())
135    stream<<"      <PARAM name=\"FDR Significance\" datatype=\"float\" ucd=\"stat.param\" value=\"" << this->par.getAlpha() << "\">" << endl;
136  else
137    stream<<"      <PARAM name=\"Threshold\" datatype=\"float\" ucd=\"stat.snr\" value=\"" << this->par.getCut() << "\">" << endl;
138  if(this->par.getFlagATrous()){
139    stream<<"      <PARAM name=\"ATrous note\" datatype=\"char\" ucd=\"meta.note\" value=\"The a trous reconstruction method was used, with the following parameters.\">" << endl;
140    stream<<"      <PARAM name=\"ATrous Dimension\" datatype=\"int\" ucd=\"meta.code;stat\" value=\"" << this->par.getReconDim() << "\">" << endl;
141    stream<<"      <PARAM name=\"ATrous Threshold\" datatype=\"float\" ucd=\"stat.snr\" value=\"" << this->par.getAtrousCut() << "\">" << endl;
142    stream<<"      <PARAM name=\"ATrous Minimum Scale\" datatype=\"int\" ucd=\"stat.param\" value=\"" << this->par.getMinScale() << "\">" << endl;
143    stream<<"      <PARAM name=\"ATrous Filter\" datatype=\"char\" ucd=\"meta.code;stat\" value=\"" << this->par.getFilterName() << "\">" << endl;
144  }
145  // FIELD section -- names, titles and info for each column.
146  stream<<"      <FIELD name=\"ID\" ID=\"col01\" ucd=\"meta.id\" datatype=\"int\" width=\""<<localCol[0].getWidth()<<"\"/>"<<endl;
147  stream<<"      <FIELD name=\"Name\" ID=\"col02\" ucd=\"meta.id;meta.main\" datatype=\"char\" arraysize=\""<<localCol[1].getWidth()<<"\"/>"<<endl;
148  stream<<"      <FIELD name=\""<<localCol[2].getName()<<"\" ID=\"col03\" ucd=\""<<posUCD[0]<<"\" ref=\"J2000\" datatype=\"float\" width=\""<<localCol[2].getWidth()<<"\" precision=\""<<prec[prPOS]<<"\" unit=\"[deg]\"/>"<<endl;
149  stream<<"      <FIELD name=\""<<localCol[3].getName()<<"\" ID=\"col04\" ucd=\""<<posUCD[1]<<"\" ref=\"J2000\" datatype=\"float\" width=\""<<localCol[3].getWidth()<<"\" precision=\""<<prec[prPOS]<<"\" unit=\"[deg]\"/>"<<endl;
150  stream<<"      <FIELD name=\""<<localCol[4].getName()<<"\" ID=\"col05\" ucd=\""<<posUCD[2]<<"\" ref=\"J2000\" datatype=\"float\" width=\""<<localCol[4].getWidth()<<"\" precision=\""<<prec[prWPOS]<<"\" unit=\""<<localCol[4].getUnits()<<"\"/>"<<endl;
151  stream<<"      <FIELD name=\""<<localCol[5].getName()<<"\" ID=\"col06\" ucd=\""<<posUCD[2]<<"\" ref=\"J2000\" datatype=\"float\" width=\""<<localCol[5].getWidth()<<"\" precision=\""<<prec[prWPOS]<<"\" unit=\""<<localCol[5].getUnits()<<"\"/>"<<endl;
152  stream<<"      <FIELD name=\"Vel\" ID=\"col07\" ucd=\"phys.veloc;src.dopplerVeloc\" datatype=\"float\" width=\""<<localCol[6].getWidth()<<"\" precision=\""<<prec[prVEL]<<"\" unit=\""<<localCol[6].getUnits()<<"\"/>"<<endl;
153  stream<<"      <FIELD name=\"w_Vel\" ID=\"col08\" ucd=\"phys.veloc;src.dopplerVeloc;spect.line.width\" datatype=\"float\" width=\""<<localCol[7].getWidth()<<"\" precision=\""<<prec[prVEL]<<"\" unit=\""<<localCol[7].getUnits()<<"\"/>"<<endl;
154  stream<<"      <FIELD name=\"Integrated_Flux\" ID=\"col09\" ucd=\"phot.flux;spect.line.intensity\" datatype=\"float\" width=\""<<localCol[8].getWidth()<<"\" precision=\""<<prec[prFLUX]<<"\" unit=\""<<localCol[8].getUnits()<<"\"/>"<<endl;
155  stream<<"      <FIELD name=\"Peak_Flux\" ID=\"col10\" ucd=\"phot.flux;spect.line.intensity\" datatype=\"float\" width=\""<<localCol[9].getWidth()<<"\" precision=\""<<prec[prFLUX]<<"\" unit=\""<<localCol[9].getUnits()<<"\"/>"<<endl;
156  stream<<"      <FIELD name=\"Flag\" ID=\"col11\" ucd=\"meta.code.qual\" datatype=\"char\" arraysize=\"3\"/>"<<endl;
157
158
159  stream<<"      <DATA>"<<endl
160        <<"        <TABLEDATA>"<<endl;
161
162  stream.setf(std::ios::fixed); 
163  for(int i=0;i<this->objectList.size();i++){
164    if(this->objectList[i].isWCS()){
165      stream<<"        <TR>"<<endl;
166      stream<<"          <TD>"<<setw(localCol[0].getWidth())<<i+1<<"</TD>";
167      stream<<"<TD>" << setw(localCol[1].getWidth()) << this->objectList[i].getName()       <<"</TD>";
168      stream<<setprecision(prec[prPOS]);
169      stream<<"<TD>" << setw(localCol[2].getWidth()) << this->objectList[i].getRA()         <<"</TD>";
170      stream<<"<TD>" << setw(localCol[3].getWidth()) << this->objectList[i].getDec()        <<"</TD>";
171      stream<<setprecision(prec[prWPOS]);
172      stream<<"<TD>" << setw(localCol[4].getWidth()) << this->objectList[i].getRAWidth()    <<"</TD>";
173      stream<<"<TD>" << setw(localCol[5].getWidth()) << this->objectList[i].getDecWidth()   <<"</TD>";
174      stream<<setprecision(prec[prVEL]);
175      stream<<"<TD>" << setw(localCol[6].getWidth()) << this->objectList[i].getVel()        <<"</TD>";
176      stream<<"<TD>" << setw(localCol[7].getWidth()) << this->objectList[i].getVelWidth()   <<"</TD>";
177      stream<<setprecision(prec[prFLUX]);
178      stream<<"<TD>" << setw(localCol[8].getWidth()) << this->objectList[i].getIntegFlux()  <<"</TD>";
179      stream<<"<TD>" << setw(localCol[9].getWidth()) << this->objectList[i].getPeakFlux()   <<"</TD>";
180      stream<<"<TD>" << setw(localCol[10].getWidth())<< this->objectList[i].getFlagText()   <<"</TD>";
181     
182      stream<<endl;
183      stream<<"        </TR>"<<endl;
184    }
185  }
186  stream<<"        </TABLEDATA>"<<endl;
187  stream<<"      </DATA>"<<endl;
188  stream<<"    </TABLE>"<<endl;
189  stream<<"  </RESOURCE>"<<endl;
190  stream<<"</VOTABLE>"<<endl;
191  resetiosflags(std::ios::fixed);
192 
193}
194
195
196void Cube::outputDetectionList()
197{
198  /**
199   * outputDetectionList
200   *  A front-end to writing the full list of detected objects to a results
201   *   file and to cout.
202   *  Uses outputDetectionTextWCS for each objects.
203   *  Leaves the testing of whether the WCS parameters for each object
204   *   have been calculated to outputDetectionTextWCS.
205   */
206
207  int count=0;
208  int flag;
209  std::ofstream output(this->par.getOutFile().c_str());
210  output<<"Results of the Duchamp source finder: ";
211  time_t now = time(NULL);
212  output << asctime( localtime(&now) );
213  this->showParam(output);
214  output<<"Total number of detections = "<<this->objectList.size()<<endl;
215  output<<"--------------------"<<endl;
216  this->setupColumns();
217  this->objectList[0].outputDetectionTextHeader(output,this->fullCols);
218  this->objectList[0].outputDetectionTextHeader(std::cout,this->fullCols);
219  for(int i=0;i<this->objectList.size();i++){
220    this->objectList[i].outputDetectionTextWCS(output,this->fullCols);
221    this->objectList[i].outputDetectionTextWCS(std::cout,this->fullCols);
222  }
223}
224
225void Cube::logDetectionList()
226{
227  /**
228   * logDetectionList
229   *  A front-end to writing a list of detected objects to the log file.
230   *  Does not assume WCS, so uses outputDetectionText.
231   *  Designed to be used by searching routines before returning their final list.
232   */
233
234  std::ofstream fout(this->par.getLogFile().c_str(),std::ios::app);
235  this->setupColumns();
236  this->objectList[0].outputDetectionTextHeader(fout,this->logCols);
237  long pos;
238  bool baselineFlag = this->par.getFlagBaseline();
239  for(int objCtr=0;objCtr<this->objectList.size();objCtr++){
240    Detection *obj = new Detection;
241    *obj = objectList[objCtr];
242    if(this->par.getFlagCubeTrimmed()){
243      for(int pix=0;pix<obj->getSize();pix++){
244        // Need to correct the pixels first, as this hasn't been done yet.
245        // Corrections needed for positions (to account for trimmed region)
246        //  and for the baseline removal, if it has happened.
247        // Don't want to keep these changes, so just do it on a dummy variable.
248        pos = obj->getX(pix) + obj->getY(pix)*this->axisDim[0]
249          + obj->getZ(pix)*this->axisDim[0]*this->axisDim[1];
250        obj->setX(pix, obj->getX(pix) + this->par.getBorderLeft() );
251        obj->setY(pix, obj->getY(pix) + this->par.getBorderBottom() );
252        if(baselineFlag) obj->setF(pix, obj->getF(pix) + this->baseline[pos]);   // add in baseline
253      }
254      obj->calcParams();
255    }
256    obj->outputDetectionText(fout,this->logCols,objCtr+1);
257    delete obj;
258  }
259  fout.close();
260}
261
262void Cube::logDetection(Detection obj, int counter)
263{
264  /**
265   * logDetection
266   *  A front-end to writing a detected object to the log file.
267   *  Does not assume WCS, so uses outputDetectionText.
268   *  obj is passed by value, as we want to potentially change positions etc, but not for
269   *  object in the calling function.
270   *  Corrects for changes to positions of pixels and removal of baselines.
271   *  Designed to be used by searching routines before returning their final list.
272   */
273
274  std::ofstream fout(this->par.getLogFile().c_str(),std::ios::app);
275  bool baselineFlag = this->par.getFlagBaseline();
276  if(this->par.getFlagCubeTrimmed()){
277    for(int pix=0;pix<obj.getSize();pix++){
278      // Need to correct the pixels first, as this hasn't been done yet.
279      // Corrections needed for positions (to account for trimmed region)
280      //  and for the baseline removal, if it has happened.
281      // Don't want to keep these changes, so just do it on a dummy variable.
282      long pos = obj.getX(pix) + obj.getY(pix)*this->axisDim[0]
283        + obj.getZ(pix)*this->axisDim[0]*this->axisDim[1];
284      obj.setX(pix, obj.getX(pix) + this->par.getBorderLeft() );
285      obj.setY(pix, obj.getY(pix) + this->par.getBorderBottom() );
286      if(baselineFlag) obj.setF(pix, obj.getF(pix) + this->baseline[pos]);   // add in baseline
287    }
288    obj.calcParams();
289  }
290  obj.outputDetectionText(fout,this->logCols,counter);
291  fout.close();
292}
Note: See TracBrowser for help on using the repository browser.