source: tags/release-1.1.7/src/Cubes/VOTable.cc @ 1455

Last change on this file since 1455 was 536, checked in by MatthewWhiting, 15 years ago

Including the recent minor changes to 1.1.7.

File size: 15.2 KB
Line 
1// -----------------------------------------------------------------------
2// VOTable.cc: Output of the detected objects to a VOTable
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
29#include <iostream>
30#include <sstream>
31#include <fstream>
32#include <iomanip>
33#include <string>
34#include <vector>
35#include <time.h>
36#include <duchamp/Cubes/VOTable.hh>
37#include <duchamp/param.hh>
38#include <duchamp/fitsHeader.hh>
39#include <duchamp/Cubes/cubes.hh>
40#include <duchamp/Detection/detection.hh>
41#include <duchamp/Detection/columns.hh>
42 
43namespace duchamp
44{
45
46  using namespace Column;
47  std::string fixUnitsVOT(std::string oldstring)
48  {
49    ///  @details
50    /// Fix a string containing units to make it acceptable for a VOTable.
51    ///
52    /// This function makes the provided units string acceptable
53    /// according to the standard found at
54    /// http://vizier.u-strasbg.fr/doc/catstd-3.2.htx
55    /// This should then be able to convert the units used in the text
56    /// table to units suitable for putting in a VOTable.
57    ///
58    /// Specifically, it removes any square brackets [] from the
59    /// start/end of the string, and replaces blank spaces (representing
60    /// multiplication) with a '.' (full stop).
61    ///
62    /// \param oldstring Input unit string to be fixed
63    /// \return String with fixed units
64
65    std::string newstring;
66    for(uint i=0;i<oldstring.size();i++){
67      if((oldstring[i]!='[')&&(oldstring[i]!=']')){
68        if(oldstring[i]==' ') newstring += '.';
69        else newstring += oldstring[i];
70      }
71    }
72    return newstring; 
73  }
74 
75
76  void VOField::define(std::string i, std::string n, std::string U, std::string u, std::string d, std::string r, int w, int p)
77  {
78    /// @details
79    /// A basic definition function, defining each parameter individually.
80    /// \param i The ID parameter
81    /// \param n The name parameter
82    /// \param U The UCD
83    /// \param u The units (fixed by fixUnits())
84    /// \param d The datatype
85    /// \param r The ref
86    /// \param w The width
87    /// \param p The precision
88
89    this->ID = i;
90    this->name = n;
91    this->UCD = U;
92    this->unit = fixUnitsVOT(u);
93    this->datatype = d;
94    this->ref = r;
95    this->width = w;
96    this->precision = p;
97  }
98
99  void VOField::define(Column::Col column, std::string i, std::string U, std::string d, std::string r)
100  {
101    /// @details
102    /// Another definition function, using the information in a Column::Col object for some parameters.
103    /// \param column A Column::Col object, used for name, unit, width & precision
104    /// \param i The ID parameter
105    /// \param U The UCD
106    /// \param d The datatype
107    /// \param r The ref
108
109    this->ID = i;
110    this->name = column.getName();
111    this->UCD = U;
112    this->unit = fixUnitsVOT(column.getUnits());
113    this->datatype = d;
114    this->ref = r;
115    this->width = column.getWidth();
116    this->precision = column.getPrecision();
117  }
118
119  void VOField::define(Column::Col column)
120  {
121    /// @details
122    /// A more useful definition function, using the Column::COLNAME
123    /// key to specify particular values for each of the parameters for
124    /// different columns.
125    /// \param column A Column::Col object of a particular type. The
126    /// column.getType() function is used to decide which call to
127    /// VOField::define(Column::Col column, std::string i, std::string
128    /// U, std::string d, std::string r) to use
129
130    switch(column.getType())
131      {
132      case NUM:
133        this->define(column,"col01","meta.id","int","");
134        break;
135      case NAME:
136        this->define(column,"col02","meta.id;meta.main","char","");
137        break;
138      case RAJD:
139        this->define(column,"col03","","float","J2000");
140        break;
141      case DECJD:
142        this->define(column,"col04","","float","J2000");
143        break;
144      case VEL:
145        this->define(column,"col05","phys.veloc;src.dopplerVeloc","float","");
146        break;
147      case WRA:
148        this->define(column,"col06","","float","J2000");
149        break;
150      case WDEC:
151        this->define(column,"col07","","float","J2000");
152        break;
153      case W50:
154        this->define(column,"col08","phys.veloc;src.dopplerVeloc;spect.line.width","float","");
155        break;
156      case W20:
157        this->define(column,"col09","phys.veloc;src.dopplerVeloc;spect.line.width","float","");
158        break;
159      case WVEL:
160        this->define(column,"col10","phys.veloc;src.dopplerVeloc;spect.line.width","float","");
161        break;
162      case FINT:
163        this->define(column,"col11","phot.flux;spect.line.intensity","float","");
164        this->name = "Integrated_Flux";
165        break;
166      case FTOT:
167        this->define(column,"col11","phot.flux;spect.line.intensity","float","");
168        this->name = "Total_Flux";
169        break;
170      case FPEAK:
171        this->define(column,"col12","phot.flux;spect.line.intensity","float","");
172        this->name = "Peak_Flux";
173        break;
174      case SNRPEAK:
175        this->define(column,"col13","phot.flux;stat.snr","float","");
176        break;
177      case FLAG:
178        this->define(column,"col14","meta.code.qual","char","");
179        break;
180      case XAV:
181        this->define(column,"col15","pos.cartesian.x","float","");
182        break;
183      case YAV:
184        this->define(column,"col16","pos.cartesian.y","float","");
185        break;
186      case ZAV:
187        this->define(column,"col17","pos.cartesian.z","float","");
188        break;
189      case XCENT:
190        this->define(column,"col18","pos.cartesian.x","float","");
191        this->name = "X_Centroid";
192        break;
193      case YCENT:
194        this->define(column,"col19","pos.cartesian.y","float","");
195        this->name = "Y_Centroid";
196        break;
197      case ZCENT:
198        this->define(column,"col20","pos.cartesian.z","float","");
199        this->name = "Z_Centroid";
200        break;
201      case XPEAK:
202        this->define(column,"col21","pos.cartesian.x","int","");
203        break;
204      case YPEAK:
205        this->define(column,"col22","pos.cartesian.y","int","");
206        break;
207      case ZPEAK:
208        this->define(column,"col23","pos.cartesian.z","int","");
209        break;
210      default:
211        break;
212      };
213  }
214
215  void VOField::printField(std::ostream &stream)
216  {
217    /// @details
218    /// Print the Field entry with appropriate formatting.
219    /// \param stream The output stream to send the text to.
220
221    stream << "<FIELD name=\"" <<this->name
222           << "\" ID=\"" << this->ID
223           << "\" ucd=\"" << this->UCD;
224    if(this->ref!="") stream << "\" ref=\"" << this->ref;
225    stream << "\" datatype=\"" << this->datatype;
226    stream << "\" unit=\"" << this->unit;
227    if(datatype=="char")
228      stream << "\" arraysize=\"" << this->width;
229    else{
230      stream << "\" width=\"" << this->width;
231      if(datatype=="float" || datatype=="double")
232        stream << "\" precision=\"" << this->precision;
233    }
234    stream << "\"/>\n";
235
236  }
237
238
239
240  //------------------------------------------------
241
242
243  template <class T> void VOParam::define(std::string n, std::string U, std::string d, T v, int w, std::string u)
244  {
245    /// @details
246    /// A basic definition function, defining each parameter
247    /// individually. The value (v) is written to a stringstream, and
248    /// from there stored as a string.
249    /// \param n The name
250    /// \param U The UCD
251    /// \param d The datatype
252    /// \param v The value
253    /// \param w The width
254    /// \param u The units
255
256    this->name = n;
257    this->UCD = U;
258    this->datatype = d;
259    this->width = w;
260    std::stringstream ss;
261    ss << v;
262    this->value = ss.str();
263    this->units = u;
264  }
265  template void VOParam::define<int>(std::string n, std::string U, std::string d, int v, int w, std::string u);
266  template void VOParam::define<long>(std::string n, std::string U, std::string d, long v, int w, std::string u);
267  template void VOParam::define<float>(std::string n, std::string U, std::string d, float v, int w, std::string u);
268  template void VOParam::define<double>(std::string n, std::string U, std::string d, double v, int w, std::string u);
269  template void VOParam::define<std::string>(std::string n, std::string U, std::string d, std::string v, int w, std::string u);
270
271  void VOParam::printParam(std::ostream &stream)
272  {
273    /// @details
274    /// Print the Param entry with appropriate formatting.
275    /// \param stream The output stream to send the text to.
276
277    stream << "<PARAM name=\"" <<this->name
278           << "\" ucd=\"" << this->UCD
279           << "\" datatype=\"" << this->datatype;
280    if(this->units!="")
281      stream << "\" units=\"" << this->units;
282    if(this->width!=0){
283      if(datatype=="char")
284        stream << "\" arraysize=\"" << this->width;
285      else
286        stream << "\" width=\"" << this->width;
287    }
288    stream << "\" value=\"" << this->value
289           << "\"/>\n";
290  }
291
292  //------------------------------------------------
293
294
295 
296  void Cube::outputDetectionsVOTable(std::ostream &stream)
297  {
298    /// @details
299    ///  Prints to a stream (provided) the list of detected objects in the cube
300    ///   in a VOTable format.
301    ///  Uses WCS information and assumes WCS parameters have been calculated for each
302    ///   detected object.
303    /// \param stream The output stream to send the text to.
304   
305    stream<<"<?xml version=\"1.0\"?>\n";
306    stream<<"<VOTABLE version=\"1.1\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n";
307    stream<<" xsi:noNamespaceSchemaLocation=\"http://www.ivoa.net/xml/VOTable/VOTable/v1.1\">\n";
308
309    stream<<"  <COOSYS ID=\"J2000\" equinox=\"J2000.\" epoch=\"J2000.\" system=\"eq_FK5\"/>\n";
310    stream<<"  <RESOURCE name=\"Duchamp Output\">\n";
311    stream<<"    <TABLE name=\"Detections\">\n";
312    stream<<"      <DESCRIPTION>Detected sources and parameters from running the Duchamp source finder.</DESCRIPTION>\n";
313
314    // PARAM section -- parts that are not entry-specific ie. apply to whole dataset
315    std::vector<VOParam> paramList;
316    std::vector<VOParam>::iterator param;
317    VOParam singleParam;
318
319    std::string fname = this->par.getImageFile();
320    if(this->par.getFlagSubsection()) fname+=this->par.getSubsection();
321   
322    singleParam.define("FITS file","meta.file;meta.fits","char",fname,fname.size(),"");
323    paramList.push_back(singleParam);
324    if(this->par.getFlagFDR())
325      singleParam.define("FDR Significance","stat.param","float",this->par.getAlpha(),0,"");
326    else
327      singleParam.define("Threshold (SNR)","stat.snr","float",this->par.getCut(),0,"");
328    paramList.push_back(singleParam);
329    singleParam.define("Flux Threshold","phot.flux;stat.min","float",this->Stats.getThreshold(),0,this->head.getFluxUnits());
330    paramList.push_back(singleParam);
331   
332    if(this->par.getFlagATrous()){
333      std::string note = "The a trous reconstruction method was used, with the following parameters.";
334      singleParam.define("ATrous note","meta.note","char",note,note.size(),"");
335      paramList.push_back(singleParam);
336      singleParam.define("ATrous Dimension","meta.code;stat","int",this->par.getReconDim(),0,"");
337      paramList.push_back(singleParam);
338      singleParam.define("ATrous Threshold","stat.snr","float",this->par.getAtrousCut(),0,"");
339      paramList.push_back(singleParam);
340      singleParam.define("ATrous Minimum Scale","stat.param","int",this->par.getMinScale(),0,"");
341      paramList.push_back(singleParam);
342      singleParam.define("ATrous Filter","meta.code;stat","char",this->par.getFilterName(),this->par.getFilterName().size(),"");
343      paramList.push_back(singleParam);
344    }
345    if(this->par.getFlagSmooth()){
346      if(this->par.getSmoothType()=="spectral"){
347        std::string note = "The cube was smoothed spectrally with a Hanning filter, with the following parameters.";
348        singleParam.define("Smoothing note","meta.note","char",note,note.size(),"");
349        paramList.push_back(singleParam);
350        singleParam.define("Hanning filter width","meta.code;stat","int",this->par.getHanningWidth(),0,"");
351        paramList.push_back(singleParam);
352      }
353      else if(this->par.getSmoothType()=="spatial"){
354        std::string note = "The cube was smoothed spatially with a Gaussian kernel, with the following parameters.";
355        singleParam.define("Smoothing note","meta.note","char",note,note.size(),"");
356        paramList.push_back(singleParam);
357        singleParam.define("Gaussian kernel major-axis FWHM","meta.code;stat","int",this->par.getKernMaj(),0,"");
358        paramList.push_back(singleParam);
359        singleParam.define("Gaussian kernel minor-axis FWHM","meta.code;stat","int",this->par.getKernMin(),0,"");
360        paramList.push_back(singleParam);
361        singleParam.define("Gaussian kernel position angle","meta.code;stat","int",this->par.getKernPA(),0,"");
362        paramList.push_back(singleParam);
363      }   
364    }
365
366    for(param=paramList.begin();param<paramList.end();param++){
367      stream << "      ";
368      param->printParam(stream);
369    }   
370
371
372    if(this->fullCols.size()==0) this->setupColumns();
373    // in case cols haven't been set -- need the column names
374
375    std::string posUCD[4];
376    if(makelower(this->fullCols[Column::RAJD].getName())=="ra"){
377      posUCD[0] = "pos.eq.ra;meta.main";
378      posUCD[2] = "phys.angSize;pos.eq.ra";
379    }
380    else{
381      posUCD[0] = "pos.galactic.lat;meta.main";
382      posUCD[2] = "phys.angSize;pos.galactic.lat";
383    }
384    if(makelower(this->fullCols[DECJD].getName())=="dec"){
385      posUCD[1] = "pos.eq.dec;meta.main";
386      posUCD[3] = "phys.angSize;pos.eq.dec";
387    }
388    else{
389      posUCD[1] = "pos.galactic.lon;meta.main";
390      posUCD[3] = "phys.angSize;pos.galactic.lon";
391    }
392
393    std::vector<Column::Col>::iterator col;
394    for(col=this->fullCols.begin();col<this->fullCols.end();col++){
395
396      if(col->doCol("votable",this->head.isSpecOK())){
397        VOField field;
398        field.define(*col);
399        if(col->getType()==RAJD)  field.setUCD(posUCD[0]);
400        if(col->getType()==WRA)   field.setUCD(posUCD[1]);
401        if(col->getType()==DECJD) field.setUCD(posUCD[2]);
402        if(col->getType()==WDEC)  field.setUCD(posUCD[3]);     
403        stream << "      ";
404        field.printField(stream);
405      }
406
407    }
408
409    stream<<"      <DATA>\n"
410          <<"        <TABLEDATA>\n";
411
412    stream.setf(std::ios::fixed); 
413
414    std::vector<Detection>::iterator obj;
415    for(obj=this->objectList->begin();obj<this->objectList->end();obj++){
416
417      stream<<"        <TR>\n";
418      stream<<"          ";
419      std::vector<Column::Col>::iterator col;
420      for(col=this->fullCols.begin();col<this->fullCols.end();col++){
421        if(col->doCol("votable",this->head.isSpecOK())){
422          stream<<"<TD>";
423          obj->printTableEntry(stream, *col);
424          stream<<"</TD>";
425        }
426      }
427      stream<<"\n";
428      stream<<"        </TR>\n";
429
430    }
431
432    stream<<"        </TABLEDATA>\n";
433    stream<<"      </DATA>\n";
434    stream<<"    </TABLE>\n";
435    stream<<"  </RESOURCE>\n";
436    stream<<"</VOTABLE>\n";
437    resetiosflags(std::ios::fixed);
438 
439  }
440
441
442
443
444}
Note: See TracBrowser for help on using the repository browser.