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

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

Changed the way the FITS file is read in, so that it can deal with
naxis>4 files, where the order of the dimensions is not necessarily
lng,lat,spec,...

Summary of changes:

*Cubes/getImage.cc:

*Removed most of the code that goes in new functions.
*Changed order of tasks, so that the WCS is derived first, then the data array, and then the remaining header information.
*Also reports both the FITS dimensions and the data array dimensions.

*FitsIO/headerIO.cc:

*Moved defineWCS to wcsIO.cc.
*Made array declarations more robust (use CFITSIO constants for lengths).
*Changed type of BLANK keyword to TINT.

*FitsIO/dataIO.cc:

*New function, designed to read in data from FITS file.
*Reads in subset of just the spatial and spectral axes.
*Also takes care of setting blank pixels to appropriate value.

*FitsIO/wcsIO.cc:

*New file, contains the function FitsHeader::defineWCS

  • Utils/wcsFunctions.cc:

*Generalised the wcs functions, so that they make no

assumptions about the location of the spatial and spectral axes.

*Cubes/cubes.cc:

*Improved Cube::initialiseCube so that it gets the dimensions correct.
*Enabled Cube::getopts to deal with non-existant param file.
*Improved error reporting in saveArray functions.

*Cubes/cubes.hh:

*Changed prototypes for readParam. Added one for getFITSdata

*Cubes/ReadAndSearch?.cc :

*Minor comment added.

*param.cc:

*Generalised way fixUnits works, to cope with new axis concept.
*Made readParams return int, so it can indicate whether reading failed.

*ATrous/ReconSearch.cc:

*Improved way the goodness of the pixels and channels was determined.

*src/param.hh

*New prototype for Param::readParams

*Guide:

*Changed text about dimensionality of FITS files.
*Changed location of images.
*Minor changes to improve readability.

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