source: tags/release-1.6.1/src/Cubes/spectraUtils.cc @ 1441

Last change on this file since 1441 was 1393, checked in by MatthewWhiting, 10 years ago

A large changeset that moves all use of bool arrays (ie. bool *) to std::vector<bool>. This will be a bit safer, plus potentially cheaper in memory usage. Interfaces to all stats functions with masks have changed accordingly, as well as the Gaussian smoothing functions and some spectral utility functions.

File size: 12.9 KB
Line 
1// -----------------------------------------------------------------------
2// spectraUtils.cc: Utility functions to obtain & manipulate spectra
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 <fstream>
30#include <iomanip>
31#include <sstream>
32#include <string>
33#include <vector>
34#include <math.h>
35#include <wcslib/wcs.h>
36#include <duchamp/Cubes/cubeUtils.hh>
37#include <duchamp/param.hh>
38#include <duchamp/duchamp.hh>
39#include <duchamp/fitsHeader.hh>
40#include <duchamp/PixelMap/Object3D.hh>
41#include <duchamp/Cubes/cubes.hh>
42#include <duchamp/Utils/utils.hh>
43
44using namespace PixelInfo;
45
46namespace duchamp
47{
48
49  void getSpecAbscissae(Detection &object, FitsHeader &head, size_t zdim, float *abscissae)
50  {
51    /// @details
52    ///  A function that returns an array of
53    ///  frequency/velocity/channel/etc values (that can be used as the
54    ///  abscissae on the spectral plot).
55    ///  \param object The object on which our spectrum is centered (in
56    ///  case the spectral value changes with x & y
57    ///  \param head The FitsHeader set of parameters that determine the coordinate transformation.
58    ///  \param zdim The length of the spectral axis
59    ///  \param abscissae The array of spectral values -- must be allocated first
60
61    getSpecAbscissae(head,object.getXcentre(),object.getYcentre(),zdim, abscissae);
62  }
63
64  void getSpecAbscissae(FitsHeader &head, float xpt, float ypt, size_t zdim, float *abscissae)
65  {
66    /// @details
67    ///  A function that returns an array of
68    ///  frequency/velocity/channel/etc values (that can be used as the
69    ///  horizontal axis on the spectral plot).
70    ///  \param head The FitsHeader set of parameters that determine the coordinate transformation.
71    ///  \param xpt The x-value of the spatial position on which our spectrum is centred.
72    ///  \param ypt The y-value of the spatial position on which our spectrum is centred.
73    ///  \param zdim The length of the spectral axis
74    ///  \param abscissae The array of spectral values -- must be allocated first.
75
76    if(head.isWCS()){
77      double xval = double(xpt);
78      double yval = double(ypt);
79      for(double zval=0;zval<zdim;zval++)
80        abscissae[int(zval)] = head.pixToVel(xval,yval,zval);
81    }
82    else
83      for(double zval=0;zval<zdim;zval++) abscissae[int(zval)] = zval;
84
85  }
86  //--------------------------------------------------------------------
87
88    void getIntSpec(Detection &object, float *fluxArray, size_t *dimArray, std::vector<bool> mask,
89                  float beamCorrection, float *spec)
90  {
91    /// @details
92    ///  The base function that extracts an integrated spectrum for a
93    ///  given object from a pixel array. The spectrum is returned as
94    ///  the integrated flux, corrected for the beam using the given
95    ///  correction factor.
96    ///   \param object The Detection in question
97    ///   \param fluxArray The full array of pixel values.
98    ///   \param dimArray The axis dimensions for the fluxArray
99    ///   \param mask A mask array indicating whether given pixels are valid
100    ///   \param beamCorrection How much to divide the summed spectrum
101    ///   by to return the integrated flux.
102    ///   \param spec The integrated spectrum for the object -- must be allocated first.
103
104    for(size_t i=0;i<dimArray[2];i++) spec[i] = 0.;
105    size_t xySize = dimArray[0]*dimArray[1];
106    std::vector<bool> done(xySize,false);
107    std::vector<Voxel> voxlist = object.getPixelSet();
108    std::vector<Voxel>::iterator vox;
109    for(vox=voxlist.begin();vox<voxlist.end();vox++){
110      size_t pos = vox->getX() + dimArray[0] * vox->getY();
111      if(!done[pos]){
112        done[pos] = true;
113        for(size_t z=0;z<dimArray[2];z++){
114          if(mask[pos+z*xySize]){
115            spec[z] += fluxArray[pos + z*xySize] / beamCorrection;
116          }         
117        }
118      }
119    }
120
121  }
122  //--------------------------------------------------------------------
123
124    void getPeakSpec(Detection &object, float *fluxArray, size_t *dimArray, std::vector<bool> mask, float *spec)
125  {
126    /// @details
127    ///  The base function that extracts an peak spectrum for a
128    ///  given object from a pixel array. The spectrum is returned as
129    ///  the integrated flux, corrected for the beam using the given
130    ///  correction factor.
131    ///   \param object The Detection in question
132    ///   \param fluxArray The full array of pixel values.
133    ///   \param dimArray The axis dimensions for the fluxArray
134    ///   \param mask A mask array indicating whether given pixels are valid
135    ///   \param spec The peak spectrum for the object -- must be allocated first
136
137    if((object.getXPeak()<0 || object.getXPeak()>=int(dimArray[0])) || (object.getYPeak()<0 || object.getYPeak()>=int(dimArray[1]))){
138      DUCHAMPWARN("getPeakSpec","Object peak outside array boundaries");
139      for (size_t z=0;z<dimArray[2];z++) spec[z]=0.;
140    }
141    else{
142      size_t xySize = dimArray[0]*dimArray[1];
143      size_t pos = object.getXPeak() + dimArray[0]*object.getYPeak();
144      for(size_t z=0;z<dimArray[2];z++){
145        if(mask[pos + z*xySize])
146          spec[z] = fluxArray[pos + z*xySize];
147      }
148    }
149  }
150  //--------------------------------------------------------------------
151
152
153  void Cube::getSpectralArrays(int objNum, float *specx, float *specy,
154                               float *specRecon, float *specBase)
155  {
156    /// @details
157    ///  A utility function that goes and calculates, for a given
158    ///  Detection, the spectral arrays, according to whether we want
159    ///  the peak or integrated flux. The arrays can be used by
160    ///  Cube::plotSpectrum() and Cube::writeSpectralData(). The arrays
161    ///  calculated are listed below. Their length is given by the
162    ///  length of the Cube's spectral dimension.
163    ///
164    ///  Note that the arrays need to be allocated prior to calling
165    ///  this function.
166    ///
167    ///  \param objNum The number of the object under
168    ///         consideration. If negative, we extract the single
169    ///         spectrum at (x,y)=(0,0) (useful for the 1D case).
170    ///  \param specx The array of frequency/velocity/channel/etc
171    ///         values (the x-axis on the spectral plot).
172    ///  \param specy The array of flux values, matching the specx
173    ///         array.
174    ///  \param specRecon The reconstructed or smoothed array, done in
175    ///         the same way as specy.
176    ///  \param specBase The fitted baseline values, done in the same
177    ///         way as specy.
178
179    size_t xdim = this->axisDim[0];
180    size_t ydim = this->axisDim[1];
181    size_t zdim = this->axisDim[2];
182       
183    for(size_t i=0;i<zdim;i++){
184      specy[i]     = 0.;
185      specRecon[i] = 0.;
186      specBase[i]  = 0.;
187    }
188
189    double xloc,yloc;
190    size_t spatpos=0;
191    std::vector<Voxel> voxlist;
192    if(objNum>=0){
193      if(this->par.getSpectralMethod()=="sum"){
194        xloc=double(this->objectList->at(objNum).getXcentre());
195        yloc=double(this->objectList->at(objNum).getYcentre());
196        voxlist = this->objectList->at(objNum).getPixelSet();
197      }
198      else{
199        spatpos = this->objectList->at(objNum).getXPeak() +
200        xdim*this->objectList->at(objNum).getYPeak();
201      }
202    }
203
204    if(this->head.isWCS()){
205//       double xval = double(this->objectList->at(objNum).getXcentre());
206//       double yval = double(this->objectList->at(objNum).getYcentre());
207//       for(double zval=0;zval<zdim;zval++)
208//      specx[int(zval)] = this->head.pixToVel(xval,yval,zval);
209      for(double zval=0;zval<zdim;zval++)
210        specx[int(zval)] = this->head.pixToVel(xloc,yloc,zval);
211    }
212    else
213      for(double zval=0;zval<zdim;zval++) specx[int(zval)] = zval;
214       
215    float beamCorrection;
216    if(this->header().needBeamSize())
217      beamCorrection = this->head.beam().area();
218    else beamCorrection = 1.;
219       
220    if(objNum>=0 && this->par.getSpectralMethod()=="sum"){
221      std::vector<bool> done(xdim*ydim,false);
222      std::vector<Voxel>::iterator vox;
223      for(vox=voxlist.begin();vox<voxlist.end();vox++){
224        spatpos = vox->getX() + xdim * vox->getY();
225        if(!done[spatpos]){
226          done[spatpos] = true;
227          for(size_t z=0;z<zdim;z++){
228            if(!(this->isBlank(spatpos+z*xdim*ydim))){
229              specy[z] += this->array[spatpos + z*xdim*ydim] / beamCorrection;
230              if(this->reconExists)
231                specRecon[z] += this->recon[spatpos + z*xdim*ydim] / beamCorrection;
232              if(this->par.getFlagBaseline())
233                specBase[z] += this->baseline[spatpos + z*xdim*ydim] / beamCorrection;
234            }       
235          }
236        }
237      }
238    }
239    else {// if(par.getSpectralMethod()=="peak"){
240//       size_t spatpos = this->objectList->at(objNum).getXPeak() +
241//      xdim*this->objectList->at(objNum).getYPeak();
242      for(size_t z=0;z<zdim;z++){
243        specy[z] = this->array[spatpos + z*xdim*ydim];
244        if(this->reconExists)
245          specRecon[z] = this->recon[spatpos + z*xdim*ydim];
246        if(this->par.getFlagBaseline())
247          specBase[z] = this->baseline[spatpos + z*xdim*ydim];
248      }
249    }
250
251  }
252  //--------------------------------------------------------------------
253
254  void getSmallVelRange(Detection &obj, FitsHeader &head,
255                        double *minvel, double *maxvel)
256  {
257    ///  @details
258    ///  Routine to calculate the velocity range for the zoomed-in region.
259    ///  This range should be the maximum of 20 pixels, or 3x the wdith of
260    ///   the detection.
261    ///  Need to :
262    ///      Calculate pixel width of a 3x-detection-width region.
263    ///      If smaller than 20, calculate velocities of central vel +- 10 pixels
264    ///      If not, use the 3x-detection-width
265    ///  Range returned via "minvel" and "maxvel" parameters.
266    ///  \param obj Detection under examination.
267    ///  \param head FitsHeader, containing the WCS information.
268    ///  \param minvel Returned value of minimum velocity
269    ///  \param maxvel Returned value of maximum velocity
270
271    double *pixcrd = new double[3];
272    double *world  = new double[3];
273    float minpix,maxpix;
274    // define new velocity extrema
275    //    -- make it 3x wider than the width of the detection.
276    *minvel = 0.5*(obj.getVelMin()+obj.getVelMax()) - 1.5*obj.getVelWidth();
277    *maxvel = 0.5*(obj.getVelMin()+obj.getVelMax()) + 1.5*obj.getVelWidth();
278    // Find velocity range in number of pixels:
279    world[0] = obj.getRA();
280    world[1] = obj.getDec();
281    world[2] = head.velToSpec(*minvel);
282    head.wcsToPix(world,pixcrd);
283    minpix = pixcrd[2];
284    world[2] = head.velToSpec(*maxvel);
285    head.wcsToPix(world,pixcrd);
286    maxpix = pixcrd[2];
287    if(maxpix<minpix) std::swap(maxpix,minpix);
288   
289    if((maxpix - minpix + 1) < 20){
290      pixcrd[0] = double(obj.getXcentre());
291      pixcrd[1] = double(obj.getYcentre());
292      pixcrd[2] = obj.getZcentre() - 10.;
293      head.pixToWCS(pixcrd,world);
294      //    *minvel = setVel_kms(wcs,world[2]);
295      *minvel = head.specToVel(world[2]);
296      pixcrd[2] = obj.getZcentre() + 10.;
297      head.pixToWCS(pixcrd,world);
298      //     *maxvel = setVel_kms(wcs,world[2]);
299      *maxvel = head.specToVel(world[2]);
300      if(*maxvel<*minvel) std::swap(*maxvel,*minvel);
301    }
302    delete [] pixcrd;
303    delete [] world;
304
305  }
306  //--------------------------------------------------------------------
307
308  void getSmallZRange(Detection &obj, double *minz, double *maxz)
309  {
310    ///  @details
311    ///  Routine to calculate the pixel range for the zoomed-in spectrum.
312    ///  This range should be the maximum of 20 pixels, or 3x the width
313    ///   of the detection.
314    ///  Need to :
315    ///      Calculate pixel width of a 3x-detection-width region.
316    ///       If smaller than 20, use central pixel +- 10 pixels
317    ///  Range returned via "minz" and "maxz" parameters.
318    ///  \param obj Detection under examination.
319    ///  \param minz Returned value of minimum z-pixel coordinate
320    ///  \param maxz Returned value of maximum z-pixel coordinate
321
322    *minz = 2.*obj.getZmin() - obj.getZmax();
323    *maxz = 2.*obj.getZmax() - obj.getZmin();
324   
325    if((*maxz - *minz + 1) < 20){
326      *minz = obj.getZcentre() - 10.;
327      *maxz = obj.getZcentre() + 10.;
328    }
329
330  }
331  //--------------------------------------------------------------------
332
333}
Note: See TracBrowser for help on using the repository browser.