source: tags/release-1.0.5/src/Cubes/cubes.cc @ 1455

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

Some crucial edits so that things will work when the cube's WCS is not well defined.

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()){
301    int maxMW = this->par.getMaxMW();
302    int minMW = this->par.getMinMW();
303    if(this->axisDim[1]==1){
304      for(int z=0;z<this->axisDim[0];z++){
305        if(!this->isBlank(z) && this->par.isInMW(z)) this->array[z]=0.;
306      }
307    }
308  }
309}
310
311void Image::findStats(int code)
312{
313  /**
314   *  Image::findStats(int code)
315   *    Front-end to function to find the stats (mean/median & sigma/madfm) and
316   *     store them in the "mean" and "sigma" members of Image.
317   *    The choice of normal(mean & sigma) or robust (median & madfm) is made
318   *      via the code parameter. This is stored as a decimal number, with 0s
319   *      representing normal stats, and 1s representing robust.
320   *      The 10s column is the mean, the 1s column the sigma.
321   *      Eg: 00 -- mean&sigma;   01 -- mean&madfm;
322   *          10 -- median&sigma; 11 -- median&madfm
323   *    If calculated, the madfm value is corrected to sigma units.
324   *    The Image member "cut" is also assigned using the parameter in Image's
325   *     par (needs to be defined first -- also for the blank pixel
326   *          determination).
327   */
328  float *tempArray = new float[this->numPixels];
329  int goodSize=0;
330  for(int i=0; i<this->numPixels; i++)
331    if(!this->isBlank(i)) tempArray[goodSize++] = this->array[i];
332  float tempMean,tempSigma,tempMedian,tempMADFM;
333  if(code != 0) findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
334  if(code != 11) findNormalStats(tempArray,goodSize,tempMean,tempSigma);
335  switch(code)
336    {
337    case 0:
338      findNormalStats(tempArray,goodSize,tempMean,tempSigma);
339      this->mean = tempMean;
340      this->sigma = tempSigma;
341      break;
342    case 10:
343      this->mean  = findMedian(tempArray,goodSize);;
344      this->sigma = findStddev(tempArray,goodSize);
345      break;
346    case 1:
347      this->mean  = findMean(tempArray,goodSize);
348      this->sigma = findMADFM(tempArray,goodSize)/correctionFactor;
349      break;
350    case 11:
351    default:
352      if(code!=11) {
353        std::stringstream errmsg;
354        errmsg << "Invalid code ("<<code<<") in findStats. Using robust method.\n";
355        duchampWarning("Image::findStats", errmsg.str());
356      }
357      findMedianStats(tempArray,goodSize,tempMedian,tempMADFM);
358      this->mean = tempMedian;
359      this->sigma = tempMADFM/correctionFactor;
360      break;
361    }
362  this->cutLevel = this->par.getCut();
363  delete [] tempArray;
364}
365
366/****************************************************************/
367/////////////////////////////////////////////////////////////
368//// Functions for Cube class
369/////////////////////////////////////////////////////////////
370
371Cube::Cube(long size){
372  // need error handling in case size<0 !!!
373  if(size<0)
374    duchampError("Cube(size)","Negative size -- could not define Cube");
375  else{
376    if(size>0){
377      this->array = new float[size];
378      this->recon = new float[size];
379    }
380    this->numPixels = size;
381    this->axisDim = new long[2];
382    this->numDim = 3;
383    this->reconExists = false;
384  }
385}
386
387Cube::Cube(long *dimensions){
388  int size   = dimensions[0] * dimensions[1] * dimensions[2];
389  int imsize = dimensions[0] * dimensions[1];
390  if((size<0) || (imsize<0) )
391    duchampError("Cube(dimArray)","Negative size -- could not define Cube");
392  else{
393    this->numPixels = size;
394    if(size>0){
395      this->array      = new float[size];
396      this->detectMap  = new short[imsize];
397      if(this->par.getFlagATrous())
398        this->recon    = new float[size];
399      if(this->par.getFlagBaseline())
400        this->baseline = new float[size];
401    }
402    this->numDim  = 3;
403    this->axisDim = new long[3];
404    for(int i=0;i<3     ;i++) this->axisDim[i]   = dimensions[i];
405    for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
406  }
407}
408
409Cube::~Cube()
410{
411  delete [] detectMap;
412  if(this->par.getFlagATrous())   delete [] recon;
413  if(this->par.getFlagBaseline()) delete [] baseline;
414  delete [] specMean,specSigma,chanMean,chanSigma;
415}
416
417void Cube::initialiseCube(long *dimensions)
418{
419  /**
420   *  Cube::initialiseCube(long *dim)
421   *   A function that defines the sizes of all the necessary
422   *    arrays in the Cube class.
423   *   It also defines the values of the axis dimensions.
424   *   This is done with the WCS in the FitsHeader class, so the
425   *    WCS needs to be good and have three axes.
426   */
427
428  int lng,lat,spc,size,imsize;
429
430  if(this->head.isWCS() && (this->head.getWCS()->naxis>=3)){
431    // if there is a WCS and there is at least 3 axes
432    lng = this->head.getWCS()->lng;
433    lat = this->head.getWCS()->lat;
434    spc = this->head.getWCS()->spec;
435  }
436  else{
437    // just take dimensions[] at face value
438    lng = 0;
439    lat = 1;
440    spc = 2;
441  }
442  size   = dimensions[lng] * dimensions[lat] * dimensions[spc];
443  imsize = dimensions[lng] * dimensions[lat];
444
445
446
447//   if(!this->head.isWCS()){
448//     duchampError("Cube::initialiseCube",
449//  "The WCS is not sufficiently defined. Not able to define Cube.\n");
450//   }
451//   else if(this->head.getWCS()->naxis<3){
452//     duchampError("Cube::initialiseCube",
453//  "The WCS does not have three axes defined. Not able to define Cube.\n");
454//   }
455//   else{
456//     int lng = this->head.getWCS()->lng;
457//     int lat = this->head.getWCS()->lat;
458//     int spc = this->head.getWCS()->spec;
459//     int size   = dimensions[lng] * dimensions[lat] * dimensions[spc];
460//     int imsize = dimensions[lng] * dimensions[lat];
461    if((size<0) || (imsize<0) )
462      duchampError("Cube::initialiseCube(dimArray)",
463                   "Negative size -- could not define Cube.\n");
464    else{
465      this->numPixels = size;
466      if(size>0){
467        this->array      = new float[size];
468        this->detectMap  = new short[imsize];
469        this->specMean   = new float[imsize];
470        this->specSigma  = new float[imsize];
471        this->chanMean   = new float[dimensions[spc]];
472        this->chanSigma  = new float[dimensions[spc]];
473        if(this->par.getFlagATrous())
474          this->recon    = new float[size];
475        if(this->par.getFlagBaseline())
476          this->baseline = new float[size];
477      }
478      this->numDim  = 3;
479      this->axisDim = new long[3];
480      this->axisDim[0] = dimensions[lng];
481      this->axisDim[1] = dimensions[lat];
482      this->axisDim[2] = dimensions[spc];
483      for(int i=0;i<imsize;i++) this->detectMap[i] = 0;
484    }
485  }
486//}
487
488int Cube::getopts(int argc, char ** argv)
489{
490  /**
491   *   Cube::getopt
492   *    A front-end to read in the command-line options,
493   *     and then read in the correct parameters to the cube->par
494   */
495
496  int returnValue;
497  if(argc==1){
498    std::cout << ERR_USAGE_MSG;
499    returnValue = FAILURE;
500  }
501  else {
502    string file;
503    Param *par = new Param;
504    char c;
505    while( ( c = getopt(argc,argv,"p:f:hv") )!=-1){
506      switch(c) {
507      case 'p':
508        file = optarg;
509        if(this->readParam(file)==FAILURE){
510          stringstream errmsg;
511          errmsg << "Could not open parameter file " << file << ".\n";
512          duchampError("Duchamp",errmsg.str());
513          returnValue = FAILURE;
514        }
515        else returnValue = SUCCESS;
516        break;
517      case 'f':
518        file = optarg;
519        par->setImageFile(file);
520        this->saveParam(*par);
521        returnValue = SUCCESS;
522        break;
523      case 'v':
524        std::cout << PROGNAME << " version " << VERSION << std::endl;
525        returnValue = FAILURE;
526        break;
527      case 'h':
528      default :
529        std::cout << ERR_USAGE_MSG;
530        returnValue = FAILURE;
531        break;
532      }
533    }
534    delete par;
535  }
536  return returnValue;
537}
538
539void Cube::saveArray(float *input, long size){
540  if(size != this->numPixels){
541    stringstream errmsg;
542    errmsg << "Input array different size to existing array ("
543           << size << " cf. " << this->numPixels << "). Cannot save.\n";
544    duchampError("Cube::saveArray",errmsg.str());
545  }
546  else {
547    if(this->numPixels>0) delete [] array;
548    this->numPixels = size;
549    this->array = new float[size];
550    for(int i=0;i<size;i++) this->array[i] = input[i];
551  }
552}
553
554void Cube::saveRecon(float *input, long size){
555  if(size != this->numPixels){
556    stringstream errmsg;
557    errmsg << "Input array different size to existing array ("
558           << size << " cf. " << this->numPixels << "). Cannot save.\n";
559    duchampError("Cube::saveRecon",errmsg.str());
560  }
561  else {
562    if(this->numPixels>0) delete [] this->recon;
563    this->numPixels = size;
564    this->recon = new float[size];
565    for(int i=0;i<size;i++) this->recon[i] = input[i];
566    this->reconExists = true;
567  }
568}
569
570void Cube::getRecon(float *output){
571  // Need check for change in number of pixels!
572  long size = this->numPixels;
573  for(int i=0;i<size;i++){
574    if(this->reconExists) output[i] = this->recon[i];
575    else output[i] = 0.;
576  }
577}
578
579void Cube::removeMW()
580{
581  if(this->par.getFlagMW()){
582    for(int pix=0;pix<this->axisDim[0]*this->axisDim[1];pix++){
583      for(int z=0;z<this->axisDim[2];z++){
584        int pos = z*this->axisDim[0]*this->axisDim[1] + pix;
585        if(!this->isBlank(pos) && this->par.isInMW(z)) this->array[pos]=0.;
586      }
587    }
588  }
589}
590
591void Cube::calcObjectWCSparams()
592{
593  /**
594   * Cube::calcObjectWCSparams()
595   *  A function that calculates the WCS parameters for each object in the
596   *  cube's list of detections.
597   *  Each object gets an ID number set (just the order in the list), and if
598   *   the WCS is good, the WCS paramters are calculated.
599   */
600 
601  for(int i=0; i<this->objectList.size();i++){
602    this->objectList[i].setID(i+1);
603    this->objectList[i].calcWCSparams(this->head);
604  } 
605
606 
607}
608
609void Cube::sortDetections()
610{
611  /**
612   * Cube::sortDetections()
613   *  A front end to the sort-by functions.
614   *  If there is a good WCS, the detection list is sorted by velocity.
615   *  Otherwise, it is sorted by increasing z-pixel value.
616   *  The ID numbers are then re-calculated.
617   */
618 
619  if(this->head.isWCS()) SortByVel(this->objectList);
620  else SortByZ(this->objectList);
621  for(int i=0; i<this->objectList.size();i++) this->objectList[i].setID(i+1);
622
623}
624
625void Cube::updateDetectMap()
626{
627  /**
628   * Cube::updateDetectMap()
629   *  A function that, for each detected object in the cube's list, increments
630   *   the cube's detection map by the required amount at each pixel.
631   */
632
633  for(int obj=0;obj<this->objectList.size();obj++){
634    for(int pix=0;pix<this->objectList[obj].getSize();pix++) {
635      int spatialPos = this->objectList[obj].getX(pix)+
636        this->objectList[obj].getY(pix)*this->axisDim[0];
637      this->detectMap[spatialPos]++;
638    }
639  }
640}
641
642void Cube::updateDetectMap(Detection obj)
643{
644  /**
645   * Cube::updateDetectMap(Detection)
646   *  A function that, for the given object, increments the cube's
647   *  detection map by the required amount at each pixel.
648   */
649  for(int pix=0;pix<obj.getSize();pix++) {
650    int spatialPos = obj.getX(pix)+obj.getY(pix)*this->axisDim[0];
651    this->detectMap[spatialPos]++;
652  }
653}
654
655void Cube::setCubeStats()
656{
657  // First set the stats for each spectrum (ie. each spatial pixel)
658  long xySize = this->axisDim[0]*this->axisDim[1];
659  float *spec = new float[this->axisDim[2]];
660  for(int i=0;i<xySize;i++){
661    for(int z=0;z<this->axisDim[2];z++){
662      //Two cases: i) have reconstructed -- use residuals
663      //          ii) otherwise          -- use original array
664      if(this->reconExists)
665        spec[z] = this->array[z*xySize+i] - this->recon[z*xySize+1];
666      else
667        spec[z] = this->array[z*xySize+i];
668    }
669    findMedianStats(spec, this->axisDim[2],
670                    this->specMean[i], this->specSigma[i]);
671  }
672  delete spec;
673  // Then set the stats for each channel map
674  float *im = new float[xySize];
675  for(int z=0;z<this->axisDim[2];z++){
676    for(int i=0;i<xySize;i++){
677      if(this->reconExists)
678        im[i] = this->array[z*xySize+i] - this->recon[z*xySize+1];
679      else
680        im[i] = this->array[z*xySize+i];
681    }
682    findMedianStats(im,this->axisDim[2],this->chanMean[z],this->chanSigma[z]);
683    this->chanSigma[z] /= correctionFactor;
684  }
685  delete im;
686
687}
688
689float Cube::enclosedFlux(Detection obj)
690{
691  /**
692   *  float Cube::enclosedFlux(Detection obj)
693   *   A function to calculate the flux enclosed by the range
694   *    of pixels detected in the object obj (not necessarily all
695   *    pixels will have been detected).
696   */
697  obj.calcParams();
698  int xsize = obj.getXmax()-obj.getXmin()+1;
699  int ysize = obj.getYmax()-obj.getYmin()+1;
700  int zsize = obj.getZmax()-obj.getZmin()+1;
701  vector <float> fluxArray(xsize*ysize*zsize,0.);
702  for(int x=0;x<xsize;x++){
703    for(int y=0;y<ysize;y++){
704      for(int z=0;z<zsize;z++){
705        fluxArray[x+y*xsize+z*ysize*xsize] =
706          this->getPixValue(x+obj.getXmin(),
707                            y+obj.getYmin(),
708                            z+obj.getZmin());
709        if(this->par.getFlagNegative())
710          fluxArray[x+y*xsize+z*ysize*xsize] *= -1.;
711      }
712    }
713  }
714  float sum = 0.;
715  for(int i=0;i<fluxArray.size();i++)
716    if(!this->par.isBlank(fluxArray[i])) sum+=fluxArray[i];
717  return sum;
718}
719
720void Cube::setupColumns()
721{
722  /**
723   *  Cube::setupColumns()
724   *   A front-end to the two setup routines in columns.cc.
725   */
726  for(int i=0; i<this->objectList.size();i++) this->objectList[i].setID(i+1);
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.