source: trunk/src/Outputs/columns.cc

Last change on this file was 1426, checked in by MatthewWhiting, 7 years ago

Applying a patch from ASKAPsoft development. This adds options to the
checkWidth functions that allow us to check or not the ASCII header.
This can help us avoid unnecessarily widening columns in the VOTable
case. Also remove the individual check calls and replace with a call
to checkAll from the catalogue specification.
ASKAPSDP revision r8915

File size: 19.3 KB
RevLine 
[300]1// -----------------------------------------------------------------------
2// columns.cc: Define a set of columns for Duchamp output.
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// -----------------------------------------------------------------------
[144]28#include <iostream>
29#include <sstream>
30
[155]31#include <math.h>
[393]32#include <duchamp/duchamp.hh>
33#include <duchamp/fitsHeader.hh>
[93]34#include <vector>
35#include <string>
[393]36#include <duchamp/Detection/detection.hh>
[1061]37#include <duchamp/Outputs/columns.hh>
[93]38
[378]39namespace duchamp
[232]40{
[221]41
[1061]42  namespace Catalogues
[272]43  {
[221]44
[439]45
[1061]46    Column::Column()
[378]47    {
[528]48      /// @brief Set the default values for the parameters.
[1061]49      this->itsWidth=1;
50      this->itsPrecision=0;
51      this->itsName=" ";
52      this->itsUnits=" ";
53      this->itsType="";
54      this->itsUCD = "";
55      this->itsDatatype = "";
56      this->itsExtraInfo="";
57      this->itsColID="";
[419]58    }
[232]59
[1061]60    Column::Column(std::string type)
61    {
62      operator=(defaultColumn(type));
63    }
[365]64
[1061]65    Column::Column(const Column& c)
[378]66    {
67      operator=(c);
68    }
[365]69
[1061]70    Column& Column::operator=(const Column& c)
[378]71    {
72      if(this==&c) return *this;
[1061]73      this->itsWidth = c.itsWidth;
74      this->itsPrecision = c.itsPrecision;
75      this->itsName = c.itsName;
76      this->itsUnits = c.itsUnits;
77      this->itsUCD = c.itsUCD;
78      this->itsDatatype = c.itsDatatype;
79      this->itsExtraInfo = c.itsExtraInfo;
80      this->itsColID = c.itsColID;
81      this->itsType = c.itsType;
[378]82      return *this;
[232]83    }
[378]84
[1064]85    Column::Column(std::string type, std::string name, std::string units, int width, int prec, std::string ucd, std::string datatype, std::string colID, std::string extraInfo):
[1067]86      itsType(type), itsName(name), itsUnits(units), itsWidth(width), itsPrecision(prec), itsUCD(ucd), itsDatatype(datatype), itsColID(colID), itsExtraInfo(extraInfo)
[540]87    {
88      /// A generic constructor designed to make a Column other than
89      /// the predefined ones listed in the Column namespace
90      /// \param name The title of the column
91      /// \param units What units the column takes
92      /// \param width The starting width
93      /// \param prec The starting precision
[1066]94      /// \param ucd The UCD relating to the quantity (VOTable use only)
95      /// \param datatype The datatype (float/char/int/etc) of the quantity (VOTable)
96      /// \param colID The column ID string used in the FIELD entry of a VOTable
97      /// \param extraInfo Other information used in the VOTable (eg. a reference to a COOSYS)
[1061]98   }
[540]99
[378]100    //------------------------------------------------------------
[540]101
[1061]102    void Column::changePrec(int p)
[540]103    {
104      /// A direct way to alter the precision without having to use
[1061]105      /// Column::upPrec(). If the precision increases, the width will
[540]106      /// increase by the same amount. If it decreases, no change is
107      /// made to the width.
108      /// \param p The new precision value.
109
[1061]110      if(p > this->itsPrecision) this->itsWidth += (p-this->itsPrecision);
111      this->itsPrecision = p;
[540]112
113    }
[1217]114
115      void Column::checkPrec(double val)
116      {
117          /// Checks a decimal value to see if it is in -1<val<1. If
118          /// so, we need sufficient precision to represent at least
119          /// one significant figure.
120          if((fabs(val)<1.)){
121              int impliedPrec = int(fabs(log10(val))+1);
122              for(int i=this->itsPrecision;i<=impliedPrec;i++) this->upPrec();
123          }
124      }
125
[1426]126      void Column::checkWidth(int width, bool checkHeader)
[1217]127      {
128          /// Three checks on the width, looking at the name, the
129          /// units string, and then some minimum width. This can be
130          /// obtained from the other check() functions that work
131          /// from various value types.
[1426]132          /// If checkHeader=false, then we only look at the width of the value.
[1217]133
134          for(int i=this->itsWidth;i<=width;i++) this->widen();// +1 for the space
[1426]135          if (checkHeader) {
136              for(int i=this->itsWidth;i<=int(this->itsName.size());i++) this->widen();  // +1 for the space
137              for(int i=this->itsWidth;i<=int(this->itsUnits.size());i++) this->widen(); // +1 for the space
138          }
139         
[1217]140      }
141
[540]142    //------------------------------------------------------------
[1061]143    void Column::printTitle(std::ostream &stream)
[378]144    {
[1061]145      stream << std::setw(this->itsWidth)
[378]146             << std::setfill(' ')
[1061]147             << this->itsName;
[378]148    }
[93]149
[1061]150    void Column::printUnits(std::ostream &stream)
[378]151    {
[1061]152      stream << std::setw(this->itsWidth)
[378]153             << std::setfill(' ')
[1061]154             << this->itsUnits;
[378]155    }
[272]156 
[1061]157    void Column::printDash (std::ostream &stream)
[378]158    {
[1061]159      stream << std::setw(this->itsWidth)
[378]160             << std::setfill('-')
161             << ""
162             << std::setfill(' ');
163    }
[232]164
[1061]165    void Column::printBlank(std::ostream &stream)
[378]166    {
[1061]167      stream << std::setw(this->itsWidth)
[378]168             << std::setfill(' ')
169             << "";
170    }
[272]171 
[1061]172    template <class T> void Column::printEntry(std::ostream &stream, T value)
[378]173    {
[528]174      ///  \param stream Where the printing is done.
175      ///  \param value  The value to be printed.
176
[1061]177      stream << std::setprecision(this->itsPrecision)
178             << std::setw(this->itsWidth)
[378]179             << std::setfill(' ')
180             << value;
181    }
[1061]182    template void Column::printEntry<int>(std::ostream &stream, int value);
183    template void Column::printEntry<long>(std::ostream &stream, long value);
184    template void Column::printEntry<unsigned int>(std::ostream &stream, unsigned int value);
185    template void Column::printEntry<unsigned long>(std::ostream &stream, unsigned long value);
186    template void Column::printEntry<float>(std::ostream &stream, float value);
187    template void Column::printEntry<double>(std::ostream &stream, double value);
188    template void Column::printEntry<std::string>(std::ostream &stream, std::string value);
[272]189
[440]190 
[1061]191    bool Column::doCol(DESTINATION tableType, bool flagFint)
[440]192    {
[1066]193      ///  @details Determines whether a given column is used for a
194      ///  given table type, based on the Column::type string.
[1047]195      /// \param tableType The type of table: one of FILE, SCREEN, LOG, VOTABLE.
[528]196      /// \param flagFint Whether to use FINT (true) or FTOT
197      /// (false). This defaults to true, so need not be given. It only
198      /// applies to the screen and votable cases -- both are written for the
199      /// results file case.
200      /// \return True if column is used for given table type. False
201      /// otherwise. False if tableType not one of four listed.
[440]202     
[1066]203 
[1273]204      const size_t sizeFileList=43;
205      std::string FileList[sizeFileList]={"NUM","NAME","X","Y","Z","RA","DEC","RAJD","DECJD","VEL","MAJ","MIN","PA","WRA","WDEC",
206                                          "W50","W20","WVEL","FINT","FINTERR","FTOT","FTOTERR","FPEAK","SNRPEAK",
207                                          "X1","X2","Y1","Y2","Z1","Z2","NVOX","NUMCH","SPATSIZE","FLAG","XAV","YAV",
[1192]208                                          "ZAV","XCENT","YCENT","ZCENT","XPEAK","YPEAK","ZPEAK"};
[1273]209      const size_t sizeScreenList=24;
[1192]210      std::string ScreenList[sizeScreenList]={"NUM","NAME","X","Y","Z","RA","DEC","VEL","MAJ","MIN","PA",
211                                              "W50","FPEAK","SNRPEAK","X1","X2","Y1",
[1273]212                                              "Y2","Z1","Z2","NVOX","NUMCH","SPATSIZE","FLAG"};
[1192]213      const size_t sizeLogList=16;
214      std::string LogList[sizeLogList]={"NUM","X","Y","Z","FTOT","FPEAK","SNRPEAK",
[1273]215                                        "X1","X2","Y1","Y2","Z1","Z2","NVOX","NUMCH","SPATSIZE"};
216      // const size_t sizeVOList=23;
217      // std::string VOList[sizeVOList]={"NUM","NAME","RAJD","DECJD","VEL","MAJ","MIN","PA",
218      //                                      "W50","W20","WVEL","FPEAK","SNRPEAK","FLAG","XAV","YAV",
219      //                                      "ZAV","XCENT","YCENT","ZCENT","XPEAK","YPEAK","ZPEAK"};
[1061]220
221      bool doIt=false;
222      if(tableType == FILE){
[1192]223        for(size_t i=0;i<sizeFileList && !doIt;i++) doIt = doIt || (this->itsType==FileList[i]);
[1061]224      }
[1047]225      else if(tableType == SCREEN){
[1061]226        if(this->itsType=="FTOT") doIt = !flagFint;
227        else if(this->itsType == "FINT") doIt = flagFint;
[1192]228        else for(size_t i=0;i<sizeScreenList && !doIt;i++) doIt = doIt || (this->itsType==ScreenList[i]);
[440]229      }
[1061]230      else if(tableType == LOG){
[1192]231        for(size_t i=0;i<sizeLogList && !doIt;i++) doIt = doIt || (this->itsType==LogList[i]);
[1061]232      }
[1047]233      else if(tableType == VOTABLE){
[1153]234        if(this->itsType=="FTOT" || this->itsType=="FTOTERR") doIt = !flagFint;
235        else if(this->itsType == "FINT" || this->itsType=="FINTERR") doIt = flagFint;
[1273]236        // else for(size_t i=0;i<sizeVOList && !doIt;i++) doIt = doIt || (this->itsType==VOList[i]);
237        else{
238            for(size_t i=0;i<sizeFileList && !doIt;i++){
239                if(FileList[i]!="RA" && FileList[i]!="DEC")
240                    doIt = doIt || (this->itsType==FileList[i]);
241            }
242        }
[440]243      }
[1273]244
[1061]245      return doIt;
246       
[440]247    }
248
[1061]249    Column defaultColumn(std::string type)
250    {
251      // type|name|units|width|prec|ucd|datatype|extraInfo
[1137]252      if (type == "NUM") return Column(type,"ObjID","",6,0,"meta.id","int","col_objnum","");
[1064]253      else if(type=="NAME") return Column(type,"Name","",8,0,"meta.id;meta.main","char","col_name","");
254      else if(type=="X") return Column(type,"X","",6,prXYZ,"pos.cartesian.x","float","col_x","");
255      else if(type=="Y") return Column(type,"Y","",6,prXYZ,"pos.cartesian.y","float","col_y","");
256      else if(type=="Z") return Column(type,"Z","",6,prXYZ,"pos.cartesian.z","float","col_z","");
257      else if(type=="RA") return Column(type,"RA","",11,0,"","char","col_ra",coordRef);
258      else if(type=="DEC") return Column(type,"DEC","",10,0,"","char","col_dec",coordRef);
259      else if(type=="RAJD") return Column(type,"RAJD","[deg]",11,prPOS,"","float","col_rajd",coordRef);
260      else if(type=="DECJD") return Column(type,"DECJD","[deg]",11,prPOS,"","float","col_decjd",coordRef);
261      else if(type=="VEL") return Column(type,"VEL","",7,prVEL,"","float","col_vel","");
[1131]262      else if(type=="MAJ") return Column(type,"MAJ","[deg]",6,prWPOS,"phys.angSize.smajAxis","float","col_maj",coordRef);
263      else if(type=="MIN") return Column(type,"MIN","[deg]",6,prWPOS,"phys.angSize.sminAxis","float","col_min",coordRef);
264      else if(type=="PA") return Column(type,"PA","[deg]",7,prWPOS,"pos.posAng;phys.angSize","float","col_pa",coordRef);
[1064]265      else if(type=="WRA") return Column(type,"w_RA","[arcmin]",9,prWPOS,"","float","col_wra",coordRef);
266      else if(type=="WDEC") return Column(type,"w_DEC","[arcmin]",9,prWPOS,"","float","col_wdec",coordRef);
267      else if(type=="W50") return Column(type,"w_50","",7,prVEL,"","float","col_w50","");
268      else if(type=="W20") return Column(type,"w_20","",7,prVEL,"","float","col_w20","");
269      else if(type=="WVEL") return Column(type,"w_VEL","",7,prVEL,"","float","col_wvel","");
[1101]270      else if(type=="FINT") return Column(type,"F_int","",10,prFLUX,"phot.flux.density.integrated","float","col_fint","");
[1152]271      else if(type=="FINTERR") return Column(type,"eF_int","",10,prFLUX,"phot.flux.density.integrated;stat.err","float","col_efint","");
[1101]272      else if(type=="FTOT") return Column(type,"F_tot","",10,prFLUX,"phot.flux.density","float","col_ftot","");
[1153]273      else if(type=="FTOTERR") return Column(type,"eF_tot","",10,prFLUX,"phot.flux.density;stat.err","float","col_eftot","");
[1101]274      else if(type=="FPEAK") return Column(type,"F_peak","",9,prFLUX,"phot.flux;stat.max","float","col_fpeak","");
275      else if(type=="SNRPEAK") return Column(type,"S/Nmax","",7,prSNR,"stat.snr;phot.flux","float","col_snrmax","");
[1064]276      else if(type=="X1") return Column(type,"X1","",4,0,"pos.cartesian.x;stat.min","int","col_x1","");
277      else if(type=="Y1") return Column(type,"Y1","",4,0,"pos.cartesian.y;stat.min","int","col_y1","");
278      else if(type=="Z1") return Column(type,"Z1","",4,0,"pos.cartesian.z;stat.min","int","col_z1","");
279      else if(type=="X2") return Column(type,"X2","",4,0,"pos.cartesian.x;stat.max","int","col_x2","");
280      else if(type=="Y2") return Column(type,"Y2","",4,0,"pos.cartesian.y;stat.max","int","col_y2","");
281      else if(type=="Z2") return Column(type,"Z2","",4,0,"pos.cartesian.z;stat.max","int","col_z2","");
[1281]282      else if(type=="NVOX") return Column(type,"Nvoxel","",7,0,"phys.size;instr.pixel;em.bin","int","col_nvox","");
[1273]283      else if(type=="NUMCH") return Column(type,"Nchan","",6,0,"spect.line.width.full;em.bin","int","col_nch","");
[1281]284      else if(type=="SPATSIZE") return Column(type,"Nspatpix","",9,0,"phys.angArea;instr.pixel","int","col_spsize","");
[1064]285      else if(type=="FLAG") return Column(type,"Flag","",5,0,"meta.code.qual","char","col_flag","");
[1101]286      else if(type=="XAV") return Column(type,"X_av","",6,prXYZ,"pos.cartesian.x;stat.mean","float","col_xav","");
287      else if(type=="YAV") return Column(type,"Y_av","",6,prXYZ,"pos.cartesian.y;stat.mean","float","col_yav","");
288      else if(type=="ZAV") return Column(type,"Z_av","",6,prXYZ,"pos.cartesian.z;stat.mean","float","col_zav","");
289      else if(type=="XCENT") return Column(type,"X_cent","",7,prXYZ,"pos.cartesian.x;stat.centroid","float","col_xcent","");
290      else if(type=="YCENT") return Column(type,"Y_cent","",7,prXYZ,"pos.cartesian.y;stat.centroid","float","col_ycent","");
291      else if(type=="ZCENT") return Column(type,"Z_cent","",7,prXYZ,"pos.cartesian.z;stat.centroid","float","col_zcent","");
292      else if(type=="XPEAK") return Column(type,"X_peak","",7,prXYZ,"pos.cartesian.x;phot.flux;stat.max","int","col_xpeak","");
293      else if(type=="YPEAK") return Column(type,"Y_peak","",7,prXYZ,"pos.cartesian.y;phot.flux;stat.max","int","col_ypeak","");
294      else if(type=="ZPEAK") return Column(type,"Z_peak","",7,prXYZ,"pos.cartesian.z;phot.flux;stat.max","int","col_zpeak","");
[1061]295      else {
296        Column col;
297        col.setType(type);
298        return col;
299      }
[221]300
[1061]301    }
302
[1064]303    CatalogueSpecification getFullColSet(std::vector<Detection> &objectList, FitsHeader &head)
[378]304    {
[1064]305      ///  @details A function that returns a catalogue specification
306      ///  containing information on the columns necessary for output
307      ///  to the results file:
308      ///  Obj#,NAME,X,Y,Z,RA,DEC,VEL,w_RA,w_DEC,w_VEL,F_tot,F_int,F_peak,
[1273]309      ///  X1,X2,Y1,Y2,Z1,Z2,Nvox,Flag,
[1064]310      ///  XAV,YAV,ZAV,XCENT,YCENT,ZCENT,XPEAK,YPEAK,ZPEAK
[528]311      ///
312      ///   Each object in the provided objectList is checked to see if it
313      ///   requires any column to be widened, or for that column to have
314      ///   its precision increased.
315      ///
316      ///   Both Ftot and Fint are provided -- it is up to the calling
317      ///   function to determine which to use.
318      ///
319      /// \param objectList A std::vector list of Detection objects that the
320      /// columns need to fit.
321      /// \param head The FitsHeader object defining the World Coordinate
322      /// System.
[1064]323      /// \return A CatalogueSpecification
[93]324
[1064]325      CatalogueSpecification newset;
[93]326
[438]327      // desired precisions for fluxes, velocities and SNR value
[461]328      int precVel,precFlux,precSNR;
329      if(objectList.size()>0){
330        precVel=objectList[0].getVelPrec();
331        precFlux=objectList[0].getFpeakPrec(); // same as FintPrec at this point.
[438]332        precSNR=objectList[0].getSNRPrec();
[461]333      }
334      else {
335        precVel = prVEL;
336        precFlux = prFLUX;
337        precSNR = prSNR;
338      }
[438]339
[378]340      // set up the default columns
[1064]341      newset.addColumn( Column("NUM") );
342      newset.addColumn( Column("NAME") );
343      newset.addColumn( Column("X") );
344      newset.addColumn( Column("Y") );
345      newset.addColumn( Column("Z") );
346      newset.addColumn( Column("RA") );
347      newset.addColumn( Column("DEC") );
348      newset.addColumn( Column("RAJD") );
349      newset.addColumn( Column("DECJD") );
350      newset.addColumn( Column("VEL") );
[1131]351      newset.addColumn( Column("MAJ") );
352      newset.addColumn( Column("MIN") );
353      newset.addColumn( Column("PA") );
[1064]354      newset.addColumn( Column("WRA") );
355      newset.addColumn( Column("WDEC") );
356      newset.addColumn( Column("W50") );
357      newset.addColumn( Column("W20") );
358      newset.addColumn( Column("WVEL") );
359      newset.addColumn( Column("FINT") );
[1152]360      newset.addColumn( Column("FINTERR") );
[1064]361      newset.addColumn( Column("FTOT") );
[1153]362      newset.addColumn( Column("FTOTERR") );
[1064]363      newset.addColumn( Column("FPEAK") );
364      newset.addColumn( Column("SNRPEAK") );
365      newset.addColumn( Column("X1") );
366      newset.addColumn( Column("X2") );
367      newset.addColumn( Column("Y1") );
368      newset.addColumn( Column("Y2") );
369      newset.addColumn( Column("Z1") );
370      newset.addColumn( Column("Z2") );
[1273]371      newset.addColumn( Column("NVOX") );
372      newset.addColumn( Column("NUMCH") );
373      newset.addColumn( Column("SPATSIZE") );
[1064]374      newset.addColumn( Column("FLAG") );
375      newset.addColumn( Column("XAV") );
376      newset.addColumn( Column("YAV") );
377      newset.addColumn( Column("ZAV") );
378      newset.addColumn( Column("XCENT") );
379      newset.addColumn( Column("YCENT") );
380      newset.addColumn( Column("ZCENT") );
381      newset.addColumn( Column("XPEAK") );
382      newset.addColumn( Column("YPEAK") );
383      newset.addColumn( Column("ZPEAK") );
[1217]384     
[1219]385      // Define the column names and units where not predifined by the
386      // default settings (ie. for those columns that depend on the
387      // WCS or image units)
[1217]388      if(head.isWCS()){
389          newset.column("RA").setName(head.lngtype());
390          newset.column("DEC").setName(head.lattype());
391          newset.column("RAJD").setName(head.lngtype());
392          newset.column("DECJD").setName(head.lattype());
393          if(head.canUseThirdAxis()){
394              if(head.WCS().spec < 0)  // if it's not a spectral axis
395                  newset.column("VEL").setName( head.WCS().ctype[2] );
396              else
397                  newset.column("VEL").setName(head.getSpectralType());
398              if(head.getSpectralUnits().size()>0)
399                  newset.column("VEL").setUnits("[" + head.getSpectralUnits() + "]");
400          }
401          newset.column("MAJ").setUnits("["+head.getShapeUnits()+"]");
402          newset.column("MIN").setUnits("["+head.getShapeUnits()+"]");
403          newset.column("WRA").setName("w_"+head.lngtype());
404          newset.column("WDEC").setName("w_"+head.lattype());
405          if(head.canUseThirdAxis()){
406              if(head.getSpectralUnits().size()>0){
407                  newset.column("W50").setUnits("[" + head.getSpectralUnits() + "]");
408                  newset.column("W20").setUnits("[" + head.getSpectralUnits() + "]");
409                  newset.column("WVEL").setUnits("[" + head.getSpectralUnits() + "]");
410              }
411              if(head.WCS().spec < 0) // if it's not a spectral axis
412                  newset.column("WVEL").setName( std::string("w_") + head.WCS().ctype[2] );
413              else
414                  newset.column("WVEL").setName(std::string("w_")+head.getSpectralType());
415          }
416      }
417      if(head.getIntFluxUnits().size()>0){
418          newset.column("FINT").setUnits("[" + head.getIntFluxUnits() + "]");
419          newset.column("FINTERR").setUnits("[" + head.getIntFluxUnits() + "]");
420      }
421      newset.column("FTOT").setUnits("[" + head.getFluxUnits() + "]");
422      newset.column("FTOTERR").setUnits("[" + head.getFluxUnits() + "]");
423      newset.column("FPEAK").setUnits("[" + head.getFluxUnits() + "]");
424     
[1426]425      newset.checkAll(objectList,head);
426     
[378]427      return newset;
[1218]428         
[378]429    }
[136]430
[378]431  }
432
[93]433}
Note: See TracBrowser for help on using the repository browser.