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

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

Large range of changes -- related to image cutouts and spectral units mostly.

duchamp.hh -- changed name of spectral type, and introduced one for frequency.
Cubes/getImage.cc -- changed the way the spectral type and spectral units are

looked at. Now is able to use frequency units (defaults
to MHz) when there isn't a good velocity transformation
possible (ie. if there is no restfreq defined).

Cubes/drawMomentCutout.cc -- Range of changes here:

  • improved the way unwanted pixels (those BLANK and outside image coundaries) are dealt with in the image array in drawMomentCutout
  • removed the way the blank pixel information was changed. Now behaves in a consistent way whether or not there are blank pixels
  • improved call to plotBlankEdges()
  • added call to drawFieldEdge() -- a new function that draws a yellow line around the boundary of the pixels of the image.
  • improved the tick mark that shows the angular scale of the cutout. Now adaptable to any pixel scale.
  • added calls to cpgtest() to all functions

Also these files were changed in relation to these edits:
Utils/drawBlankEdges.cc -- improved execution, with "blank" array.
Cubes/cubes.cc -- added call to Param::drawBlankEdge in Cube::plotBlankEdges()
Cubes/outputSpectra.cc -- moved spectra away from left and right axes.
param.cc -- added necessary calls for the new parameter. Other minor changes

to formatting. Added a missed call to stringize.

mainDuchamp.cc -- added #include <param.hh>
param.hh -- Added a new parameter: blankEdge
Cubes/cubes.hh -- improved appearance of comments
Cubes/plots.hh -- improved appearance of comments
InputComplete? -- added new parameter.
docs/Guide.tex -- added text about blank edge plotting.
All six images were changed as well.

CHANGES -- some of these changes -- not up to date yet!

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