source: tags/release-1.2.2/src/Utils/wcsFunctions.cc

Last change on this file was 933, checked in by MatthewWhiting, 12 years ago

Getting the error reporting for the WCS functions right - I'd mistaken the size of the stat[] arrays that they return.

File size: 13.7 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
38using namespace duchamp;
39
40int pixToWCSSingle(struct wcsprm *wcs, const double *pix, double *world)
41{
42  ///  @details
43  ///   Uses wcs to convert the three-dimensional pixel position referenced
44  ///    by pix to world coordinates, which are placed in the array world[].
45  ///   Assumes that pix only has one point with an x,y,and z pixel positions.
46  ///   If there are any other axes present (eg. Stokes), these are set to the
47  ///    first pixel in that axis.
48  ///   Offsets these pixel values by 1 to account for the C arrays being
49  ///    indexed to 0.
50  ///
51  /// \param wcs The wcsprm struct containing the WCS information.
52  /// \param pix The array of pixel coordinates.
53  /// \param world The returned array of world coordinates.
54
55  int naxis=wcs->naxis,npts=1,status;
56  int specAxis = wcs->spec;
57  if(specAxis<0) specAxis=2;
58  if(specAxis>=naxis) specAxis = naxis-1;
59
60  double *newpix = new double[naxis*npts];
61  // correct from 0-indexed to 1-indexed pixel array
62  for(int i=0;i<naxis;i++) newpix[i] = 1.;
63  newpix[wcs->lng] += pix[0];
64  newpix[wcs->lat] += pix[1];
65  newpix[specAxis]+= pix[2];
66
67  int    *stat      = new int[npts];
68  double *imgcrd    = new double[naxis*npts];
69  double *tempworld = new double[naxis*npts];
70  double *phi       = new double[npts];
71  double *theta     = new double[npts];
72  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
73                phi, theta, tempworld, stat);
74  if(status>0){
75    DUCHAMPTHROW("pixToWCSSingle","WCS Error Code = " << status <<": stat="<<stat[0] << " : " << wcs_errmsg[status]);
76  }
77
78  //return just the spatial/velocity information
79  world[0] = tempworld[wcs->lng];
80  world[1] = tempworld[wcs->lat];
81  world[2] = tempworld[specAxis];
82
83  delete [] stat;
84  delete [] imgcrd;
85  delete [] tempworld;
86  delete [] phi;
87  delete [] theta;
88  delete [] newpix;
89  return status;
90}
91
92int wcsToPixSingle(struct wcsprm *wcs, const double *world, double *pix)
93{
94  ///  @details
95  ///   Uses wcs to convert the three-dimensional world coordinate position
96  ///    referenced by world to pixel coordinates, which are placed in the
97  ///    array pix[].
98  ///   Assumes that world only has one point (three values eg RA Dec Velocity)
99  ///   Offsets the pixel values by 1 to account for the C arrays being
100  ///    indexed to 0.
101  ///
102  /// \param wcs The wcsprm struct containing the WCS information.
103  /// \param world The array of world coordinates.
104  /// \param pix The returned array of pixel coordinates.
105
106  int naxis=wcs->naxis,npts=1,status;
107  int specAxis = wcs->spec;
108  if(specAxis<0) specAxis=2;
109  if(specAxis>=naxis) specAxis = naxis-1;
110
111  double *tempworld = new double[naxis*npts];
112  for(int i=0;i<naxis;i++) tempworld[i] = wcs->crval[i];
113  tempworld[wcs->lng]  = world[0];
114  tempworld[wcs->lat]  = world[1];
115  tempworld[specAxis] = world[2];
116
117  int    *stat    = new int[npts];
118  double *temppix = new double[naxis*npts];
119  double *imgcrd  = new double[naxis*npts];
120  double *phi     = new double[npts];
121  double *theta   = new double[npts];
122
123  status=wcss2p(wcs, npts, naxis, tempworld,
124                phi, theta, imgcrd, temppix, stat);
125
126  if( status > 0 ){
127    DUCHAMPTHROW("wcsToPixSingle","WCS Error Code = " << status <<": stat="<<stat[0] << " : " << wcs_errmsg[status]);
128  }
129
130  pix[0] = temppix[wcs->lng] - 1.;
131  pix[1] = temppix[wcs->lat] - 1.;
132  pix[2] = temppix[specAxis] - 1.;
133  // correct from 1-indexed to 0-indexed pixel array
134  //  and only return the spatial & frequency information
135
136  delete [] stat;
137  delete [] imgcrd;
138  delete [] temppix;
139  delete [] phi;
140  delete [] theta;
141  delete [] tempworld;
142  return status;
143}
144
145int pixToWCSMulti(struct wcsprm *wcs, const double *pix,
146                  double *world, const int npts)
147{
148  ///  @details
149  ///   Uses wcs to convert the three-dimensional pixel positions referenced
150  ///    by pix to world coordinates, which are placed in the array world[].
151  ///   pix is assumed to hold the positions of npts points.
152  ///   Offsets these pixel values by 1 to account for the C arrays being
153  ///    indexed to 0.
154  ///
155  /// \param wcs The wcsprm struct containing the WCS information.
156  /// \param pix The array of pixel coordinates.
157  /// \param world The returned array of world coordinates.
158  /// \param npts The number of distinct pixels in the arrays.
159
160  int naxis=wcs->naxis,status;
161  int specAxis = wcs->spec;
162  if(specAxis<0) specAxis=2;
163  if(specAxis>=naxis) specAxis = naxis-1;
164
165  // correct from 0-indexed to 1-indexed pixel array
166  // Add entries for any other axes that are present, keeping the
167  //   order of pixel positions the same
168  double *newpix = new double[naxis*npts];
169  for(int pt=0;pt<npts;pt++){
170    for(int i=0;i<naxis;i++) newpix[pt*naxis+i] = 1.;
171    newpix[pt*naxis+wcs->lng]  += pix[pt*3+0];
172    newpix[pt*naxis+wcs->lat]  += pix[pt*3+1];
173    newpix[pt*naxis+specAxis] += pix[pt*3+2];
174  }
175
176  int    *stat      = new int[npts];
177  double *imgcrd    = new double[naxis*npts];
178  double *tempworld = new double[naxis*npts];
179  double *phi       = new double[npts];
180  double *theta     = new double[npts];
181  status=wcsp2s(wcs, npts, naxis, newpix, imgcrd,
182                phi, theta, tempworld, stat);
183  if(status>0){
184    std::stringstream statstr;
185    statstr<<"|";
186    for(int i=0;i<npts;i++) statstr<<stat[i]<<"|";
187    DUCHAMPTHROW("pixToWCSMulti","WCS Error Code = " << status <<": stat="<<statstr.str() << " : " << wcs_errmsg[status]);
188  }
189  else{
190    //return just the spatial/velocity information, keeping the
191    //  order of the pixel positions the same.
192    for(int pt=0;pt<npts;pt++){
193      world[pt*3+0] = tempworld[pt*naxis + wcs->lng];
194      world[pt*3+1] = tempworld[pt*naxis + wcs->lat];
195      world[pt*3+2] = tempworld[pt*naxis + specAxis];
196    }
197   
198  }
199
200  delete [] stat;
201  delete [] imgcrd;
202  delete [] tempworld;
203  delete [] phi;
204  delete [] theta;
205  delete [] newpix;
206  return status;
207}
208
209int wcsToPixMulti(struct wcsprm *wcs, const double *world,
210                  double *pix, const int npts)
211{
212  ///  @details
213  ///   Uses wcs to convert the three-dimensional world coordinate position
214  ///    referenced by world to pixel coordinates, which are placed in the
215  ///    array pix[].
216  ///   world is assumed to hold the positions of npts points.
217  ///   Offsets the pixel values by 1 to account for the C arrays being
218  ///    indexed to 0.
219  ///
220  /// \param wcs The wcsprm struct containing the WCS information.
221  /// \param world The array of world coordinates.
222  /// \param pix The returned array of pixel coordinates.
223  /// \param npts The number of distinct pixels in the arrays.
224
225  int naxis=wcs->naxis,status=0;
226  int specAxis = wcs->spec;
227  if(specAxis<0) specAxis=2;
228  if(specAxis>=naxis) specAxis = naxis-1;
229
230  // Test to see if there are other axes present, eg. stokes
231  if(wcs->naxis>naxis) naxis = wcs->naxis;
232
233  // Add entries for any other axes that are present, keeping the
234  //   order of pixel positions the same
235  double *tempworld = new double[naxis*npts];
236  for(int pt=0;pt<npts;pt++){
237    for(int axis=0;axis<naxis;axis++)
238      tempworld[pt*naxis+axis] = wcs->crval[axis];
239    tempworld[pt*naxis + wcs->lng]  = world[pt*3+0];
240    tempworld[pt*naxis + wcs->lat]  = world[pt*3+1];
241    tempworld[pt*naxis + specAxis] = world[pt*3+2];
242  }
243
244  int    *stat   = new int[npts];
245  double *temppix = new double[naxis*npts];
246  double *imgcrd = new double[naxis*npts];
247  double *phi    = new double[npts];
248  double *theta  = new double[npts];
249  status=wcss2p(wcs,npts,naxis,tempworld,phi,theta,
250                imgcrd,temppix,stat);
251  if(status>0){
252    std::stringstream statstr;
253    statstr<<"|";
254    for(int i=0;i<npts;i++) statstr<<stat[i]<<"|";
255    DUCHAMPTHROW("wcsToPixMulti","WCS Error Code = " << status <<": stat="<<statstr.str() << " : " << wcs_errmsg[status]);
256  }
257  else{
258    // correct from 1-indexed to 0-indexed pixel array
259    //  and return just the spatial/velocity information,
260    //  keeping the order of the pixel positions the same.
261    for(int pt=0;pt<npts;pt++){
262      pix[pt*naxis + 0] = temppix[pt*naxis + wcs->lng] - 1.;
263      pix[pt*naxis + 1] = temppix[pt*naxis + wcs->lat] - 1.;
264      pix[pt*naxis + 2] = temppix[pt*naxis + specAxis] - 1.;
265    }
266  }
267
268  delete [] stat;
269  delete [] imgcrd;
270  delete [] temppix;
271  delete [] phi;
272  delete [] theta;
273  delete [] tempworld;
274  return status;
275}
276
277double pixelToVelocity(struct wcsprm *wcs, double &x, double &y, double &z,
278                       std::string velUnits)
279{
280  ///  @details
281  ///   Uses wcs to convert the three-dimensional pixel position (x,y,z)
282  ///   to world coordinates.
283  ///   Returns the velocity in the units given by velUnits.
284  ///
285  /// \param wcs  The wcsprm struct containing the WCS information.
286  /// \param x The x pixel coordinate.
287  /// \param y The y pixel coordinate.
288  /// \param z The z pixel coordinate.
289  /// \param velUnits The string containing the units of the output velocity.
290  /// \return The velocity of the pixel.
291
292  int naxis=wcs->naxis,status=0;
293  int    *stat   = new int[1];
294  double *pixcrd = new double[naxis];
295  double *imgcrd = new double[naxis];
296  double *world  = new double[naxis];
297  double *phi    = new double[1];
298  double *theta  = new double[1];
299
300  int specAxis = wcs->spec;
301  if(specAxis<0) specAxis=2;
302  if(specAxis>=naxis) specAxis = naxis-1;
303
304  // correct from 0-indexed to 1-indexed pixel array by adding 1 to
305  // pixel values.
306  for(int i=0;i<naxis;i++) pixcrd[i] = 1.;
307  pixcrd[wcs->lng] += x;
308  pixcrd[wcs->lat] += y;
309  pixcrd[specAxis]+= z;
310  status=wcsp2s(wcs, 1, naxis, pixcrd, imgcrd,
311                phi, theta, world, stat);
312  if(status>0){
313    std::stringstream statstr;
314    statstr<<"|";
315    for(int i=0;i<naxis;i++) statstr<<stat[i]<<"|";
316    DUCHAMPTHROW("pixelToVelocity","WCS Error Code = " << status <<": stat="<<stat[0] << " : " << wcs_errmsg[status]);
317  }
318
319  double vel = coordToVel(wcs, world[specAxis], velUnits);
320
321  delete [] stat;
322  delete [] pixcrd;
323  delete [] imgcrd;
324  delete [] world;
325  delete [] phi;
326  delete [] theta;
327 
328  return vel;
329}
330 
331double coordToVel(struct wcsprm *wcs, const double coord,
332                  std::string outputUnits)
333{
334  ///  @details
335  ///   Convert the wcs coordinate given by coord to a velocity in km/s.
336  ///   Does this by checking the ztype parameter in wcs to see if it is
337  ///    FREQ or otherwise, and converts accordingly.
338  ///
339  /// \param wcs  The wcsprm struct containing the WCS information.
340  /// \param coord The input WCS coordinate.
341  /// \param outputUnits The string containing the units of the output velocity.
342  /// \return The velocity of the input coord value.
343
344  static int errflag = 0;
345  double scale, offset, power;
346  int specIndex = wcs->spec;
347  if(specIndex<0) specIndex = 2;
348  if(specIndex>=wcs->naxis) specIndex = wcs->naxis-1;
349  int status = wcsunits( wcs->cunit[specIndex], outputUnits.c_str(),
350                         &scale, &offset, &power);
351
352  if(status > 0){
353    if(errflag==0){
354      std::stringstream errmsg;
355      errmsg << "WCSUNITS Error Code = " << status << ":"
356             << wcsunits_errmsg[status];
357      if(status == 10) errmsg << "\nTried to get conversion from "
358                              << wcs->cunit[specIndex]
359                              << " to " << outputUnits.c_str();
360      //      errmsg << "\nUsing coordinate value instead.\n";
361      DUCHAMPERROR("coordToVel", errmsg);
362      errflag = 1;
363    }
364    return coord;
365  }
366  else return pow( (coord*scale + offset), power);
367
368}
369
370double velToCoord(struct wcsprm *wcs, const float velocity,
371                  std::string outputUnits)
372{
373  ///  @details
374  ///   Convert the velocity given to the appropriate world coordinate for wcs.
375  ///   Does this by checking the ztype parameter in wcs to see if it is
376  ///    FREQ or otherwise, and converts accordingly.
377  ///
378  /// \param wcs  The wcsprm struct containing the WCS information.
379  /// \param velocity The input velocity.
380  /// \param outputUnits The string containing the units of the input velocity.
381  /// \return The WCS coordinate corresponding to the input velocity.
382
383  double scale, offset, power;
384  int specIndex = wcs->spec;
385  if(specIndex<0) specIndex = 2;
386  if(specIndex>=wcs->naxis) specIndex = wcs->naxis-1;
387  int status = wcsunits( outputUnits.c_str(), wcs->cunit[specIndex],
388                         &scale, &offset, &power);
389
390  if(status > 0){
391    std::stringstream errmsg;
392    errmsg << "WCSUNITS Error Code = " << status << ":" << wcsunits_errmsg[status];
393// << "\nUsing coordinate value instead.\n";
394    DUCHAMPERROR("velToCoord",errmsg.str());
395    return velocity;
396  }
397  else return (pow(velocity, 1./power) - offset) / scale;
398 
399}
Note: See TracBrowser for help on using the repository browser.