source: trunk/src/fitsHeader.cc @ 541

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

Changing all calls of uint to unsigned int, as there are sometimes compilers that don't know about that typedef. Also added an include call for stdlib.h to fitsHeader.cc so that it knows about calloc.

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