source: trunk/Cubes/cubes.cc @ 53

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

Added some improved stats and image segmenting routines:
Utils/getStats.cc -- added functions to calculate the individual stats,

so eg. if one only wants the median, one calculates
it and not the madfm as well.

Utils/utils.hh -- prototypes for above functions added
Cubes/cubes.cc -- added extractImage and extractSpectrum as easy tasks

to get a particular spectrum or channel map.
Also findStats, which calculates the correct stats
for the image.

Cubes/cubes.hh -- Prototypes for above functions
Cubes/cubicSearch.cc -- Made use of the above functions
ATrous/ReconSearch.cc -- Made use of the above functions

File size: 14.3 KB
Line 
1#include <iostream>
2#include <iomanip>
3#include <vector>
4#include <string>
5#include <wcs.h>
6#include <Cubes/cubes.hh>
7#include <Utils/utils.hh>
8using std::endl;
9
10/****************************************************************/
11///////////////////////////////////////////////////
12//// Functions for DataArray class:
13///////////////////////////////////////////////////
14
15DataArray::DataArray(short int nDim, long size){
16  // need error handling in case size<0 !!!
17  if(size>0) this->array = new float[size];
18  this->numPixels = size;
19  if(nDim>0) this->axisDim = new long[nDim];
20  this->numDim = nDim;
21}
22
23DataArray::DataArray(short int nDim, long *dimensions){
24  int size = dimensions[0];
25  for(int i=1;i<nDim;i++) size *= dimensions[i];
26  this->numPixels = size;
27  if(size>0){
28    this->array = new float[size];
29//     this->blankarray = new bool[size];
30  }
31  this->numDim=nDim;
32  if(nDim>0) this->axisDim = new long[nDim];
33  for(int i=0;i<nDim;i++) this->axisDim[i] = dimensions[i];
34}
35
36void DataArray::getDimArray(long *output){
37  for(int i=0;i<this->numDim;i++) output[i] = this->axisDim[i];
38}
39
40void DataArray::getArray(float *output){
41  for(int i=0;i<this->numPixels;i++) output[i] = this->array[i];
42}
43
44void DataArray::saveArray(float *input, long size){
45  delete [] this->array;
46  // Need check for change in number of pixels!
47  this->numPixels = size;
48  this->array = new float[size];
49  for(int i=0;i<size;i++) this->array[i] = input[i];
50}
51
52void DataArray::getDim(long &x, long &y, long &z){
53  if(numDim>0) x=axisDim[0];
54  else x=0;
55  if(numDim>1) y=axisDim[1];
56  else y=0;
57  if(numDim>2) z=axisDim[2];
58  else z=0;
59}
60
61void DataArray::addObject(Detection object){
62  // adds a single detection to the object list
63  // objectList is a vector, so just use push_back()
64  this->objectList.push_back(object);
65}
66
67void DataArray::addObjectList(vector <Detection> newlist) {
68  for(int i=0;i<newlist.size();i++) this->objectList.push_back(newlist[i]);
69}
70
71std::ostream& operator<< ( std::ostream& theStream, DataArray &array){
72
73  for(int i=0;i<array.numDim;i++){
74    if(i>0) theStream<<"x";
75    theStream<<array.axisDim[i];
76  }
77  theStream<<endl;
78  theStream<<array.objectList.size()<<" detections:"<<endl<<"--------------\n";
79  for(int i=0;i<array.objectList.size();i++){
80    theStream << "Detection #" << array.objectList[i].getID()<<endl;
81    Detection *obj = new Detection;
82    *obj = array.objectList[i];
83    for(int j=0;j<obj->getSize();j++){
84      obj->setX(j,obj->getX(j)+obj->getXOffset());
85      obj->setY(j,obj->getY(j)+obj->getYOffset());
86      obj->setZ(j,obj->getZ(j)+obj->getZOffset());
87    }
88    theStream<<*obj;
89    delete obj;
90  }
91  theStream<<"--------------\n";
92}
93
94/****************************************************************/
95/////////////////////////////////////////////////////////////
96//// Functions for Image class
97/////////////////////////////////////////////////////////////
98
99Image::Image(long size){
100  // need error handling in case size<0 !!!
101  if(size>0){
102    this->array = new float[size];
103    this->pValue = new float[size];
104    this->mask = new short int[size];
105  }
106  this->numPixels = size;
107  this->axisDim = new long[2];
108  this->numDim = 2;
109}
110
111Image::Image(long *dimensions){
112  int size = dimensions[0] * dimensions[1];
113  this->numPixels = size;
114  if(size>0){
115    this->array = new float[size];
116    this->pValue = new float[size];
117    this->mask = new short int[size];
118  }
119  this->numDim=2;
120  this->axisDim = new long[2];
121  for(int i=0;i<2;i++) this->axisDim[i] = dimensions[i];
122  for(int i=0;i<size;i++) this->mask[i] = 0;
123}
124
125void Image::saveArray(float *input, long size){
126  // Need check for change in number of pixels!
127  if(this->numPixels>0){
128    delete [] array;
129    delete [] pValue;
130    delete [] mask;
131  }
132  this->numPixels = size;
133  this->array = new float[size];
134  this->pValue = new float[size];
135  this->mask = new short int[size];
136  for(int i=0;i<size;i++) this->array[i] = input[i];
137  for(int i=0;i<size;i++) this->mask[i] = 0;
138}
139
140void Image::maskObject(Detection &object)
141{
142  /**
143   * Image::maskObject(Detection &)
144   *  A function that increments the mask for each pixel of the detection.
145   */
146  for(long i=0;i<object.getSize();i++){
147    this->setMaskValue(object.getX(i),object.getY(i),1);
148  }
149}
150
151void Image::extractSpectrum(float *Array, long *dim, long pixel)
152{
153  /**
154   * Image::extractSpectrum(float *, int)
155   *  A function to extract a 1-D spectrum from a 3-D array.
156   *  The array is assumed to be 3-D with the third dimension the spectral one.
157   *  The dimensions of the array are in the dim[] array.
158   *  The spectrum extracted is the one lying in the spatial pixel referenced
159   *    by the third argument.
160   */
161  float *spec = new float[dim[2]];
162  for(int z=0;z<dim[2];z++) spec[z] = Array[z*dim[0]*dim[1] + pixel];
163  this->saveArray(spec,dim[2]);
164  delete [] spec;
165}
166
167void Image::extractImage(float *Array, long *dim, long channel)
168{
169  /**
170   * Image::extractImage(float *, int)
171   *  A function to extract a 2-D image from a 3-D array.
172   *  The array is assumed to be 3-D with the third dimension the spectral one.
173   *  The dimensions of the array are in the dim[] array.
174   *  The image extracted is the one lying in the channel referenced
175   *    by the third argument.
176   */
177  float *image = new float[dim[0]*dim[1]];
178  for(int npix=0; npix<dim[0]*dim[1]; npix++){
179    image[npix] = Array[channel*dim[0]*dim[1] + npix];
180
181//     int npts = 0;
182//     image[npix] = 2.*Array[channel*dim[0]*dim[1] + npix];
183//     npts+=2;
184//     // npts++;
185//     if(channel>0){
186//       image[npix] += Array[(channel-1)*dim[0]*dim[1] + npix];
187//       npts++;
188//     }
189//     if(channel<(dim[2]-1)){
190//       image[npix] += Array[(channel+1)*dim[0]*dim[1] + npix];
191//       npts++;
192//     }
193//     image[npix] /= float(npts);
194
195  }
196  this->saveArray(image,dim[0]*dim[1]);
197  delete [] image;
198}
199
200void Image::findStats(int code)
201{
202  /**
203   *  Image::findStats(int code)
204   *    Front-end to function to find the stats (mean/median & sigma/madfm) and
205   *     store them in the "mean" and "sigma" members of Image.
206   *    The choice of normal(mean & sigma) or robust (median & madfm) is made via the
207   *      code parameter. This is stored as a decimal number, with 0s representing
208   *      normal stats, and 1s representing robust.
209   *      The 10s column is the mean, the 1s column the sigma.
210   *      Eg: 00 -- mean&sigma; 01 -- mean&madfm; 10 -- median&sigma; 11 -- median&madfm
211   *    If calculated, the madfm value is corrected to sigma units.
212   *    The Image member "cut" is also assigned using the parameter in Image's par
213   *      (needs to be defined first -- also for the blank pixel determination).
214   */
215  float *tempArray = new float[this->numPixels];
216  int goodSize=0;
217  for(int i=0; i<this->numPixels; i++)
218    if(!this->isBlank(i)) tempArray[goodSize++] = this->array[i];
219  float tempMean,tempSigma,tempMedian,tempMADFM;
220  if(code != 0) findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
221  if(code != 11) findNormalStats(tempArray,goodSize,tempMean,tempSigma);
222  switch(code)
223    {
224    case 0:
225      findNormalStats(tempArray,goodSize,tempMean,tempSigma);
226      this->mean = tempMean;
227      this->sigma = tempSigma;
228      break;
229    case 10:
230      this->mean = findMedian(tempArray,goodSize);;
231      this->sigma = findSigma(tempArray,goodSize);
232      break;
233    case 1:
234      this->mean = findMean(tempArray,goodSize);
235      this->sigma = findMADFM(tempArray,goodSize)/correctionFactor;
236      break;
237    case 11:
238    default:
239      if(code!=11) std::cerr <<
240                     "Invalid code ("<<code<<") in findStats. Using robust method.\n";
241      findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
242      this->mean = tempMedian;
243      this->sigma = tempMADFM/correctionFactor;
244      break;
245    }
246  this->cutLevel = this->par.getCut();
247  delete [] tempArray;
248}
249
250/****************************************************************/
251/////////////////////////////////////////////////////////////
252//// Functions for Cube class
253/////////////////////////////////////////////////////////////
254
255Cube::Cube(long size){
256  // need error handling in case size<0 !!!
257  if(size>0){
258    this->array = new float[size];
259//     this->blankarray = new bool[size];
260    this->recon = new float[size];
261  }
262  this->numPixels = size;
263  this->axisDim = new long[2];
264  this->numDim = 3;
265  this->reconExists = false;
266  flagWCS = false;
267}
268
269Cube::Cube(long *dimensions){
270  int size   = dimensions[0] * dimensions[1] * dimensions[2];
271  int imsize = dimensions[0] * dimensions[1];
272  this->numPixels = size;
273  if(size>0){
274    this->array      = new float[size];
275//     this->blankarray = new bool[size];
276    this->detectMap  = new short[imsize];
277    if(this->par.getFlagATrous())
278      this->recon    = new float[size];
279    if(this->par.getFlagBaseline())
280      this->baseline = new float[size];
281  }
282  this->numDim  = 3;
283  this->axisDim = new long[3];
284  for(int i=0;i<3     ;i++) this->axisDim[i]   = dimensions[i];
285  for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
286  this->wcs = new wcsprm;
287  this->wcs->flag=-1;
288  wcsini(true,3,this->wcs);
289  flagWCS = false;
290}
291
292void Cube::initialiseCube(long *dimensions){
293  int size   = dimensions[0] * dimensions[1] * dimensions[2];
294  int imsize = dimensions[0] * dimensions[1];
295  this->numPixels = size;
296  if(size>0){
297    this->array      = new float[size];
298//     this->blankarray = new bool[size];
299    this->detectMap  = new short[imsize];
300    this->specMean   = new float[imsize];
301    this->specSigma  = new float[imsize];
302    this->chanMean   = new float[dimensions[2]];
303    this->chanSigma  = new float[dimensions[2]];
304    if(this->par.getFlagATrous())
305      this->recon    = new float[size];
306    if(this->par.getFlagBaseline())
307      this->baseline = new float[size];
308  }
309  this->numDim  = 3;
310  this->axisDim = new long[3];
311  for(int i=0;i<3     ;i++) this->axisDim[i]   = dimensions[i];
312  for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
313  this->wcs = new wcsprm;
314  this->wcs->flag=-1;
315  wcsini(true,3,this->wcs);
316}
317
318void Cube::saveArray(float *input, long size){
319  // Need check for change in number of pixels!
320  if(this->numPixels>0) delete [] array;
321  this->numPixels = size;
322  this->array = new float[size];
323  for(int i=0;i<size;i++) this->array[i] = input[i];
324}
325
326void Cube::saveRecon(float *input, long size){
327  // Need check for change in number of pixels!
328  if(this->numPixels>0) delete [] recon;
329  this->numPixels = size;
330  this->recon = new float[size];
331  for(int i=0;i<size;i++) this->recon[i] = input[i];
332  this->reconExists = true;
333}
334
335void Cube::getRecon(float *output){
336  // Need check for change in number of pixels!
337  long size = this->numPixels;
338  for(int i=0;i<size;i++){
339    if(this->reconExists) output[i] = this->recon[i];
340    else output[i] = 0.;
341  }
342}
343
344////////// WCS-related functions
345
346void Cube::setWCS(wcsprm *w)
347{
348  /**
349   * Cube::setWCS(wcsprm *)
350   *  A function that assigns the cube's wcs parameters, and runs
351   *   wcsset to set it up correctly.
352   *  Performs a check to see if the WCS is good (by looking at
353   *   the lng and lat wcsprm parameters), and sets the flagWCS accordingly.
354   */
355
356  wcscopy(true,w,this->wcs);
357  wcsset(this->wcs);
358  if( (w->lng!=-1) && (w->lat!=-1) ) this->flagWCS = true;
359}
360
361wcsprm *Cube::getWCS()
362{
363  /**
364   * Cube::getWCS()
365   *  A function that returns a wcsprm object corresponding to the cube's WCS.
366   */
367
368  wcsprm *wNew = new wcsprm;
369//   wcsprm *wOld = new wcsprm;
370//   wOld = this->wcs;
371  wNew->flag=-1;
372//   wcsini(true,wOld->naxis,wNew);
373//   wcscopy(true,wOld,wNew);
374  wcsini(true,this->wcs->naxis,wNew);
375  wcscopy(true,this->wcs,wNew);
376  return wNew;
377}
378
379void Cube::calcObjectWCSparams()
380{
381  /**
382   * Cube::calcObjectWCSparams()
383   *  A function that calculates the WCS parameters for each object in the
384   *  cube's list of detections.
385   *  Each object gets an ID number set (just the order in the list), and if the
386   *   WCS is good, the WCS paramters are calculated.
387   */
388 
389  for(int i=0; i<this->objectList.size();i++){
390    this->objectList[i].setID(i+1);
391    if(this->flagWCS) this->objectList[i].calcWCSparams(this->wcs);
392    this->objectList[i].setIntegFlux( this->objectList[i].getIntegFlux()/this->par.getBeamSize() );
393    // correct the integrated flux for the beam size.
394  } 
395
396 
397}
398
399void Cube::sortDetections()
400{
401  /**
402   * Cube::sortDetections()
403   *  A front end to the sort-by functions.
404   *  If there is a good WCS, the detection list is sorted by velocity.
405   *  Otherwise, it is sorted by increasing z-pixel value.
406   *  The ID numbers are then re-calculated.
407   */
408 
409  if(this->flagWCS) SortByVel(this->objectList);
410  else SortByZ(this->objectList);
411  for(int i=0; i<this->objectList.size();i++) this->objectList[i].setID(i+1);
412
413}
414
415void Cube::updateDetectMap()
416{
417  /**
418   * Cube::updateDetectMap()
419   *  A function that, for each detected object in the cube's list, increments the
420   *  cube's detection map by the required amount at each pixel.
421   */
422
423  for(int obj=0;obj<this->objectList.size();obj++)
424    for(int pix=0;pix<this->objectList[obj].getSize();pix++)
425      this->detectMap[this->objectList[obj].getX(pix)+this->objectList[obj].getY(pix)*this->axisDim[0]]++;
426}
427
428void Cube::updateDetectMap(Detection obj)
429{
430  /**
431   * Cube::updateDetectMap(Detection)
432   *  A function that, for the given object, increments the cube's
433   *  detection map by the required amount at each pixel.
434   */
435  for(int pix=0;pix<obj.getSize();pix++)
436    this->detectMap[obj.getX(pix)+obj.getY(pix)*this->axisDim[0]]++;
437}
438
439void Cube::setCubeStats()
440{
441  // First set the stats for each spectrum (ie. each spatial pixel)
442  long xySize = this->axisDim[0]*this->axisDim[1];
443  float *spec = new float[this->axisDim[2]];
444  for(int i=0;i<xySize;i++){
445    for(int z=0;z<this->axisDim[2];z++){
446      //Two cases: i) have reconstructed -- use residuals
447      //          ii) otherwise          -- use original array
448      if(this->reconExists) spec[z] = this->array[z*xySize+i] - this->recon[z*xySize+1];
449      else                  spec[z] = this->array[z*xySize+i];
450    }
451    findMedianStats(spec,this->axisDim[2],this->specMean[i],this->specSigma[i]);
452  }
453  delete spec;
454  // Then set the stats for each channel map
455  float *im = new float[xySize];
456  for(int z=0;z<this->axisDim[2];z++){
457    for(int i=0;i<xySize;i++){
458      if(this->reconExists) im[i] = this->array[z*xySize+i] - this->recon[z*xySize+1];
459      else                  im[i] = this->array[z*xySize+i];
460     
461    }
462    findMedianStats(im,this->axisDim[2],this->chanMean[z],this->chanSigma[z]);
463    this->chanSigma[z] /= correctionFactor;
464  }
465  delete im;
466
467}
Note: See TracBrowser for help on using the repository browser.