source: trunk/src/Cubes/cubes.cc @ 187

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

Large suite of edits, mostly due to testing with valgrind, which clear up bad memory allocations and so on.
Improved the printing of progress bars in some routines by introducing a new ProgressBar? class, with associated functions to do the printing (now much cleaner).

File size: 23.6 KB
Line 
1#include <unistd.h>
2#include <iostream>
3#include <iomanip>
4#include <vector>
5#include <string>
6
7#include <wcs.h>
8
9#include <duchamp.hh>
10#include <param.hh>
11#include <Cubes/cubes.hh>
12#include <Detection/detection.hh>
13#include <Detection/columns.hh>
14#include <Utils/utils.hh>
15#include <Utils/mycpgplot.hh>
16using std::endl;
17using namespace Column;
18using namespace mycpgplot;
19
20/****************************************************************/
21///////////////////////////////////////////////////
22//// Functions for DataArray class:
23///////////////////////////////////////////////////
24
25DataArray::DataArray(short int nDim, long size){
26
27  if(size<0)
28    duchampError("DataArray(nDim,size)",
29                 "Negative size -- could not define DataArray");
30  else if(nDim<0)
31    duchampError("DataArray(nDim,size)",
32                 "Negative number of dimensions: could not define DataArray");
33  else {
34    if(size>0) this->array = new float[size];
35    this->numPixels = size;
36    if(nDim>0) this->axisDim = new long[nDim];
37    this->numDim = nDim;
38  }
39}
40
41DataArray::DataArray(short int nDim, long *dimensions){
42  if(nDim<0)
43    duchampError("DataArray(nDim,dimArray)",
44                 "Negative number of dimensions: could not define DataArray");
45  else {
46    int size = dimensions[0];
47    for(int i=1;i<nDim;i++) size *= dimensions[i];
48    if(size<0)
49      duchampError("DataArray(nDim,dimArray)",
50                   "Negative size: could not define DataArray");
51    else{
52      this->numPixels = size;
53      if(size>0){
54        this->array = new float[size];
55      }
56      this->numDim=nDim;
57      if(nDim>0) this->axisDim = new long[nDim];
58      for(int i=0;i<nDim;i++) this->axisDim[i] = dimensions[i];
59    }
60  }
61}
62
63DataArray::~DataArray()
64{
65  delete [] array;
66  delete [] axisDim;
67  objectList.clear();
68}
69
70void DataArray::getDimArray(long *output){
71  for(int i=0;i<this->numDim;i++) output[i] = this->axisDim[i];
72}
73
74void DataArray::getArray(float *output){
75  for(int i=0;i<this->numPixels;i++) output[i] = this->array[i];
76}
77
78void DataArray::saveArray(float *input, long size){
79  if(size != this->numPixels)
80    duchampError("DataArray::saveArray",
81                 "Input array different size to existing array. Cannot save.");
82  else {
83    if(this->numPixels>0) delete [] this->array;
84    this->numPixels = size;
85    this->array = new float[size];
86    for(int i=0;i<size;i++) this->array[i] = input[i];
87  }
88}
89
90void DataArray::getDim(long &x, long &y, long &z){
91  if(numDim>0) x=axisDim[0];
92  else x=0;
93  if(numDim>1) y=axisDim[1];
94  else y=0;
95  if(numDim>2) z=axisDim[2];
96  else z=0;
97}
98
99void DataArray::addObject(Detection object){
100  // adds a single detection to the object list
101  // objectList is a vector, so just use push_back()
102  this->objectList.push_back(object);
103}
104
105void DataArray::addObjectList(vector <Detection> newlist) {
106  for(int i=0;i<newlist.size();i++) this->objectList.push_back(newlist[i]);
107}
108
109void DataArray::addObjectOffsets(){
110  for(int i=0;i<this->objectList.size();i++){
111    for(int p=0;p<this->objectList[i].getSize();p++){
112      this->objectList[i].setX(p,this->objectList[i].getX(p)+
113                               this->par.getXOffset());
114      this->objectList[i].setY(p,this->objectList[i].getY(p)+
115                               this->par.getYOffset());
116      this->objectList[i].setZ(p,this->objectList[i].getZ(p)+
117                               this->par.getZOffset());
118    }
119  }
120}
121
122
123std::ostream& operator<< ( std::ostream& theStream, DataArray &array)
124{
125  for(int i=0;i<array.numDim;i++){
126    if(i>0) theStream<<"x";
127    theStream<<array.axisDim[i];
128  }
129  theStream<<endl;
130  theStream<<array.objectList.size()<<" detections:"<<endl<<"--------------\n";
131  for(int i=0;i<array.objectList.size();i++){
132    theStream << "Detection #" << array.objectList[i].getID()<<endl;
133    Detection *obj = new Detection;
134    *obj = array.objectList[i];
135    for(int j=0;j<obj->getSize();j++){
136      obj->setX(j,obj->getX(j)+obj->getXOffset());
137      obj->setY(j,obj->getY(j)+obj->getYOffset());
138      obj->setZ(j,obj->getZ(j)+obj->getZOffset());
139    }
140    theStream<<*obj;
141    delete obj;
142  }
143  theStream<<"--------------\n";
144}
145
146/****************************************************************/
147/////////////////////////////////////////////////////////////
148//// Functions for Image class
149/////////////////////////////////////////////////////////////
150
151Image::Image(long size){
152  // need error handling in case size<0 !!!
153  if(size<0)
154    duchampError("Image(size)","Negative size -- could not define Image");
155  else{
156    if(size>0){
157      this->array = new float[size];
158      this->pValue = new float[size];
159      this->mask = new short int[size];
160    }
161    this->numPixels = size;
162    this->axisDim = new long[2];
163    this->numDim = 2;
164  }
165}
166
167Image::Image(long *dimensions){
168  int size = dimensions[0] * dimensions[1];
169  if(size<0)
170    duchampError("Image(dimArray)","Negative size -- could not define Image");
171  else{
172    this->numPixels = size;
173    if(size>0){
174      this->array = new float[size];
175      this->pValue = new float[size];
176      this->mask = new short int[size];
177    }
178    this->numDim=2;
179    this->axisDim = new long[2];
180    for(int i=0;i<2;i++) this->axisDim[i] = dimensions[i];
181    for(int i=0;i<size;i++) this->mask[i] = 0;
182  }
183}
184
185Image::~Image(){
186  if(this->numPixels > 0){
187    delete [] this->pValue;
188    delete [] this->mask;
189  }
190}
191
192
193void Image::saveArray(float *input, long size){
194  if(size != this->numPixels)
195    duchampError("Image::saveArray",
196                 "Input array different size to existing array. Cannot save.");
197  else {
198    if(this->numPixels>0){
199      delete [] array;
200      delete [] pValue;
201      delete [] mask;
202    }
203    this->numPixels = size;
204    if(this->numPixels>0){
205      this->array = new float[size];
206      this->pValue = new float[size];
207      this->mask = new short int[size];
208    }
209    for(int i=0;i<size;i++) this->array[i] = input[i];
210    for(int i=0;i<size;i++) this->mask[i] = 0;
211  }
212}
213
214void Image::maskObject(Detection &object)
215{
216  /**
217   * Image::maskObject(Detection &)
218   *  A function that increments the mask for each pixel of the detection.
219   */
220  for(long i=0;i<object.getSize();i++){
221    this->setMaskValue(object.getX(i),object.getY(i),1);
222  }
223}
224
225void Image::extractSpectrum(float *Array, long *dim, long pixel)
226{
227  /**
228   * Image::extractSpectrum(float *, long *, int)
229   *  A function to extract a 1-D spectrum from a 3-D array.
230   *  The array is assumed to be 3-D with the third dimension the spectral one.
231   *  The dimensions of the array are in the dim[] array.
232   *  The spectrum extracted is the one lying in the spatial pixel referenced
233   *    by the third argument.
234   */
235  float *spec = new float[dim[2]];
236  for(int z=0;z<dim[2];z++) spec[z] = Array[z*dim[0]*dim[1] + pixel];
237  this->saveArray(spec,dim[2]);
238  delete [] spec;
239}
240
241void Image::extractSpectrum(Cube &cube, long pixel)
242{
243  /**
244   * Image::extractSpectrum(Cube &, int)
245   *  A function to extract a 1-D spectrum from a Cube class
246   *  The spectrum extracted is the one lying in the spatial pixel referenced
247   *    by the second argument.
248   */
249  long zdim = cube.getDimZ();
250  long spatSize = cube.getDimX()*cube.getDimY();
251  float *spec = new float[zdim];
252  for(int z=0;z<zdim;z++) spec[z] = cube.getPixValue(z*spatSize + pixel);
253  this->saveArray(spec,zdim);
254  delete [] spec;
255}
256
257void Image::extractImage(float *Array, long *dim, long channel)
258{
259  /**
260   * Image::extractImage(float *, long *, int)
261   *  A function to extract a 2-D image from a 3-D array.
262   *  The array is assumed to be 3-D with the third dimension the spectral one.
263   *  The dimensions of the array are in the dim[] array.
264   *  The image extracted is the one lying in the channel referenced
265   *    by the third argument.
266   */
267  float *image = new float[dim[0]*dim[1]];
268  for(int npix=0; npix<dim[0]*dim[1]; npix++){
269    image[npix] = Array[channel*dim[0]*dim[1] + npix];
270  }
271  this->saveArray(image,dim[0]*dim[1]);
272  delete [] image;
273}
274
275void Image::extractImage(Cube &cube, long channel)
276{
277  /**
278   * Image::extractImage(Cube &, int)
279   *  A function to extract a 2-D image from Cube class.
280   *  The image extracted is the one lying in the channel referenced
281   *    by the second argument.
282   */
283  long spatSize = cube.getDimX()*cube.getDimY();
284  float *image = new float[spatSize];
285  for(int npix=0; npix<spatSize; npix++)
286    image[npix] = cube.getPixValue(channel*spatSize + npix);
287  this->saveArray(image,spatSize);
288  delete [] image;
289}
290
291void Image::removeMW()
292{
293  /**
294   * Image::removeMW()
295   *  A function to remove the Milky Way range of channels from a 1-D spectrum.
296   *  The array in this Image is assumed to be 1-D, with only the first axisDim
297   *    equal to 1.
298   *  The values of the MW channels are set to 0, unless they are BLANK.
299   */
300  if(this->par.getFlagMW() && (this->axisDim[1]==1) ){
301    for(int z=0;z<this->axisDim[0];z++){
302      if(!this->isBlank(z) && this->par.isInMW(z)) this->array[z]=0.;
303    }
304  }
305}
306
307void Image::findStats(int code)
308{
309  /**
310   *  Image::findStats(int code)
311   *    Front-end to function to find the stats (mean/median & sigma/madfm) and
312   *     store them in the "mean" and "sigma" members of Image.
313   *    The choice of normal(mean & sigma) or robust (median & madfm) is made
314   *      via the code parameter. This is stored as a decimal number, with 0s
315   *      representing normal stats, and 1s representing robust.
316   *      The 10s column is the mean, the 1s column the sigma.
317   *      Eg: 00 -- mean&sigma;   01 -- mean&madfm;
318   *          10 -- median&sigma; 11 -- median&madfm
319   *    If calculated, the madfm value is corrected to sigma units.
320   *    The Image member "cut" is also assigned using the parameter in Image's
321   *     par (needs to be defined first -- also for the blank pixel
322   *          determination).
323   */
324  float *tempArray = new float[this->numPixels];
325  int goodSize=0;
326  for(int i=0; i<this->numPixels; i++)
327    if(!this->isBlank(i)) tempArray[goodSize++] = this->array[i];
328  float tempMean,tempSigma,tempMedian,tempMADFM;
329  if(code != 0) findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
330  if(code != 11) findNormalStats(tempArray,goodSize,tempMean,tempSigma);
331  switch(code)
332    {
333    case 0:
334      findNormalStats(tempArray,goodSize,tempMean,tempSigma);
335      this->mean = tempMean;
336      this->sigma = tempSigma;
337      break;
338    case 10:
339      this->mean  = findMedian(tempArray,goodSize);;
340      this->sigma = findStddev(tempArray,goodSize);
341      break;
342    case 1:
343      this->mean  = findMean(tempArray,goodSize);
344      this->sigma = findMADFM(tempArray,goodSize)/correctionFactor;
345      break;
346    case 11:
347    default:
348      if(code!=11) {
349        std::stringstream errmsg;
350        errmsg << "Invalid code ("<<code<<") in findStats. Using robust method.\n";
351        duchampWarning("Image::findStats", errmsg.str());
352      }
353      findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
354      this->mean = tempMedian;
355      this->sigma = tempMADFM/correctionFactor;
356      break;
357    }
358  this->cutLevel = this->par.getCut();
359  delete [] tempArray;
360}
361
362/****************************************************************/
363/////////////////////////////////////////////////////////////
364//// Functions for Cube class
365/////////////////////////////////////////////////////////////
366
367Cube::Cube(long size){
368  // need error handling in case size<0 !!!
369  if(size<0)
370    duchampError("Cube(size)","Negative size -- could not define Cube");
371  else{
372    if(size>0){
373      this->array = new float[size];
374      this->recon = new float[size];
375    }
376    this->numPixels = size;
377    this->axisDim = new long[2];
378    this->numDim = 3;
379    this->reconExists = false;
380  }
381}
382
383Cube::Cube(long *dimensions){
384  int size   = dimensions[0] * dimensions[1] * dimensions[2];
385  int imsize = dimensions[0] * dimensions[1];
386  if((size<0) || (imsize<0) )
387    duchampError("Cube(dimArray)","Negative size -- could not define Cube");
388  else{
389    this->numPixels = size;
390    if(size>0){
391      this->array      = new float[size];
392      this->detectMap  = new short[imsize];
393      if(this->par.getFlagATrous())
394        this->recon    = new float[size];
395      if(this->par.getFlagBaseline())
396        this->baseline = new float[size];
397    }
398    this->numDim  = 3;
399    this->axisDim = new long[3];
400    for(int i=0;i<3     ;i++) this->axisDim[i]   = dimensions[i];
401    for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
402    this->reconExists = false;
403  }
404}
405
406Cube::~Cube()
407{
408  delete [] detectMap;
409  if(this->par.getFlagATrous())   delete [] recon;
410  if(this->par.getFlagBaseline()) delete [] baseline;
411  delete [] specMean,specSigma,chanMean,chanSigma;
412}
413
414void Cube::initialiseCube(long *dimensions)
415{
416  /**
417   *  Cube::initialiseCube(long *dim)
418   *   A function that defines the sizes of all the necessary
419   *    arrays in the Cube class.
420   *   It also defines the values of the axis dimensions.
421   *   This is done with the WCS in the FitsHeader class, so the
422   *    WCS needs to be good and have three axes.
423   */
424
425  int lng,lat,spc,size,imsize;
426
427  if(this->head.isWCS() && (this->head.getWCS()->naxis>=3)){
428    // if there is a WCS and there is at least 3 axes
429    lng = this->head.getWCS()->lng;
430    lat = this->head.getWCS()->lat;
431    spc = this->head.getWCS()->spec;
432  }
433  else{
434    // just take dimensions[] at face value
435    lng = 0;
436    lat = 1;
437    spc = 2;
438  }
439  size   = dimensions[lng] * dimensions[lat] * dimensions[spc];
440  imsize = dimensions[lng] * dimensions[lat];
441
442
443
444//   if(!this->head.isWCS()){
445//     duchampError("Cube::initialiseCube",
446//  "The WCS is not sufficiently defined. Not able to define Cube.\n");
447//   }
448//   else if(this->head.getWCS()->naxis<3){
449//     duchampError("Cube::initialiseCube",
450//  "The WCS does not have three axes defined. Not able to define Cube.\n");
451//   }
452//   else{
453//     int lng = this->head.getWCS()->lng;
454//     int lat = this->head.getWCS()->lat;
455//     int spc = this->head.getWCS()->spec;
456//     int size   = dimensions[lng] * dimensions[lat] * dimensions[spc];
457//     int imsize = dimensions[lng] * dimensions[lat];
458    if((size<0) || (imsize<0) )
459      duchampError("Cube::initialiseCube(dimArray)",
460                   "Negative size -- could not define Cube.\n");
461    else{
462      this->numPixels = size;
463      if(size>0){
464        this->array      = new float[size];
465        this->detectMap  = new short[imsize];
466        this->specMean   = new float[imsize];
467        this->specSigma  = new float[imsize];
468        this->chanMean   = new float[dimensions[spc]];
469        this->chanSigma  = new float[dimensions[spc]];
470        if(this->par.getFlagATrous())
471          this->recon    = new float[size];
472        if(this->par.getFlagBaseline())
473          this->baseline = new float[size];
474      }
475      this->numDim  = 3;
476      this->axisDim = new long[3];
477      this->axisDim[0] = dimensions[lng];
478      this->axisDim[1] = dimensions[lat];
479      this->axisDim[2] = dimensions[spc];
480      for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
481      this->reconExists = false;
482    }
483  }
484//}
485
486int Cube::getopts(int argc, char ** argv)
487{
488  /**
489   *   Cube::getopt
490   *    A front-end to read in the command-line options,
491   *     and then read in the correct parameters to the cube->par
492   */
493
494  int returnValue;
495  if(argc==1){
496    std::cout << ERR_USAGE_MSG;
497    returnValue = FAILURE;
498  }
499  else {
500    string file;
501    Param *par = new Param;
502    char c;
503    while( ( c = getopt(argc,argv,"p:f:hv") )!=-1){
504      switch(c) {
505      case 'p':
506        file = optarg;
507        if(this->readParam(file)==FAILURE){
508          stringstream errmsg;
509          errmsg << "Could not open parameter file " << file << ".\n";
510          duchampError("Duchamp",errmsg.str());
511          returnValue = FAILURE;
512        }
513        else returnValue = SUCCESS;
514        break;
515      case 'f':
516        file = optarg;
517        par->setImageFile(file);
518        this->saveParam(*par);
519        returnValue = SUCCESS;
520        break;
521      case 'v':
522        std::cout << PROGNAME << " version " << VERSION << std::endl;
523        returnValue = FAILURE;
524        break;
525      case 'h':
526      default :
527        std::cout << ERR_USAGE_MSG;
528        returnValue = FAILURE;
529        break;
530      }
531    }
532    delete par;
533  }
534  return returnValue;
535}
536
537void Cube::saveArray(float *input, long size){
538  if(size != this->numPixels){
539    stringstream errmsg;
540    errmsg << "Input array different size to existing array ("
541           << size << " cf. " << this->numPixels << "). Cannot save.\n";
542    duchampError("Cube::saveArray",errmsg.str());
543  }
544  else {
545    if(this->numPixels>0) delete [] array;
546    this->numPixels = size;
547    this->array = new float[size];
548    for(int i=0;i<size;i++) this->array[i] = input[i];
549  }
550}
551
552void Cube::saveRecon(float *input, long size){
553  if(size != this->numPixels){
554    stringstream errmsg;
555    errmsg << "Input array different size to existing array ("
556           << size << " cf. " << this->numPixels << "). Cannot save.\n";
557    duchampError("Cube::saveRecon",errmsg.str());
558  }
559  else {
560    if(this->numPixels>0) delete [] this->recon;
561    this->numPixels = size;
562    this->recon = new float[size];
563    for(int i=0;i<size;i++) this->recon[i] = input[i];
564    this->reconExists = true;
565  }
566}
567
568void Cube::getRecon(float *output){
569  // Need check for change in number of pixels!
570  long size = this->numPixels;
571  for(int i=0;i<size;i++){
572    if(this->reconExists) output[i] = this->recon[i];
573    else output[i] = 0.;
574  }
575}
576
577void Cube::removeMW()
578{
579  if(this->par.getFlagMW()){
580    for(int pix=0;pix<this->axisDim[0]*this->axisDim[1];pix++){
581      for(int z=0;z<this->axisDim[2];z++){
582        int pos = z*this->axisDim[0]*this->axisDim[1] + pix;
583        if(!this->isBlank(pos) && this->par.isInMW(z)) this->array[pos]=0.;
584      }
585    }
586  }
587}
588
589void Cube::calcObjectWCSparams()
590{
591  /**
592   * Cube::calcObjectWCSparams()
593   *  A function that calculates the WCS parameters for each object in the
594   *  cube's list of detections.
595   *  Each object gets an ID number set (just the order in the list), and if
596   *   the WCS is good, the WCS paramters are calculated.
597   */
598 
599  for(int i=0; i<this->objectList.size();i++){
600    this->objectList[i].setID(i+1);
601    this->objectList[i].calcWCSparams(this->head);
602  } 
603
604 
605}
606
607void Cube::sortDetections()
608{
609  /**
610   * Cube::sortDetections()
611   *  A front end to the sort-by functions.
612   *  If there is a good WCS, the detection list is sorted by velocity.
613   *  Otherwise, it is sorted by increasing z-pixel value.
614   *  The ID numbers are then re-calculated.
615   */
616 
617  if(this->head.isWCS()) SortByVel(this->objectList);
618  else SortByZ(this->objectList);
619  for(int i=0; i<this->objectList.size();i++) this->objectList[i].setID(i+1);
620
621}
622
623void Cube::updateDetectMap()
624{
625  /**
626   * Cube::updateDetectMap()
627   *  A function that, for each detected object in the cube's list, increments
628   *   the cube's detection map by the required amount at each pixel.
629   */
630
631  for(int obj=0;obj<this->objectList.size();obj++){
632    for(int pix=0;pix<this->objectList[obj].getSize();pix++) {
633      int spatialPos = this->objectList[obj].getX(pix)+
634        this->objectList[obj].getY(pix)*this->axisDim[0];
635      this->detectMap[spatialPos]++;
636    }
637  }
638}
639
640void Cube::updateDetectMap(Detection obj)
641{
642  /**
643   * Cube::updateDetectMap(Detection)
644   *  A function that, for the given object, increments the cube's
645   *  detection map by the required amount at each pixel.
646   */
647  for(int pix=0;pix<obj.getSize();pix++) {
648    int spatialPos = obj.getX(pix)+obj.getY(pix)*this->axisDim[0];
649    this->detectMap[spatialPos]++;
650  }
651}
652
653void Cube::setCubeStats()
654{
655  // First set the stats for each spectrum (ie. each spatial pixel)
656  long xySize = this->axisDim[0]*this->axisDim[1];
657  float *spec = new float[this->axisDim[2]];
658  for(int i=0;i<xySize;i++){
659    for(int z=0;z<this->axisDim[2];z++){
660      //Two cases: i) have reconstructed -- use residuals
661      //          ii) otherwise          -- use original array
662      if(this->reconExists)
663        spec[z] = this->array[z*xySize+i] - this->recon[z*xySize+1];
664      else
665        spec[z] = this->array[z*xySize+i];
666    }
667    findMedianStats(spec, this->axisDim[2],
668                    this->specMean[i], this->specSigma[i]);
669  }
670  delete spec;
671  // Then set the stats for each channel map
672  float *im = new float[xySize];
673  for(int z=0;z<this->axisDim[2];z++){
674    for(int i=0;i<xySize;i++){
675      if(this->reconExists)
676        im[i] = this->array[z*xySize+i] - this->recon[z*xySize+1];
677      else
678        im[i] = this->array[z*xySize+i];
679    }
680    findMedianStats(im,this->axisDim[2],this->chanMean[z],this->chanSigma[z]);
681    this->chanSigma[z] /= correctionFactor;
682  }
683  delete im;
684
685}
686
687float Cube::enclosedFlux(Detection obj)
688{
689  /**
690   *  float Cube::enclosedFlux(Detection obj)
691   *   A function to calculate the flux enclosed by the range
692   *    of pixels detected in the object obj (not necessarily all
693   *    pixels will have been detected).
694   */
695  obj.calcParams();
696  int xsize = obj.getXmax()-obj.getXmin()+1;
697  int ysize = obj.getYmax()-obj.getYmin()+1;
698  int zsize = obj.getZmax()-obj.getZmin()+1;
699  vector <float> fluxArray(xsize*ysize*zsize,0.);
700  for(int x=0;x<xsize;x++){
701    for(int y=0;y<ysize;y++){
702      for(int z=0;z<zsize;z++){
703        fluxArray[x+y*xsize+z*ysize*xsize] =
704          this->getPixValue(x+obj.getXmin(),
705                            y+obj.getYmin(),
706                            z+obj.getZmin());
707        if(this->par.getFlagNegative())
708          fluxArray[x+y*xsize+z*ysize*xsize] *= -1.;
709      }
710    }
711  }
712  float sum = 0.;
713  for(int i=0;i<fluxArray.size();i++)
714    if(!this->par.isBlank(fluxArray[i])) sum+=fluxArray[i];
715  return sum;
716}
717
718void Cube::setupColumns()
719{
720  /**
721   *  Cube::setupColumns()
722   *   A front-end to the two setup routines in columns.cc.
723   */
724  this->calcObjectWCSparams(); 
725  // need this as the colSet functions use vel, RA, Dec, etc...
726 
727  this->fullCols.clear();
728  this->fullCols = getFullColSet(this->objectList, this->head);
729
730  this->logCols.clear();
731  this->logCols = getLogColSet(this->objectList, this->head);
732
733  int vel,fpeak,fint,pos,xyz,temp;
734  vel = fullCols[VEL].getPrecision();
735  fpeak = fullCols[FPEAK].getPrecision();
736  xyz = fullCols[X].getPrecision();
737  if(temp=fullCols[Y].getPrecision() > xyz) xyz = temp;
738  if(temp=fullCols[Z].getPrecision() > xyz) xyz = temp;
739  if(this->head.isWCS()) fint = fullCols[FINT].getPrecision();
740  else fint = fullCols[FTOT].getPrecision();
741  pos = fullCols[WRA].getPrecision();
742  if(temp=fullCols[WDEC].getPrecision() > pos) pos = temp;
743 
744  for(int obj=0;obj<this->objectList.size();obj++){
745    this->objectList[obj].setVelPrec(vel);
746    this->objectList[obj].setFpeakPrec(fpeak);
747    this->objectList[obj].setXYZPrec(xyz);
748    this->objectList[obj].setPosPrec(pos);
749    this->objectList[obj].setFintPrec(fint);
750  }
751
752}
753
754bool Cube::objAtEdge(Detection obj)
755{
756  /**
757   *  bool Cube::objAtEdge()
758   *   A function to test whether the object obj
759   *    lies at the edge of the cube's field --
760   *    either at the boundary, or next to BLANKs
761   */
762
763  bool atEdge = false;
764
765  int pix = 0;
766  while(!atEdge && pix<obj.getSize()){
767    // loop over each pixel in the object, until we find an edge pixel.
768    Voxel vox = obj.getPixel(pix);
769    for(int dx=-1;dx<=1;dx+=2){
770      if(((vox.getX()+dx)<0) || ((vox.getX()+dx)>=this->axisDim[0]))
771        atEdge = true;
772      else if(this->isBlank(vox.getX()+dx,vox.getY(),vox.getZ()))
773        atEdge = true;
774    }
775    for(int dy=-1;dy<=1;dy+=2){
776      if(((vox.getY()+dy)<0) || ((vox.getY()+dy)>=this->axisDim[1]))
777        atEdge = true;
778      else if(this->isBlank(vox.getX(),vox.getY()+dy,vox.getZ()))
779        atEdge = true;
780    }
781    for(int dz=-1;dz<=1;dz+=2){
782      if(((vox.getZ()+dz)<0) || ((vox.getZ()+dz)>=this->axisDim[2]))
783        atEdge = true;
784      else if(this->isBlank(vox.getX(),vox.getY(),vox.getZ()+dz))
785        atEdge = true;
786    }
787    pix++;
788  }
789
790  return atEdge;
791}
792
793void Cube::setObjectFlags()
794{
795  /**
796   *  void Cube::setObjectFlags()
797   *   A function to set any warning flags for all the detected objects
798   *    associated with the cube.
799   *   Flags to be looked for:
800   *       * Negative enclosed flux (N)
801   *       * Object at edge of field (E)
802   */
803
804  for(int i=0;i<this->objectList.size();i++){
805
806    if( this->enclosedFlux(this->objectList[i]) < 0. ) 
807      this->objectList[i].addToFlagText("N");
808
809    if( this->objAtEdge(this->objectList[i]) )
810      this->objectList[i].addToFlagText("E");
811
812  }
813
814}
815
816void Cube::plotBlankEdges()
817{
818  if(this->par.drawBlankEdge()){
819    int colour;
820    cpgqci(&colour);
821    cpgsci(MAGENTA);
822    drawBlankEdges(this->array,this->axisDim[0],this->axisDim[1],this->par);
823    cpgsci(colour);
824  }
825}
Note: See TracBrowser for help on using the repository browser.