source: branches/pixel-map-branch/src/Detection/detection.cc @ 1213

Last change on this file since 1213 was 252, checked in by Matthew Whiting, 17 years ago
  • Have put all classes in the files in src/PixelMap/ into a PixelInfo? namespace.
  • Added "using namespace PixelInfo?" to all necessary files.
  • Removed "friend class Detection" from Voxel and Object3D classes -- not necessary and complicated now by them being in the namespace
  • Various minor changes, including fixing up commentary.
File size: 12.0 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <vector>
4#include <string>
5#include <wcs.h>
6#include <math.h>
7#include <param.hh>
8#include <Utils/utils.hh>
9#include <PixelMap/Voxel.hh>
10#include <PixelMap/Object3D.hh>
11#include <Detection/detection.hh>
12
13using std::setw;
14using std::setprecision;
15using std::endl;
16using std::vector;
17
18using namespace PixelInfo;
19
20Detection::Detection(const Detection& d)
21{
22  pixelArray      = d.pixelArray;
23  xSubOffset      = d.xSubOffset;
24  ySubOffset      = d.ySubOffset;
25  zSubOffset      = d.zSubOffset;
26  totalFlux       = d.totalFlux;
27  intFlux         = d.intFlux;
28  peakFlux        = d.peakFlux;
29  xpeak           = d.xpeak;
30  ypeak           = d.ypeak;
31  zpeak           = d.zpeak;
32  peakSNR         = d.peakSNR;
33  negSource       = d.negSource;
34  flagText        = d.flagText;
35  id              = d.id;
36  name            = d.name;
37  flagWCS         = d.flagWCS;
38  raS             = d.raS;
39  decS            = d.decS;
40  ra              = d.ra;
41  dec             = d.dec;
42  raWidth         = d.raWidth;
43  decWidth        = d.decWidth;
44  specUnits       = d.specUnits;
45  fluxUnits       = d.fluxUnits;
46  intFluxUnits    = d.intFluxUnits;
47  lngtype         = d.lngtype;
48  lattype         = d.lattype;
49  vel             = d.vel;
50  velWidth        = d.velWidth;
51  velMin          = d.velMin;
52  velMax          = d.velMax;
53  posPrec         = d.posPrec;
54  xyzPrec         = d.xyzPrec;
55  fintPrec        = d.fintPrec;
56  fpeakPrec       = d.fpeakPrec;
57  velPrec         = d.velPrec;
58  snrPrec         = d.snrPrec;
59}
60
61//--------------------------------------------------------------------
62
63  Detection& Detection::operator= (const Detection& d)
64{
65  pixelArray      = d.pixelArray;
66  xSubOffset      = d.xSubOffset;
67  ySubOffset      = d.ySubOffset;
68  zSubOffset      = d.zSubOffset;
69  totalFlux       = d.totalFlux;
70  intFlux         = d.intFlux;
71  peakFlux        = d.peakFlux;
72  xpeak           = d.xpeak;
73  ypeak           = d.ypeak;
74  zpeak           = d.zpeak;
75  peakSNR         = d.peakSNR;
76  negSource       = d.negSource;
77  flagText        = d.flagText;
78  id              = d.id;
79  name            = d.name;
80  flagWCS         = d.flagWCS;
81  raS             = d.raS;
82  decS            = d.decS;
83  ra              = d.ra;
84  dec             = d.dec;
85  raWidth         = d.raWidth;
86  decWidth        = d.decWidth;
87  specUnits       = d.specUnits;
88  fluxUnits       = d.fluxUnits;
89  intFluxUnits    = d.intFluxUnits;
90  lngtype         = d.lngtype;
91  lattype         = d.lattype;
92  vel             = d.vel;
93  velWidth        = d.velWidth;
94  velMin          = d.velMin;
95  velMax          = d.velMax;
96  posPrec         = d.posPrec;
97  xyzPrec         = d.xyzPrec;
98  fintPrec        = d.fintPrec;
99  fpeakPrec       = d.fpeakPrec;
100  velPrec         = d.velPrec;
101  snrPrec         = d.snrPrec;
102}
103
104//--------------------------------------------------------------------
105
106void Detection::calcFluxes(float *fluxArray, long *dim)
107{
108  /**
109   *  A function that calculates total & peak fluxes (and the location
110   *  of the peak flux) for a Detection.
111   *
112   *  \param fluxArray The array of flux values to calculate the
113   *  flux parameters from.
114   *  \param dim The dimensions of the flux array.
115   */
116
117  this->totalFlux = this->peakFlux = 0;
118
119  long x,y,z,count=0;
120
121  for(int m=0; m<this->pixelArray.getNumChanMap(); m++)
122    {
123      ChanMap tempmap = this->pixelArray.getChanMap(m);
124      z = tempmap.getZ();
125      for(int s=0; s<tempmap.getNumScan(); s++)
126        {
127          Scan tempscan = tempmap.getScan(s);
128          y = tempscan.getY();
129          for(long x=tempscan.getX(); x<=tempscan.getXmax(); x++)
130            {
131
132              float f = fluxArray[x + y*dim[0] + z*dim[0]*dim[1]];
133              this->totalFlux += f;
134              if( (count==0) ||  //first time round
135                  (this->negSource&&(f<this->peakFlux)) ||
136                  (!this->negSource&&(f>this->peakFlux))   )
137                {
138                  this->peakFlux = f;
139                  this->xpeak =    x;
140                  this->ypeak =    y;
141                  this->zpeak =    z;
142                }
143              count++;
144            }
145        }
146    }
147}
148//--------------------------------------------------------------------
149
150void Detection::calcWCSparams(float *fluxArray, long *dim, FitsHeader &head)
151{
152  /**
153   *  Use the input wcs to calculate the position and velocity
154   *    information for the Detection.
155   *  Quantities calculated:
156   *  <ul><li> RA: ra [deg], ra (string), ra width.
157   *      <li> Dec: dec [deg], dec (string), dec width.
158   *      <li> Vel: vel [km/s], min & max vel, vel width.
159   *      <li> coord type for all three axes, nuRest,
160   *      <li> name (IAU-style, in equatorial or Galactic)
161   *  </ul>
162   *  Uses Detection::getIntegFlux(FitsHeader &) to calculate the
163   *  integrated flux in (say) [Jy km/s]
164   *
165   *  Note that the regular parameters are NOT recalculated!
166   *
167   *  \param fluxArray The array of flux values to calculate the
168   *  integrated flux from.
169   *  \param dim The dimensions of the flux array.
170   *  \param head FitsHeader object that contains the WCS information.
171   */
172
173  if(head.isWCS()){
174
175    double *pixcrd = new double[15];
176    double *world  = new double[15];
177    /*
178      define a five-point array in 3D:
179      (x,y,z), (x,y,z1), (x,y,z2), (x1,y1,z), (x2,y2,z)
180      [note: x = central point, x1 = minimum x, x2 = maximum x etc.]
181      and convert to world coordinates.   
182    */
183    pixcrd[0]  = pixcrd[3] = pixcrd[6] = this->getXcentre();
184    pixcrd[9]  = this->getXmin()-0.5;
185    pixcrd[12] = this->getXmax()+0.5;
186    pixcrd[1]  = pixcrd[4] = pixcrd[7] = this->getYcentre();
187    pixcrd[10] = this->getYmin()-0.5;
188    pixcrd[13] = this->getYmax()+0.5;
189    pixcrd[2] = pixcrd[11] = pixcrd[14] = this->getZcentre();
190    pixcrd[5] = this->getZmin();
191    pixcrd[8] = this->getZmax();
192    int flag = head.pixToWCS(pixcrd, world, 5);
193    delete [] pixcrd;
194
195    // world now has the WCS coords for the five points
196    //    -- use this to work out WCS params
197 
198    this->lngtype = head.getWCS()->lngtyp;
199    this->lattype = head.getWCS()->lattyp;
200    this->specUnits = head.getSpectralUnits();
201    this->fluxUnits = head.getFluxUnits();
202    // if fluxUnits are eg. Jy/beam, make intFluxUnits = Jy km/s
203    this->intFluxUnits = head.getIntFluxUnits();
204    this->ra   = world[0];
205    this->dec  = world[1];
206    this->raS  = decToDMS(this->ra, this->lngtype);
207    this->decS = decToDMS(this->dec,this->lattype);
208    this->raWidth = angularSeparation(world[9],world[1],world[12],world[1])*60.;
209    this->decWidth  = angularSeparation(world[0],world[10],world[0],world[13]) * 60.;
210    this->name = head.getIAUName(this->ra, this->dec);
211    this->vel    = head.specToVel(world[2]);
212    this->velMin = head.specToVel(world[5]);
213    this->velMax = head.specToVel(world[8]);
214    this->velWidth = fabs(this->velMax - this->velMin);
215
216    this->getIntegFlux(fluxArray,dim,head);
217   
218    this->flagWCS = true;
219
220    delete [] world;
221
222  }
223}
224//--------------------------------------------------------------------
225
226float Detection::getIntegFlux(float *fluxArray, long *dim, FitsHeader &head)
227{
228  /**
229   *  Uses the input WCS to calculate the velocity-integrated flux,
230   *   putting velocity in units of km/s.
231   *  Integrates over full spatial and velocity range as given
232   *   by the extrema calculated by calcWCSparams.
233   *  If the flux units end in "/beam" (eg. Jy/beam), then the
234   *   flux is corrected by the beam size (in pixels).
235   *
236   *  \param fluxArray The array of flux values.
237   *  \param dim The dimensions of the flux array.
238   *  \param head FitsHeader object that contains the WCS information.
239   */
240
241  // include one pixel either side in each direction
242  long xsize = (this->getXmax()-this->getXmin()+3);
243  long ysize = (this->getYmax()-this->getYmin()+3);
244  long zsize = (this->getZmax()-this->getZmin()+3);
245  vector <bool> isObj(xsize*ysize*zsize,false);
246  vector <float> localFlux(xsize*ysize*zsize,0.);
247  // work out which pixels are object pixels
248  for(int m=0; m<this->pixelArray.getNumChanMap(); m++){
249    ChanMap tempmap = this->pixelArray.getChanMap(m);
250    long z = this->pixelArray.getChanMap(m).getZ();
251    for(int s=0; s<this->pixelArray.getChanMap(m).getNumScan(); s++){
252      long y = this->pixelArray.getChanMap(m).getScan(s).getY();
253      for(long x=this->pixelArray.getChanMap(m).getScan(s).getX();
254          x<=this->pixelArray.getChanMap(m).getScan(s).getXmax();
255          x++){
256        long pos = (x-this->getXmin()+1) + (y-this->getYmin()+1)*xsize
257          + (z-this->getZmin()+1)*xsize*ysize;
258        localFlux[pos] = fluxArray[x + y*dim[0] + z*dim[0]*dim[1]];
259        isObj[pos] = true;
260      }
261    }
262  }
263 
264  // work out the WCS coords for each pixel
265  double *world  = new double[xsize*ysize*zsize];
266  double xpt,ypt,zpt;
267  for(int i=0;i<xsize*ysize*zsize;i++){
268    xpt = double( this->getXmin() -1 + i%xsize );
269    ypt = double( this->getYmin() -1 + (i/xsize)%ysize );
270    zpt = double( this->getZmin() -1 + i/(xsize*ysize) );
271    world[i] = head.pixToVel(xpt,ypt,zpt);
272  }
273
274  this->intFlux = 0.;
275  for(int pix=0; pix<xsize*ysize; pix++){ // loop over each spatial pixel.
276    for(int z=0; z<zsize; z++){
277      int pos =  z*xsize*ysize + pix;
278      if(isObj[pos]){ // if it's an object pixel...
279        float deltaVel;
280        if(z==0)
281          deltaVel = (world[pos+xsize*ysize] - world[pos]);
282        else if(z==(zsize-1))
283          deltaVel = (world[pos] - world[pos-xsize*ysize]);
284        else
285          deltaVel = (world[pos+xsize*ysize] - world[pos-xsize*ysize]) / 2.;
286        this->intFlux += localFlux[pos] * fabs(deltaVel);
287      }
288    }
289  }
290
291  // correct for the beam size if the flux units string ends in "/beam"
292  int size = this->fluxUnits.size();
293  std::string tailOfFluxUnits = this->fluxUnits.substr(size-5,size);
294  if(tailOfFluxUnits == "/beam") this->intFlux /= head.getBeamSize();
295
296  delete [] world;
297}
298//--------------------------------------------------------------------
299
300Detection operator+ (Detection lhs, Detection rhs)
301{
302  /**
303   *  Combines two objects by adding all the pixels using the Object3D
304   *  operator.
305   *
306   *  The pixel parameters are recalculated in the process (equivalent
307   *  to calling pixels().calcParams()), but WCS parameters
308   *  are not.
309   */
310  Detection output;
311  output.pixelArray = lhs.pixelArray + rhs.pixelArray;
312//   output.totalFlux  = lhs.totalFlux  + rhs.totalFlux;
313//   if(lhs.peakFlux > rhs.peakFlux){
314//     output.peakFlux = lhs.peakFlux;
315//     output.xpeak    = lhs.xpeak;
316//     output.ypeak    = lhs.ypeak;
317//     output.zpeak    = lhs.zpeak;
318//     output.peakSNR  = lhs.peakSNR;
319//   }
320//   else{
321//     output.peakFlux = rhs.peakFlux;
322//     output.xpeak    = rhs.xpeak;
323//     output.ypeak    = rhs.ypeak;
324//     output.zpeak    = rhs.zpeak;
325//     output.peakSNR  = rhs.peakSNR;
326//   }
327  return output;
328}
329//--------------------------------------------------------------------
330
331void Detection::setOffsets(Param &par)
332{
333  /**
334   * This function stores the values of the offsets for each cube axis.
335   * The offsets are the starting values of the cube axes that may differ from
336   *  the default value of 0 (for instance, if a subsection is being used).
337   * The values will be used when the detection is outputted.
338   */
339  this->xSubOffset = par.getXOffset();
340  this->ySubOffset = par.getYOffset();
341  this->zSubOffset = par.getZOffset();
342}
343//--------------------------------------------------------------------
344
345bool Detection::hasEnoughChannels(int minNumber)
346{
347  /**
348   * A function to determine if the Detection has enough
349   * contiguous channels to meet the minimum requirement
350   * given as the argument.
351   * \param minNumber How many channels is the minimum acceptable number?
352   * \return True if there is at least one occurence of minNumber consecutive
353   * channels present to return true. False otherwise.
354   */
355
356// Preferred method -- need a set of minNumber consecutive channels present.
357  this->pixelArray.order();
358  int numChannels = 0;
359  bool result = false;
360  int size = this->pixelArray.getNumChanMap();
361  if(size>0) numChannels++;
362  for(int i=1;(i<size && !result);i++) {
363    if( (this->pixelArray.getZ(i) - this->pixelArray.getZ(i-1)) == 1)
364      numChannels++;
365    else if( (this->pixelArray.getZ(i) - this->pixelArray.getZ(i-1)) >= 2)
366      numChannels = 1;
367
368    if( numChannels >= minNumber) result = true;
369  }
370  return result;
371 
372}
373//--------------------------------------------------------------------
374
375std::ostream& operator<< ( std::ostream& theStream, Detection& obj)
376{
377  /**
378   *  A convenient way of printing the coordinate values for each
379   *  pixel in the Detection. 
380   *
381   *  NOTE THAT THERE IS CURRENTLY NO FLUX INFORMATION BEING PRINTED!
382   *
383   *  Use as front end to the Object3D::operator<< function.
384   */ 
385
386  theStream << obj.pixelArray << "---\n";
387}
388//--------------------------------------------------------------------
389
Note: See TracBrowser for help on using the repository browser.