source: tags/release-1.1.12/src/fitsHeader.cc

Last change on this file was 796, checked in by MatthewWhiting, 13 years ago

Removing the getBeamArea function, as the new classes do this now. Also reordering the file without any functional change.

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