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

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

Some changes prompted by askapsoft development.

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