source: tags/release-1.1.5/src/Cubes/VOTable.cc @ 1391

Last change on this file since 1391 was 441, checked in by MatthewWhiting, 16 years ago

Cleaning up, and commenting.

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