source: trunk/src/PixelMap/Object3D.cc @ 1069

Last change on this file since 1069 was 1002, checked in by MatthewWhiting, 12 years ago

Another long --> size_t change, this time in the getPixelSet function for Object3D that is only used in askapsoft

File size: 13.3 KB
RevLine 
[301]1// -----------------------------------------------------------------------
[528]2// Object3D.cc: Member functions for Object3D class.
[301]3// -----------------------------------------------------------------------
4// Copyright (C) 2006, Matthew Whiting, ATNF
5//
6// This program is free software; you can redistribute it and/or modify it
7// under the terms of the GNU General Public License as published by the
8// Free Software Foundation; either version 2 of the License, or (at your
9// option) any later version.
10//
11// Duchamp is distributed in the hope that it will be useful, but WITHOUT
12// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14// for more details.
15//
16// You should have received a copy of the GNU General Public License
17// along with Duchamp; if not, write to the Free Software Foundation,
18// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
19//
20// Correspondence concerning Duchamp may be directed to:
21//    Internet email: Matthew.Whiting [at] atnf.csiro.au
22//    Postal address: Dr. Matthew Whiting
23//                    Australia Telescope National Facility, CSIRO
24//                    PO Box 76
25//                    Epping NSW 1710
26//                    AUSTRALIA
27// -----------------------------------------------------------------------
[244]28#include <iostream>
[658]29#include <sstream>
[393]30#include <duchamp/PixelMap/Voxel.hh>
31#include <duchamp/PixelMap/Scan.hh>
32#include <duchamp/PixelMap/Object2D.hh>
33#include <duchamp/PixelMap/Object3D.hh>
[927]34#include <duchamp/Utils/Section.hh>
[238]35#include <vector>
[570]36#include <map>
[238]37
[252]38namespace PixelInfo
39{
[365]40  Object3D::Object3D()
41  {
42    this->numVox=0;
[570]43    this->xSum = 0;
44    this->ySum = 0;
45    this->zSum = 0;
46    this->xmin = this->xmax = this->ymin = this->ymax = this->zmin = this->zmax = -1;
[365]47  }
[570]48  //--------------------------------------------
[365]49
[270]50  Object3D::Object3D(const Object3D& o)
51  {
[365]52    operator=(o);
[252]53  }
54  //--------------------------------------------
55
[270]56  Object3D& Object3D::operator= (const Object3D& o)
57  {
58    if(this == &o) return *this;
[570]59    this->chanlist = o.chanlist;
[252]60    this->numVox  = o.numVox;
[927]61    this->spatialMap = o.spatialMap;
[252]62    this->xSum    = o.xSum;
63    this->ySum    = o.ySum;
64    this->zSum    = o.zSum;
65    this->xmin    = o.xmin;
66    this->ymin    = o.ymin;
67    this->zmin    = o.zmin;
68    this->xmax    = o.xmax;
69    this->ymax    = o.ymax;
70    this->zmax    = o.zmax;
[270]71    return *this;
[252]72  }
73  //--------------------------------------------
[570]74
75  Object3D operator+ (Object3D lhs, Object3D rhs)
76  {
77    Object3D output = lhs;
78    for(std::map<long, Object2D>::iterator it = rhs.chanlist.begin(); it!=rhs.chanlist.end();it++)
79      output.addChannel(it->first, it->second);
[770]80      //      output.addChannel(*it);
[570]81    return output;
82  }
83
84  //--------------------------------------------
85  float Object3D::getXaverage()
86  {
87    if(numVox>0) return xSum/float(numVox);
88    else return 0.;
89  }
90  //--------------------------------------------
91
92  float Object3D::getYaverage()
93  {
94    if(numVox>0) return ySum/float(numVox);
95    else return 0.;
96  }
97  //--------------------------------------------
98
99  float Object3D::getZaverage()
100  {
101    if(numVox>0) return zSum/float(numVox);
102    else return 0.;
103  }
104  //--------------------------------------------
[243]105 
[252]106  bool Object3D::isInObject(long x, long y, long z)
107  {
[570]108    std::map<long,Object2D>::iterator it=this->chanlist.begin();
109    while(it!=this->chanlist.end() && it->first!=z) it++;
110
111    if(it==this->chanlist.end()) return false;
112    else                         return it->second.isInObject(x,y);
[238]113  }
[252]114  //--------------------------------------------
[238]115
[252]116  void Object3D::addPixel(long x, long y, long z)
117  {
[570]118 
119    std::map<long,Object2D>::iterator it=this->chanlist.begin();
120    while(it!=this->chanlist.end() && it->first!=z) it++;
[238]121
[570]122    if(it==this->chanlist.end()){ //new channel
123      Object2D obj;
124      obj.addPixel(x,y);
125      chanlist.insert( std::pair<int,Object2D>(z,obj) );
[252]126      // update the centres, min & max, as well as the number of voxels
127      if(this->numVox==0){
128        this->xSum = this->xmin = this->xmax = x;
129        this->ySum = this->ymin = this->ymax = y;
130        this->zSum = this->zmin = this->zmax = z;
131      }
132      else{
133        this->xSum += x;
134        this->ySum += y;
135        this->zSum += z;
136        if(x<this->xmin) this->xmin = x;
137        if(x>this->xmax) this->xmax = x;
138        if(y<this->ymin) this->ymin = y;
139        if(y>this->ymax) this->ymax = y;
[570]140        // since we've ordered the maplist, the min & max z fall out naturally
141        this->zmin = this->chanlist.begin()->first;
142        this->zmax = this->chanlist.rbegin()->first;
[252]143      }
144      this->numVox++;   
[246]145    }
[570]146    else{ // existing channel
147      // This method deals with the case of a new pixel being added AND
148      // with the new pixel already existing in the Object2D
149 
[252]150      // Remove that channel's information from the Object's information
[570]151      this->xSum -= it->second.xSum;
152      this->ySum -= it->second.ySum;
[776]153      this->zSum -= z*it->second.numPix;
154      this->numVox -= it->second.numPix;
[252]155
[570]156      // Add the pixel
157      it->second.addPixel(x,y);
[252]158   
[776]159      this->numVox += it->second.numPix;
[570]160      this->xSum += it->second.xSum;
161      this->ySum += it->second.ySum;
[776]162      this->zSum += z*it->second.numPix;
[246]163      if(x<this->xmin) this->xmin = x;
164      if(x>this->xmax) this->xmax = x;
165      if(y<this->ymin) this->ymin = y;
166      if(y>this->ymax) this->ymax = y;
[252]167      // don't need to do anything to zmin/zmax -- the z-value is
168      // already in the list
[246]169    }
170
[927]171    this->spatialMap.addPixel(x,y);
172
[238]173  }
[252]174  //--------------------------------------------
[238]175
[472]176  void Object3D::addScan(Scan s, long z)
177  {
178    long y=s.getY();
179    for(int x=s.getX(); x<=s.getXmax(); x++)
180      this->addPixel(x,y,z);
181  }
182
183  //--------------------------------------------
184
[770]185  // void Object3D::addChannel(const std::pair<long, Object2D> *chan)
186  // {
187  //   long z = chan->first;
188  //   Object2D
189  // }
190
191
[570]192  void Object3D::addChannel(const long &z, Object2D &obj)
[252]193  {
[238]194
[570]195    std::map<long,Object2D>::iterator it=this->chanlist.begin();
196    while(it!=this->chanlist.end() && it->first!=z) it++;
197
[577]198    if(it == this->chanlist.end()){ // channel z is not already in object, so add it.
[570]199      this->chanlist.insert(std::pair<long,Object2D>(z,obj));
[577]200      if(this->numVox == 0){ // if there are no other pixels, so initialise mins,maxs,sums
[570]201        this->xmin = obj.xmin;
202        this->xmax = obj.xmax;
203        this->ymin = obj.ymin;
204        this->ymax = obj.ymax;
205        this->zmin = this->zmax = z;
206        this->xSum = obj.xSum;
207        this->ySum = obj.ySum;
208        this->zSum = z * obj.getSize();
[252]209      }
[577]210      else{ // there are other pixels in other channels, so update mins, maxs, sums
[570]211        if(obj.xmin<this->xmin) this->xmin = obj.xmin;
212        if(obj.xmax>this->xmax) this->xmax = obj.xmax;
213        if(obj.ymin<this->ymin) this->ymin = obj.ymin;
214        if(obj.ymax>this->ymax) this->ymax = obj.ymax;
215        if(z<this->zmin) this->zmin = z;
216        if(z>this->zmax) this->zmax = z;
217        this->xSum += obj.xSum;
218        this->ySum += obj.ySum;
219        this->zSum += z * obj.getSize();
[252]220      }
[570]221      this->numVox += obj.getSize();
[246]222    }
[577]223    else{ // channel is already present, so need to combine objects.
[570]224      this->xSum -= it->second.xSum;
225      this->ySum -= it->second.ySum;
226      this->zSum -= z*it->second.getSize();
227      this->numVox -= it->second.getSize();
[577]228      it->second = it->second + obj;
[570]229      this->xSum += it->second.xSum;
230      this->ySum += it->second.ySum;
231      this->zSum += z*it->second.getSize();
232      this->numVox += it->second.getSize();
233      if(obj.xmin<this->xmin) this->xmin = obj.xmin;
234      if(obj.xmax>this->xmax) this->xmax = obj.xmax;
235      if(obj.ymin<this->ymin) this->ymin = obj.ymin;
236      if(obj.ymax>this->ymax) this->ymax = obj.ymax;
[252]237    }
[419]238
[927]239    this->spatialMap = this->spatialMap + obj;
[238]240
241  }
242
[252]243  //--------------------------------------------
[238]244 
[252]245  void Object3D::calcParams()
246  {
247    this->xSum = 0;
248    this->ySum = 0;
249    this->zSum = 0;
[570]250    this->numVox = 0;
[238]251
[570]252    this->zmin = this->chanlist.begin()->first;
253    this->zmax = this->chanlist.rbegin()->first;
254    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
255        it!=this->chanlist.end();it++){
[238]256
[570]257      it->second.calcParams();
258
259      if(it==this->chanlist.begin()){
260        this->xmin = it->second.getXmin();
261        this->xmax = it->second.getXmax();
262        this->ymin = it->second.getYmin();
263        this->ymax = it->second.getYmax();
[252]264      }
265      else{
[570]266        if(it->second.xmin<this->xmin) this->xmin = it->second.xmin;
267        if(it->second.xmax>this->xmax) this->xmax = it->second.xmax;
268        if(it->second.ymin<this->ymin) this->ymin = it->second.ymin;
269        if(it->second.ymax>this->ymax) this->ymax = it->second.ymax;
[252]270      }
271
[570]272      this->xSum += it->second.xSum;
273      this->ySum += it->second.ySum;
274      this->zSum += it->first * it->second.getSize();
275      this->numVox += it->second.getSize();
[252]276
[238]277    }
278
279  }
[252]280  //------------------------------------------------------
[238]281
[773]282  void Object3D::print(std::ostream& theStream)
[252]283  {
[773]284    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
285        it!=this->chanlist.end();it++){
286      for(std::vector<Scan>::iterator s=it->second.scanlist.begin();s!=it->second.scanlist.end();s++){
287        theStream << *s << "," << it->first << "\n";
[244]288      }
[252]289    } 
290    theStream << "\n";
[773]291  }
292
293
294  std::ostream& operator<< ( std::ostream& theStream, Object3D& obj)
295  {
296    obj.print(theStream);
[270]297    return theStream;
[252]298  }
299  //--------------------------------------------
[241]300
[252]301  std::vector<Voxel> Object3D::getPixelSet()
302  {
[724]303    /// @details Returns a vector of the Voxels in the object. All
304    /// flux values are set to 0.
305
[252]306    std::vector<Voxel> voxList(this->numVox);
307    long count = 0;
[570]308    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
309        it!=this->chanlist.end();it++){
310      long z = it->first;
[773]311      for(std::vector<Scan>::iterator s=it->second.scanlist.begin();s!=it->second.scanlist.end();s++){
312        long y = s->getY();
313        for(long x=s->getX(); x<=s->getXmax(); x++){
[252]314          voxList[count].setXYZF(x,y,z,0);
315          count++;
[241]316        }
[252]317      }
[241]318    }
[252]319    return voxList;
[243]320
321  }
322
[399]323  //--------------------------------------------------------------------
324
[1002]325  std::vector<Voxel> Object3D::getPixelSet(float *array, size_t *dim)
[724]326  {
327    /// @details Returns a vector of Voxels with the flux values for each voxel
328    /// taken from the array provided. No check is made as to whether
329    /// the pixels fall in the array boundaries
330    /// @param array Array of pixel values
331    /// @param dim Array of axis dimensions
332
333    std::vector<Voxel> voxList(this->numVox);
334    long count = 0;
335    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
336        it!=this->chanlist.end();it++){
337      long z = it->first;
[773]338      for(std::vector<Scan>::iterator s=it->second.scanlist.begin();s!=it->second.scanlist.end();s++){
339        long y = s->getY();
340        for(long x=s->getX(); x<=s->getXmax(); x++){
[724]341          voxList[count].setXYZF(x,y,z,array[x+dim[0]*y+dim[0]*dim[1]*z]);
342          count++;
343        }
344      }
345    }
346    return voxList;
347
348  }
349
350  //--------------------------------------------------------------------
351
[570]352  std::vector<long> Object3D::getChannelList()
[399]353  {
[570]354
355    std::vector<long> chanlist;
356    for(std::map<long, Object2D>::iterator it = this->chanlist.begin();
357        it != this->chanlist.end(); it++){
358      chanlist.push_back(it->first);
359    }
360    return chanlist;
[399]361  }
[570]362
[399]363  //--------------------------------------------------------------------
364
[570]365  Object2D Object3D::getChanMap(long z)
366  {
367    Object2D obj;
368    std::map<long,Object2D>::iterator it=this->chanlist.begin();
369    while(it!=this->chanlist.end() && it->first!=z) it++;
370
371    if(it==this->chanlist.end()) obj = Object2D();
372    else obj = it->second;
373
374    return obj;
375  }
376
377  //--------------------------------------------------------------------
378
379  int Object3D::getMaxAdjacentChannels()
380  {
[691]381    /// @details Find the maximum number of contiguous channels in the
382    /// object. Since there can be gaps in the channels included in an
383    /// object, we run through the list of channels and keep track of
384    /// sizes of contiguous segments. Then return the largest size.
385
[570]386    int maxnumchan=0;
[691]387    int zcurrent=0, zprevious,zcount=0;
388    std::map<long, Object2D>::iterator it;
389    for(it = this->chanlist.begin(); it!=this->chanlist.end();it++)
[570]390      {
[691]391        if(it==this->chanlist.begin()){
392          zcount++;
393          zcurrent = it->first;
[570]394        }
[691]395        else{
396          zprevious = zcurrent;
397          zcurrent = it->first;
398          if(zcurrent-zprevious>1){
399            maxnumchan = std::max(maxnumchan, zcount);
400            zcount=1;
401          }
402          else zcount++;
403        }
[570]404      }
405    maxnumchan = std::max(maxnumchan,zcount);
406    return maxnumchan;
407  }
408
409  //--------------------------------------------------------------------
410
[399]411  void Object3D::addOffsets(long xoff, long yoff, long zoff)
[419]412  {
[658]413    std::map<long,Object2D> newmap;
414    for(std::map<long, Object2D>::iterator it = this->chanlist.begin(); it!=this->chanlist.end();it++){
415      std::pair<long,Object2D> newOne(it->first+zoff, it->second);
416      newOne.second.addOffsets(xoff,yoff);
417      newmap.insert(newOne);
418    }
419    this->chanlist.clear();
420    this->chanlist = newmap;
[570]421    if(this->numVox>0){
422      this->xSum += xoff*numVox;
423      this->xmin += xoff; this->xmax += xoff;
424      this->ySum += yoff*numVox;
425      this->ymin += yoff; this->ymax += yoff;
426      this->zSum += zoff*numVox;
427      this->zmin += zoff; this->zmax += zoff;
428    }
[419]429  }
[399]430
[658]431
432  duchamp::Section Object3D::getBoundingSection(int boundary)
433  {
434    std::stringstream ss;
435    ss << "[" << this->xmin-boundary <<":"<<this->xmax+boundary<<","<< this->ymin-boundary <<":"<<this->ymax+boundary<<","<< this->zmin-boundary <<":"<<this->zmax+boundary<<"]";
436    std::string sec=ss.str();
437    duchamp::Section section(sec);
438    return section;
439  }
440
[243]441}
Note: See TracBrowser for help on using the repository browser.