source: trunk/src/Utils/wcsFunctions.cc @ 478

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

Fixed a bug in the WCS conversions that led to crashes if no spectral axis was specified.

File size: 13.5 KB
Line 
1// -----------------------------------------------------------------------
2// wcsFunctions.cc: Functions to convert between pixel and world
3//                  coordinates -- user-friendly front ends to the
4//                  WCSLIB functions.
5// -----------------------------------------------------------------------
6// Copyright (C) 2006, Matthew Whiting, ATNF
7//
8// This program is free software; you can redistribute it and/or modify it
9// under the terms of the GNU General Public License as published by the
10// Free Software Foundation; either version 2 of the License, or (at your
11// option) any later version.
12//
13// Duchamp is distributed in the hope that it will be useful, but WITHOUT
14// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
16// for more details.
17//
18// You should have received a copy of the GNU General Public License
19// along with Duchamp; if not, write to the Free Software Foundation,
20// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
21//
22// Correspondence concerning Duchamp may be directed to:
23//    Internet email: Matthew.Whiting [at] atnf.csiro.au
24//    Postal address: Dr. Matthew Whiting
25//                    Australia Telescope National Facility, CSIRO
26//                    PO Box 76
27//                    Epping NSW 1710
28//                    AUSTRALIA
29// -----------------------------------------------------------------------
30#include <iostream>
31#include <sstream>
32#include <math.h>
33#include <wcslib/wcs.h>
34#include <wcslib/wcsunits.h>
35#include <duchamp/duchamp.hh>
36#include <duchamp/Utils/utils.hh>
37
38int pixToWCSSingle(struct wcsprm *wcs, const double *pix, double *world)
39{
40  /**
41   *   Uses wcs to convert the three-dimensional pixel position referenced
42   *    by pix to world coordinates, which are placed in the array world[].
43   *   Assumes that pix only has one point with an x,y,and z pixel positions.
44   *   If there are any other axes present (eg. Stokes), these are set to the
45   *    first pixel in that axis.
46   *   Offsets these pixel values by 1 to account for the C arrays being
47   *    indexed to 0.
48   *
49   * \param wcs The wcsprm struct containing the WCS information.
50   * \param pix The array of pixel coordinates.
51   * \param world The returned array of world coordinates.
52   */
53
54  int naxis=wcs->naxis,npts=1,status;
55  int specAxis = wcs->spec;
56  if(specAxis<0) specAxis=2;
57
58  double *newpix = new double[naxis*npts];
59  // correct from 0-indexed to 1-indexed pixel array
60  for(int i=0;i<naxis;i++) newpix[i] = 1.;
61  newpix[wcs->lng] += pix[0];
62  newpix[wcs->lat] += pix[1];
63  newpix[specAxis]+= pix[2];
64
65  int    *stat      = new int[npts];
66  double *imgcrd    = new double[naxis*npts];
67  double *tempworld = new double[naxis*npts];
68  double *phi       = new double[npts];
69  double *theta     = new double[npts];
70  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
71                phi, theta, tempworld, stat);
72  if(status>0){
73    std::stringstream errmsg;
74    errmsg << "WCS Error Code = " << status <<": " << wcs_errmsg[status]
75           << "\nstat value is " << stat[0] << std::endl;
76    duchamp::duchampError("pixToWCSSingle",errmsg.str());
77  }
78
79  //return just the spatial/velocity information
80  world[0] = tempworld[wcs->lng];
81  world[1] = tempworld[wcs->lat];
82  world[2] = tempworld[specAxis];
83
84  delete [] stat;
85  delete [] imgcrd;
86  delete [] tempworld;
87  delete [] phi;
88  delete [] theta;
89  delete [] newpix;
90  return status;
91}
92
93int wcsToPixSingle(struct wcsprm *wcs, const double *world, double *pix)
94{
95  /**
96   *   Uses wcs to convert the three-dimensional world coordinate position
97   *    referenced by world to pixel coordinates, which are placed in the
98   *    array pix[].
99   *   Assumes that world only has one point (three values eg RA Dec Velocity)
100   *   Offsets the pixel values by 1 to account for the C arrays being
101   *    indexed to 0.
102   *
103   * \param wcs The wcsprm struct containing the WCS information.
104   * \param world The array of world coordinates.
105   * \param pix The returned array of pixel coordinates.
106   */
107
108  int naxis=wcs->naxis,npts=1,status;
109  int specAxis = wcs->spec;
110  if(specAxis<0) specAxis=2;
111
112  double *tempworld = new double[naxis*npts];
113  for(int i=0;i<naxis;i++) tempworld[i] = wcs->crval[i];
114  tempworld[wcs->lng]  = world[0];
115  tempworld[wcs->lat]  = world[1];
116  tempworld[specAxis] = world[2];
117
118  int    *stat    = new int[npts];
119  double *temppix = new double[naxis*npts];
120  double *imgcrd  = new double[naxis*npts];
121  double *phi     = new double[npts];
122  double *theta   = new double[npts];
123
124  status=wcss2p(wcs, npts, naxis, tempworld,
125                phi, theta, imgcrd, temppix, stat);
126
127  if( status > 0 ){
128    std::stringstream errmsg;
129    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
130           << "\nstat value is " << stat[0] << std::endl;
131    duchamp::duchampError("wcsToPixSingle",errmsg.str());
132  }
133
134  pix[0] = temppix[wcs->lng] - 1.;
135  pix[1] = temppix[wcs->lat] - 1.;
136  pix[2] = temppix[specAxis] - 1.;
137  // correct from 1-indexed to 0-indexed pixel array
138  //  and only return the spatial & frequency information
139
140  delete [] stat;
141  delete [] imgcrd;
142  delete [] temppix;
143  delete [] phi;
144  delete [] theta;
145  delete [] tempworld;
146  return status;
147}
148
149int pixToWCSMulti(struct wcsprm *wcs, const double *pix,
150                  double *world, const int npts)
151{
152  /**
153   *   Uses wcs to convert the three-dimensional pixel positions referenced
154   *    by pix to world coordinates, which are placed in the array world[].
155   *   pix is assumed to hold the positions of npts points.
156   *   Offsets these pixel values by 1 to account for the C arrays being
157   *    indexed to 0.
158   *
159   * \param wcs The wcsprm struct containing the WCS information.
160   * \param pix The array of pixel coordinates.
161   * \param world The returned array of world coordinates.
162   * \param npts The number of distinct pixels in the arrays.
163   */
164
165  int naxis=wcs->naxis,status;
166  int specAxis = wcs->spec;
167  if(specAxis<0) specAxis=2;
168
169  // correct from 0-indexed to 1-indexed pixel array
170  // Add entries for any other axes that are present, keeping the
171  //   order of pixel positions the same
172  double *newpix = new double[naxis*npts];
173  for(int pt=0;pt<npts;pt++){
174    for(int i=0;i<naxis;i++) newpix[pt*naxis+i] = 1.;
175    newpix[pt*naxis+wcs->lng]  += pix[pt*3+0];
176    newpix[pt*naxis+wcs->lat]  += pix[pt*3+1];
177    newpix[pt*naxis+specAxis] += pix[pt*3+2];
178  }
179
180  int    *stat      = new int[npts];
181  double *imgcrd    = new double[naxis*npts];
182  double *tempworld = new double[naxis*npts];
183  double *phi       = new double[npts];
184  double *theta     = new double[npts];
185  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
186                phi, theta, tempworld, stat);
187  if(status>0){
188    std::stringstream errmsg;
189    errmsg << "WCS Error Code = " <<status<<": " << wcs_errmsg[status]
190           << "\nstat value is " << stat[0] << std::endl;
191    duchamp::duchampError("pixToWCSMulti",errmsg.str());
192  }
193  else{
194    //return just the spatial/velocity information, keeping the
195    //  order of the pixel positions the same.
196    for(int pt=0;pt<npts;pt++){
197      world[pt*3+0] = tempworld[pt*naxis + wcs->lng];
198      world[pt*3+1] = tempworld[pt*naxis + wcs->lat];
199      world[pt*3+2] = tempworld[pt*naxis + specAxis];
200    }
201   
202  }
203
204  delete [] stat;
205  delete [] imgcrd;
206  delete [] tempworld;
207  delete [] phi;
208  delete [] theta;
209  delete [] newpix;
210  return status;
211}
212
213int wcsToPixMulti(struct wcsprm *wcs, const double *world,
214                  double *pix, const int npts)
215{
216  /**
217   *   Uses wcs to convert the three-dimensional world coordinate position
218   *    referenced by world to pixel coordinates, which are placed in the
219   *    array pix[].
220   *   world is assumed to hold the positions of npts points.
221   *   Offsets the pixel values by 1 to account for the C arrays being
222   *    indexed to 0.
223   *
224   * \param wcs The wcsprm struct containing the WCS information.
225   * \param world The array of world coordinates.
226   * \param pix The returned array of pixel coordinates.
227   * \param npts The number of distinct pixels in the arrays.
228   */
229
230  int naxis=wcs->naxis,status=0;
231  int specAxis = wcs->spec;
232  if(specAxis<0) specAxis=2;
233
234  // Test to see if there are other axes present, eg. stokes
235  if(wcs->naxis>naxis) naxis = wcs->naxis;
236
237  // Add entries for any other axes that are present, keeping the
238  //   order of pixel positions the same
239  double *tempworld = new double[naxis*npts];
240  for(int pt=0;pt<npts;pt++){
241    for(int axis=0;axis<naxis;axis++)
242      tempworld[pt*naxis+axis] = wcs->crval[axis];
243    tempworld[pt*naxis + wcs->lng]  = world[pt*3+0];
244    tempworld[pt*naxis + wcs->lat]  = world[pt*3+1];
245    tempworld[pt*naxis + specAxis] = world[pt*3+2];
246  }
247
248  int    *stat   = new int[npts];
249  double *temppix = new double[naxis*npts];
250  double *imgcrd = new double[naxis*npts];
251  double *phi    = new double[npts];
252  double *theta  = new double[npts];
253  status=wcss2p(wcs,npts,naxis,tempworld,phi,theta,
254                imgcrd,temppix,stat);
255  if(status>0){
256    std::stringstream errmsg;
257    errmsg << "WCS Error Code = " <<status<<": " <<wcs_errmsg[status]
258           << "\nstat value is " << stat[0] << std::endl;
259    duchamp::duchampError("wcsToPixMulti",errmsg.str());
260  }
261  else{
262    // correct from 1-indexed to 0-indexed pixel array
263    //  and return just the spatial/velocity information,
264    //  keeping the order of the pixel positions the same.
265    for(int pt=0;pt<npts;pt++){
266      pix[pt*naxis + 0] = temppix[pt*naxis + wcs->lng] - 1.;
267      pix[pt*naxis + 1] = temppix[pt*naxis + wcs->lat] - 1.;
268      pix[pt*naxis + 2] = temppix[pt*naxis + specAxis] - 1.;
269    }
270  }
271
272  delete [] stat;
273  delete [] imgcrd;
274  delete [] temppix;
275  delete [] phi;
276  delete [] theta;
277  delete [] tempworld;
278  return status;
279}
280
281double pixelToVelocity(struct wcsprm *wcs, double &x, double &y, double &z,
282                       std::string velUnits)
283{
284  /**
285   *   Uses wcs to convert the three-dimensional pixel position (x,y,z)
286   *   to world coordinates.
287   *   Returns the velocity in the units given by velUnits.
288   *
289   * \param wcs  The wcsprm struct containing the WCS information.
290   * \param x The x pixel coordinate.
291   * \param y The y pixel coordinate.
292   * \param z The z pixel coordinate.
293   * \param velUnits The string containing the units of the output velocity.
294   * \return The velocity of the pixel.
295   */
296
297  int naxis=wcs->naxis,status=0;
298  int    *stat   = new int[1];
299  double *pixcrd = new double[naxis];
300  double *imgcrd = new double[naxis];
301  double *world  = new double[naxis];
302  double *phi    = new double[1];
303  double *theta  = new double[1];
304
305  int specAxis = wcs->spec;
306  if(specAxis<0) specAxis=2;
307
308  // correct from 0-indexed to 1-indexed pixel array by adding 1 to
309  // pixel values.
310  for(int i=0;i<naxis;i++) pixcrd[i] = 1.;
311  pixcrd[wcs->lng] += x;
312  pixcrd[wcs->lat] += y;
313  pixcrd[specAxis]+= z;
314  status=wcsp2s(wcs, 1, naxis, pixcrd, imgcrd,
315                phi, theta, world, stat);
316  if(status>0){
317    std::stringstream errmsg;
318    errmsg <<"WCS Error Code = "<<status<<": "<<wcs_errmsg[status]
319           << "\nstat value is "<<stat[0]<<std::endl;
320    duchamp::duchampError("pixelToVelocity",errmsg.str());
321  }
322
323  double vel = coordToVel(wcs, world[specAxis], velUnits);
324
325  delete [] stat;
326  delete [] pixcrd;
327  delete [] imgcrd;
328  delete [] world;
329  delete [] phi;
330  delete [] theta;
331 
332  return vel;
333}
334 
335double coordToVel(struct wcsprm *wcs, const double coord,
336                  std::string outputUnits)
337{
338  /**
339   *   Convert the wcs coordinate given by coord to a velocity in km/s.
340   *   Does this by checking the ztype parameter in wcs to see if it is
341   *    FREQ or otherwise, and converts accordingly.
342   *
343   * \param wcs  The wcsprm struct containing the WCS information.
344   * \param coord The input WCS coordinate.
345   * \param outputUnits The string containing the units of the output velocity.
346   * \return The velocity of the input coord value.
347   */
348
349  static int errflag = 0;
350  double scale, offset, power;
351  int specIndex = wcs->spec;
352  if(specIndex<0) specIndex = 2;
353  int status = wcsunits( wcs->cunit[specIndex], outputUnits.c_str(),
354                         &scale, &offset, &power);
355
356  if(status > 0){
357    if(errflag==0){
358      std::stringstream errmsg;
359      errmsg << "WCSUNITS Error Code = " << status << ":"
360             << wcsunits_errmsg[status];
361      if(status == 10) errmsg << "\nTried to get conversion from "
362                              << wcs->cunit[specIndex]
363                              << " to " << outputUnits.c_str();
364      errmsg << "\nUsing coordinate value instead.\n";
365      duchamp::duchampError("coordToVel", errmsg.str());
366      errflag = 1;
367    }
368    return coord;
369  }
370  else return pow( (coord*scale + offset), power);
371
372}
373
374double velToCoord(struct wcsprm *wcs, const float velocity,
375                  std::string outputUnits)
376{
377  /**
378   *   Convert the velocity given to the appropriate world coordinate for wcs.
379   *   Does this by checking the ztype parameter in wcs to see if it is
380   *    FREQ or otherwise, and converts accordingly.
381   *
382   * \param wcs  The wcsprm struct containing the WCS information.
383   * \param velocity The input velocity.
384   * \param outputUnits The string containing the units of the input velocity.
385   * \return The WCS coordinate corresponding to the input velocity.
386   */
387
388  double scale, offset, power;
389  int specIndex = wcs->spec;
390  if(specIndex<0) specIndex = 2;
391  int status = wcsunits( outputUnits.c_str(), wcs->cunit[specIndex],
392                         &scale, &offset, &power);
393
394  if(status > 0){
395    std::stringstream errmsg;
396    errmsg << "WCSUNITS Error Code = " << status << ":"
397           << wcsunits_errmsg[status] << "\nUsing coordinate value instead.\n";
398    duchamp::duchampError("velToCoord",errmsg.str());
399    return velocity;
400  }
401  else return (pow(velocity, 1./power) - offset) / scale;
402 
403}
Note: See TracBrowser for help on using the repository browser.