source: trunk/Detection/detection.cc @ 3

Last change on this file since 3 was 3, checked in by Matthew Whiting, 18 years ago

This is the first full import of all working code to
the Duchamp repository.
Made three directories at top level:

branches/ tags/ trunk/

and trunk/ has the full set of code:
ATrous/ Cubes/ Detection/ InputComplete? InputExample? README Utils/ docs/ mainDuchamp.cc param.cc param.hh

File size: 12.6 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <vector>
4#include <string>
5#include <wcs.h>
6#include <param.hh>
7#include <Detection/detection.hh>
8
9using std::setw;
10using std::setprecision;
11using std::endl;
12
13std::ostream& operator<< ( std::ostream& theStream, Voxel& vox)
14{
15  /**
16   * << operator for Voxel class
17   * A convenient way of printing the coordinate & flux values of a voxel.
18   */ 
19
20  theStream << setw(4) << vox.itsX ;
21  theStream << " " << setw(4) << vox.itsY;
22  theStream << " " << setw(4) << vox.itsZ;
23  theStream << setprecision(4);
24  theStream << "  " << vox.itsF;
25
26}
27
28
29void Detection::calcParams()
30{
31  /**
32   * Detection::calcParams()
33   *  A function that calculates centroid positions, minima & maxima of coordinates,
34   *   and total & peak fluxes for a detection.
35   */
36
37  this->xcentre = 0;
38  this->ycentre = 0;
39  this->zcentre = 0;
40  this->totalFlux = 0;
41  this->peakFlux = 0;
42  this->xmin = 0;
43  this->xmax = 0;
44  this->ymin = 0;
45  this->ymax = 0;
46  this->zmin = 0;
47  this->zmax = 0;
48  int *ctr = new int;
49  for((*ctr)=0;(*ctr)<this->pix.size();(*ctr)++){
50    this->xcentre   += this->pix[*ctr].itsX;
51    this->ycentre   += this->pix[*ctr].itsY;
52    this->zcentre   += this->pix[*ctr].itsZ;
53    this->totalFlux += this->pix[*ctr].itsF;
54    if(((*ctr)==0)||(this->pix[*ctr].itsX<this->xmin))     this->xmin     = this->pix[*ctr].itsX;
55    if(((*ctr)==0)||(this->pix[*ctr].itsX>this->xmax))     this->xmax     = this->pix[*ctr].itsX;
56    if(((*ctr)==0)||(this->pix[*ctr].itsY<this->ymin))     this->ymin     = this->pix[*ctr].itsY;
57    if(((*ctr)==0)||(this->pix[*ctr].itsY>this->ymax))     this->ymax     = this->pix[*ctr].itsY;
58    if(((*ctr)==0)||(this->pix[*ctr].itsZ<this->zmin))     this->zmin     = this->pix[*ctr].itsZ;
59    if(((*ctr)==0)||(this->pix[*ctr].itsZ>this->zmax))     this->zmax     = this->pix[*ctr].itsZ;
60    if(((*ctr)==0)||(this->pix[*ctr].itsF>this->peakFlux)) this->peakFlux = this->pix[*ctr].itsF;
61  }
62  delete ctr;
63  this->xcentre /= this->pix.size();
64  this->ycentre /= this->pix.size();
65  this->zcentre /= this->pix.size();
66}
67
68void Detection::calcWCSparams(wcsprm *wcs)
69{
70  /**
71   * Detection::calcWCSParams(wcsprm *)
72   *  Use the input wcs to calculate the position and velocity information for the Detection.
73   *  Makes no judgement as to whether the WCS is good -- this needs to be done beforehand.
74   *  Quantities calculated:
75   *     RA: ra (deg), ra (string), ra width.
76   *     Dec: dec (deg), dec (string), dec width.
77   *     Vel: vel (km/s), min & max vel, vel width.
78   *     Other: coord type for all three axes, nuRest, name (IAU-style, either equatorial or Galactic)
79   *     Uses getIntegFlux to calculate the integrated flux in (say) Jy km/s
80   */
81
82  int    *stat   = new int[5];
83  double *pixcrd = new double[15];
84  double *imgcrd = new double[15];
85  double *world  = new double[15];
86  double *phi    = new double[5];
87  double *theta  = new double[5];
88  /*
89  define a five-point array in 3D:
90     (x,y,z), (x,y,z1), (x,y,z2), (x1,y1,z), (x2,y2,z)
91   note x = central point, x1 = minimum x, x2 = maximum x etc.
92  */
93  pixcrd[0]  = pixcrd[3] = pixcrd[6] = this->xcentre;
94  pixcrd[9]  = this->xmin-0.5;
95  pixcrd[12] = this->xmax+0.5;
96  pixcrd[1]  = pixcrd[4] = pixcrd[7] = this->ycentre;
97  pixcrd[10] = this->ymin-0.5;
98  pixcrd[13] = this->ymax+0.5;
99  pixcrd[2] = pixcrd[11] = pixcrd[14] = this->zcentre;
100  pixcrd[5] = this->zmin;
101  pixcrd[8] = this->zmax;
102  wcsp2s(wcs, 5, 3, pixcrd, imgcrd, phi, theta, world, stat);
103  delete [] stat;
104  delete [] pixcrd;
105  delete [] imgcrd;
106  delete [] phi;
107  delete [] theta;
108
109  this->lngtype = wcs->lngtyp;
110  this->lattype = wcs->lattyp;
111  this->ztype   = wcs->ctype[2];
112  this->nuRest  = wcs->restfrq;
113  if(this->lngtype=="RA") this->lngRatio=15.;
114  else this->lngRatio = 1.;
115  this->ra   = world[0];
116  this->dec  = world[1];
117  this->raS  = decToDMS(this->ra/this->lngRatio,false);
118  this->decS = decToDMS(this->dec,true);
119  if(this->lngtype=="RA") this->name = getIAUNameEQ(this->ra,this->dec,wcs->equinox);
120  else this->name = getIAUNameGAL(this->ra,this->dec);
121  this->raWidth   = angularSeparation(world[9],world[1],world[12],world[1]) * 60.;
122  this->decWidth  = angularSeparation(world[0],world[10],world[0],world[13]) * 60.;
123  if(this->ztype=="FREQ"){
124    this->vel = C_kms * (this->nuRest*this->nuRest - world[2]*world[2]) /
125      (this->nuRest*this->nuRest + world[2]*world[2]);
126    this->velMin = C_kms * (this->nuRest*this->nuRest - world[5]*world[5]) /
127      (this->nuRest*this->nuRest + world[5]*world[5]);
128    this->velMax = C_kms * (this->nuRest*this->nuRest - world[8]*world[8]) /
129      (this->nuRest*this->nuRest + world[8]*world[8]);
130    this->velWidth = fabs(this->velMax - this->velMin);
131  }
132  else{
133    this->vel    = world[2] / 1000.;
134    this->velMin = world[5] / 1000.;
135    this->velMax = world[8] / 1000.;
136    this->velWidth = fabs(this->velMax - this->velMin);
137  }
138
139  this->getIntegFlux(wcs);
140
141  this->flagWCS = true;
142
143  delete [] world;
144
145}
146
147float Detection::getIntegFlux(wcsprm *wcs)
148{
149  /**
150   * Detection::getIntegFlux(wcsprm *)
151   *  Uses the input wcs to calculate the velocity-integrated flux,
152   *  putting velocity in units of km/s.
153   *  Integrates over full spatial and velocity range as given by extrema calculated
154   *  by calcWCSparams.
155   *  Units are (Jy/beam) . km/s  (no correction for the beam is made here...)
156   */
157
158  // include one pixel either side in each direction
159  int xsize = (this->xmax-this->xmin+3);
160  int ysize = (this->ymax-this->ymin+3);
161  int zsize = (this->zmax-this->zmin+3);
162  vector <bool> isObj(xsize*ysize*zsize,false);
163  vector <float> fluxArray(xsize*ysize*zsize,0.);
164  int    *stat   = new    int[xsize*ysize*zsize];
165  double *pixcrd = new double[xsize*ysize*zsize*3];
166  double *imgcrd = new double[xsize*ysize*zsize*3];
167  double *world  = new double[xsize*ysize*zsize*3];
168  double *phi    = new double[xsize*ysize*zsize];
169  double *theta  = new double[xsize*ysize*zsize];
170  for(int p=0;p<this->pix.size();p++){
171    int pos = (this->pix[p].getX()-this->xmin+1) + (this->pix[p].getY()-this->ymin+1)*xsize +
172      (this->pix[p].getZ()-this->zmin+1)*xsize*ysize;
173    fluxArray[pos] = this->pix[p].getF();
174    isObj[pos] = true;
175  }
176
177  for(int i=0;i<xsize*ysize*zsize;i++){
178    pixcrd[3*i]   = this->xmin -1 + i%xsize;
179    pixcrd[3*i+1] = this->ymin -1 + (i/xsize)%ysize;
180    pixcrd[3*i+2] = this->zmin -1 + i/(xsize*ysize);
181  }
182
183  wcsp2s(wcs, xsize*ysize*zsize, 3, pixcrd, imgcrd, phi, theta, world, stat);
184  for(int i=0;i<xsize*ysize*zsize;i++){
185    // put velocity coords into km/s
186    if(this->ztype=="FREQ")
187      world[3*i+2] = C_kms * (wcs->restfrq*wcs->restfrq - world[3*i+2]*world[3*i+2]) /
188        (wcs->restfrq*wcs->restfrq + world[3*i+2]*world[3*i+2]);
189    else world[3*i+2] /= 1000.;
190  }
191  delete [] stat;
192  delete [] pixcrd;
193  delete [] imgcrd;
194  delete [] phi;
195  delete [] theta;
196
197  this->intFlux = 0.;
198  for(int pix=0; pix<xsize*ysize; pix++){ // loop over each spatial pixel.
199    for(int z=0; z<zsize; z++){
200      int pos =  z*xsize*ysize + pix;
201      if(isObj[pos]){ // if it's an object pixel...
202        float deltaVel = (world[3*(pos+xsize*ysize)+2] - world[ 3*(pos-xsize*ysize)+2 ]) / 2.;
203        this->intFlux += fluxArray[pos] * fabsf(deltaVel);
204      }
205    }
206  }
207  delete [] world;
208}
209
210
211// void Detection::addAnObject(Detection &toAdd)
212// {
213  /**
214   * Detection::addAnObject(Detection &)
215   *  Combines two objects by adding all the pixels of the argument to the instigator.
216   *  All pixel & flux parameters are recalculated (so that calcParams does not need to be
217   *   called a second time), but WCS parameters are not.
218   */
219/*
220  int *ctr = new int;
221  this->xcentre *= this->pix.size();
222  this->ycentre *= this->pix.size();
223  this->zcentre *= this->pix.size();
224  for((*ctr)=0;(*ctr)<toAdd.getSize();(*ctr)++){
225    this->pix.push_back(toAdd.getPixel(*ctr));
226    this->xcentre += toAdd.getX(*ctr);
227    this->ycentre += toAdd.getY(*ctr);
228    this->zcentre += toAdd.getZ(*ctr);
229    this->totalFlux += toAdd.getF(*ctr);
230    if(toAdd.getX(*ctr)<this->xmin) this->xmin=toAdd.getX(*ctr);
231    if(toAdd.getX(*ctr)>this->xmax) this->xmax=toAdd.getX(*ctr);
232    if(toAdd.getY(*ctr)<this->ymin) this->ymin=toAdd.getY(*ctr);
233    if(toAdd.getY(*ctr)>this->ymax) this->ymax=toAdd.getY(*ctr);
234    if(toAdd.getZ(*ctr)<this->zmin) this->zmin=toAdd.getZ(*ctr);
235    if(toAdd.getZ(*ctr)>this->zmax) this->zmax=toAdd.getZ(*ctr);
236    if(toAdd.getF(*ctr)>this->peakFlux) this->peakFlux=toAdd.getF(*ctr);
237  }
238  this->xcentre /= this->pix.size();
239  this->ycentre /= this->pix.size();
240  this->zcentre /= this->pix.size();
241   
242  delete ctr;
243
244}
245*/
246
247
248void Detection::addAnObject(Detection &toAdd)
249{
250  /**
251   * Detection::addAnObject(Detection &)
252   *  Combines two objects by adding all the pixels of the argument to the instigator.
253   *  All pixel & flux parameters are recalculated (so that calcParams does not need to be
254   *   called a second time), but WCS parameters are not.
255   */
256
257  int *ctr = new int;
258  int *ctr2 = new int;
259  bool *isNewPix = new bool;
260  this->xcentre *= this->pix.size();
261  this->ycentre *= this->pix.size();
262  this->zcentre *= this->pix.size();
263  for((*ctr)=0;(*ctr)<toAdd.getSize();(*ctr)++){
264    // For each pixel in the new object, test to see if it already appears in the object
265    long *x = new long;
266    *x = toAdd.getX(*ctr);
267    long *y = new long;
268    *y = toAdd.getY(*ctr);
269    long *z = new long;
270    *z = toAdd.getZ(*ctr);
271    float *f = new float;
272    *f = toAdd.getF(*ctr);
273    *isNewPix = true;
274    *ctr2 = 0;
275    while( *isNewPix && (*ctr2<this->pix.size()) ){
276      *isNewPix = *isNewPix && (( this->pix[*ctr2].itsX != *x ) ||
277                                ( this->pix[*ctr2].itsY != *y ) ||
278                                ( this->pix[*ctr2].itsZ != *z ) );
279      *ctr2 += 1;
280    }
281    if(*isNewPix){
282      // If the pixel is new, add it to the object and re-calculate the parameters.
283      this->pix.push_back(toAdd.getPixel(*ctr));
284      this->xcentre += *x;
285      this->ycentre += *y;
286      this->zcentre += *z;
287      this->totalFlux += *f;
288      if(*x<this->xmin) this->xmin=*x;
289      if(*x>this->xmax) this->xmax=*x;
290      if(*y<this->ymin) this->ymin=*y;
291      if(*y>this->ymax) this->ymax=*y;
292      if(*z<this->zmin) this->zmin=*z;
293      if(*z>this->zmax) this->zmax=*z;
294      if(*f>this->peakFlux) this->peakFlux=*f;
295    }
296    delete x,y,z,f;
297  }
298  this->xcentre /= this->pix.size();
299  this->ycentre /= this->pix.size();
300  this->zcentre /= this->pix.size();
301   
302  delete ctr;
303  delete ctr2;
304  delete isNewPix;
305}
306
307
308void Detection::addOffsets(Param &par)
309{
310  this->xSubOffset = par.getXOffset();
311  this->ySubOffset = par.getYOffset();
312  this->zSubOffset = par.getZOffset();
313}
314
315bool Detection::hasEnoughChannels(int minNumber)
316{
317  /**
318   *  bool hasEnoughChannels(int)
319   *    A function to determine if the Detection has enough
320   *    contiguous channels to meet the minimum requirement
321   *    given as the argument.
322   *    Needs to have at least one occurence of minNumber consecutive
323   *    channels present to return true. Otherwise returns false.
324   */
325
326  // Original requirement -- based on total span
327// int numChannels = this->getZmax() - this->getZmin() + 1;
328
329// Alternative -- number of distinct channels detected
330//   int numChannels = 0;
331//   this->SortByZ();
332//   if(this->getSize()>0) numChannels++;
333//   for(int i=1;i<this->getSize();i++)
334//     if(this->getZ(i)>this->getZ(i-1)) numChannels++; 
335//   return (numChannels < minNumber);
336
337// Preferred method -- need a set of minNumber consecutive channels present.
338  this->SortByZ();
339  int numChannels = 0;
340  bool result = false;
341  if(this->getSize()>0) numChannels++;
342  for(int i=1;i<this->getSize();i++) {
343    if( (this->getZ(i) - this->getZ(i-1)) == 1) numChannels++;
344    else if( (this->getZ(i) - this->getZ(i-1)) >= 2) numChannels = 1;
345
346    if( numChannels == minNumber) result = true;
347  }
348  return result;
349 
350}
351
352std::ostream& operator<< ( std::ostream& theStream, Detection& obj)
353{
354  /**
355   * << operator for Detection class
356   *  A convenient way of printing the coordinate & flux
357   *  values for each pixel in the Detection
358   */ 
359
360  for(int i=0;i<obj.pix.size();i++) theStream << obj.pix[i] << endl;
361  theStream<<"---"<<endl;
362}
363
364Detection combineObjects(Detection &first, Detection &second)
365{
366  // make the new object
367  int *ctr = new int;
368  Detection *newObject = new Detection;
369  for(*ctr=0;(*ctr)<first.getSize();(*ctr)++){
370    newObject->addPixel(first.getPixel(*ctr));
371  }
372  for(*ctr=0;(*ctr)<second.getSize();(*ctr)++){
373    newObject->addPixel(second.getPixel(*ctr));
374  }
375  delete ctr;
376  newObject->calcParams();
377  return *newObject;
378}
379
380vector <Detection> combineLists(vector <Detection> &first, vector <Detection> &second)
381{
382  // make the new object
383  vector <Detection> newList(first.size()+second.size());
384  for(int i=0;i<first.size();i++) newList[i] = first[i];
385  for(int i=0;i<second.size();i++) newList[i+first.size()] = second[i];
386 
387  return newList;
388}
389
Note: See TracBrowser for help on using the repository browser.