source: trunk/src/fitsHeader.cc @ 494

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

Fixing up some minor bugs in the definition of fitsHeader

File size: 9.4 KB
Line 
1// -----------------------------------------------------------------------
2// fitsHeader.cc: Information about the FITS file's header.
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#include <iostream>
29#include <sstream>
30#include <string>
31#include <wcslib/wcs.h>
32#include <wcslib/wcsunits.h>
33#include <duchamp/duchamp.hh>
34#include <duchamp/param.hh>
35#include <duchamp/fitsHeader.hh>
36#include <duchamp/Utils/utils.hh>
37
38namespace duchamp
39{
40
41  FitsHeader::FitsHeader()
42  {
43    this->wcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
44    this->wcs->flag=-1;
45    wcsini(true, 3, this->wcs);
46    this->wcsIsGood = false;
47    this->nwcs = 0;
48    this->scale=1.;
49    this->offset=0.;
50    this->power=1.;
51    this->fluxUnits="counts";
52    this->intFluxUnits="counts";
53  }
54
55  FitsHeader::~FitsHeader()
56  {
57    /**
58     *  Uses the WCSLIB function wcsvfree to clear the wcsprm struct.
59     */
60    wcsvfree(&nwcs,&wcs);
61  }
62
63  FitsHeader::FitsHeader(const FitsHeader& h)
64  {
65    operator=(h);
66  }
67
68  FitsHeader& FitsHeader::operator= (const FitsHeader& h)
69  {
70    if(this == &h) return *this;
71    this->wcs = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
72    this->wcs->flag     = -1;
73    wcsini(true, h.wcs->naxis, this->wcs);
74    wcscopy(true, h.wcs, this->wcs);
75    wcsset(this->wcs);
76    this->nwcs          = h.nwcs;
77    this->wcsIsGood     = h.wcsIsGood;
78    this->naxis         = h.naxis;
79    this->spectralUnits = h.spectralUnits;
80    this->fluxUnits     = h.fluxUnits;
81    this->intFluxUnits  = h.intFluxUnits;
82    this->beamSize      = h.beamSize;
83    this->bmajKeyword   = h.bmajKeyword;
84    this->bminKeyword   = h.bminKeyword;
85    this->bpaKeyword    = h.bpaKeyword;
86    this->blankKeyword  = h.blankKeyword;
87    this->bzeroKeyword  = h.bzeroKeyword;
88    this->bscaleKeyword = h.bscaleKeyword;
89    this->scale         = h.scale;
90    this->offset        = h.offset;
91    this->power         = h.power;
92    return *this;
93  }
94
95  void FitsHeader::setWCS(struct wcsprm *w)
96  {
97    /**
98     *  A function that assigns the wcs parameters, and runs
99     *   wcsset to set it up correctly.
100     *  Performs a check to see if the WCS is good (by looking at
101     *   the lng and lat wcsprm parameters), and sets the wcsIsGood
102     *   flag accordingly.
103     * \param w A WCSLIB wcsprm struct with the correct parameters.
104     */
105    wcscopy(true, w, this->wcs);
106    wcsset(this->wcs);
107    if( (w->lng!=-1) && (w->lat!=-1) ) this->wcsIsGood = true;
108  }
109
110  struct wcsprm *FitsHeader::getWCS()
111  {
112    /**
113     *  A function that returns a properly initilized wcsprm object
114     *  corresponding to the WCS.
115     */
116    struct wcsprm *wNew = (struct wcsprm *)calloc(1,sizeof(struct wcsprm));
117    wNew->flag=-1;
118    wcsini(true, this->wcs->naxis, wNew);
119    wcscopy(true, this->wcs, wNew);
120    wcsset(wNew);
121    return wNew;
122  }
123
124  int FitsHeader::wcsToPix(const double *world, double *pix)
125  {     
126    return wcsToPixSingle(this->wcs, world, pix); 
127  }
128  int FitsHeader::wcsToPix(const double *world, double *pix, const int npts)
129  {
130    return wcsToPixMulti(this->wcs, world, pix, npts); 
131  }
132  int FitsHeader::pixToWCS(const double *pix, double *world)
133  {   
134    return pixToWCSSingle(this->wcs, pix, world); 
135  }
136  int FitsHeader::pixToWCS(const double *pix, double *world, const int npts)
137  {
138    return pixToWCSMulti(this->wcs, pix,world, npts); 
139  }
140
141
142  double FitsHeader::pixToVel(double &x, double &y, double &z)
143  {
144    double vel;
145    if(this->wcsIsGood){
146      double *pix   = new double[3];
147      double *world = new double[3];
148      pix[0] = x; pix[1] = y; pix[2] = z;
149      pixToWCSSingle(this->wcs,pix,world);
150      vel = this->specToVel(world[2]);
151      delete [] pix;
152      delete [] world;
153    }
154    else vel = z;
155    return vel;
156  }
157
158  double* FitsHeader::pixToVel(double &x, double &y, double *zarray, int size)
159  {
160    double *newzarray = new double[size];
161    if(this->wcsIsGood){
162      double *pix   = new double[size*3];
163      for(int i=0;i<size;i++){
164        pix[3*i]   = x;
165        pix[3*i+1] = y;
166        pix[3*i+2] = zarray[i];
167      }
168      double *world = new double[size*3];
169      pixToWCSMulti(this->wcs,pix,world,size);
170      delete [] pix;
171      for(int i=0;i<size;i++) newzarray[i] = this->specToVel(world[3*i+2]);
172      delete [] world;
173    }
174    else{
175      for(int i=0;i<size;i++) newzarray[i] = zarray[i];
176    }
177    return newzarray;
178  }
179
180  double FitsHeader::specToVel(const double &coord)
181  {
182    double vel;
183    if(power==1.0) vel =  coord*this->scale + this->offset;
184    else vel = pow( (coord*this->scale + this->offset), this->power);
185    return vel;
186  }
187
188  double FitsHeader::velToSpec(const float &velocity)
189  {
190    //   return velToCoord(this->wcs,velocity,this->spectralUnits);};
191    return (pow(velocity, 1./this->power) - this->offset) / this->scale;
192  }
193
194  std::string FitsHeader::getIAUName(double ra, double dec)
195  {
196    if(strcmp(this->wcs->lngtyp,"RA")==0)
197      return getIAUNameEQ(ra, dec, this->wcs->equinox);
198    else
199      return getIAUNameGAL(ra, dec);
200  }
201
202  bool FitsHeader::needBeamSize()
203  {
204    /**
205     *  A function that tells you whether the beam correction is
206     *  needed. It checks to see whether the flux units string ends in
207     *  "/beam" (in which case the beam size etc is needed and
208     *  integrated fluxes need to be corrected).
209     *  /return True if FitsHeader::fluxUnits ends in "/beam". False
210     *  otherwise.
211     */
212    int size = this->fluxUnits.size();
213    if(size<6) return false;
214    else {
215      std::string tailOfFluxUnits = makelower(this->fluxUnits.substr(size-5,size));
216      return (tailOfFluxUnits == "/beam");
217    }
218  }
219
220  void FitsHeader::fixUnits(Param &par)
221  {
222    /**
223     *  Put the units for the FITS header into some sort of standard form.
224     *
225     *  We first get the desired spectral units from the Parameter set,
226     *  and then transform the spectral units of the wcsprm struct to
227     *  those units. If this doesn't work, we leave them as they are. If
228     *  they are blank, we make them SPC and give an error message --
229     *  this should hopefully NOT happen.
230     *
231     *  We also work out the units for the integrated flux. If there are
232     *  three axes, we just append the spectral units to the flux units
233     *  (removing "/beam" if it is present). If there are just two, we
234     *  simply keep it the same, removing the "/beam".
235     *
236     *  \param par The parameter set telling us what the desired
237     *             spectral units are.
238     */
239
240    // define spectral units from the param set
241    this->spectralUnits = par.getSpectralUnits();
242    double sc=1.;
243    double of=0.;
244    double po=1.;
245    //   if((this->wcsIsGood) && (this->naxis>2)){
246    if(this->wcsIsGood){
247      int status = wcsunits( this->wcs->cunit[this->wcs->spec],
248                             (char *)this->spectralUnits.c_str(),
249                             &sc, &of, &po);
250      if(status > 0){
251        std::stringstream errmsg;
252        errmsg << "WCSUNITS Error, Code = " << status
253               << ": " << wcsunits_errmsg[status] << "\n";
254        if(status == 10)
255          errmsg << "Tried to get conversion from \""
256                 << this->wcs->cunit[this->wcs->spec] << "\" to \""
257                 << this->spectralUnits.c_str() << "\".\n";
258        this->spectralUnits = this->wcs->cunit[this->wcs->spec];
259        if(this->spectralUnits==""){
260          errmsg << "Spectral units not specified. "
261                 << "For data presentation, we will use dummy units of \"SPC\"."
262                 << "\n"
263                 << "Please report this occurence -- it should not happen now! "
264                 << "In the meantime, you may want to set the CUNIT"
265                 << this->wcs->spec + 1 <<" keyword to make this work.\n";
266          this->spectralUnits = "SPC";
267        }
268        duchampError("fixUnits", errmsg.str());
269      }
270
271    }
272    this->scale = sc;
273    this->offset= of;
274    this->power = po;
275
276    this->setIntFluxUnits();
277
278  }
279
280  void FitsHeader::setIntFluxUnits()
281  {
282
283    /**
284     * Work out the integrated flux units, based on the spectral units.
285     * If flux is per beam, trim the /beam from the flux units and multiply
286     *  by the spectral units.
287     * Otherwise, just muliply by the spectral units.
288     */
289
290    if(this->fluxUnits.size()>5){
291   
292      if(makelower(this->fluxUnits.substr(this->fluxUnits.size()-5,
293                                          this->fluxUnits.size()   )) == "/beam"){
294        this->intFluxUnits = this->fluxUnits.substr(0,this->fluxUnits.size()-5);
295      }
296      else this->intFluxUnits = this->fluxUnits;
297
298      if(this->wcs->naxis>2) this->intFluxUnits += " " + this->spectralUnits;
299    }
300
301  }
302
303}
Note: See TracBrowser for help on using the repository browser.