source: trunk/src/Cubes/Merger.cc @ 744

Last change on this file since 744 was 744, checked in by MatthewWhiting, 14 years ago

Two major changes. We make use of the ObjectGrower? class to handle the growing of the detections, and there are some improvements to the addPixel function in Object2D that result in major speed-ups.

File size: 6.9 KB
Line 
1// -----------------------------------------------------------------------
2// Merger.cc: Merging a list of Detections, and rejecting on the basis
3//            of number of channels or pixels.
4// -----------------------------------------------------------------------
5// Copyright (C) 2006, Matthew Whiting, ATNF
6//
7// This program is free software; you can redistribute it and/or modify it
8// under the terms of the GNU General Public License as published by the
9// Free Software Foundation; either version 2 of the License, or (at your
10// option) any later version.
11//
12// Duchamp is distributed in the hope that it will be useful, but WITHOUT
13// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
15// for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with Duchamp; if not, write to the Free Software Foundation,
19// Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA
20//
21// Correspondence concerning Duchamp may be directed to:
22//    Internet email: Matthew.Whiting [at] atnf.csiro.au
23//    Postal address: Dr. Matthew Whiting
24//                    Australia Telescope National Facility, CSIRO
25//                    PO Box 76
26//                    Epping NSW 1710
27//                    AUSTRALIA
28// -----------------------------------------------------------------------
29#include <iostream>
30#include <fstream>
31#include <iomanip>
32#include <math.h>
33#include <vector>
34#include <duchamp/PixelMap/Object3D.hh>
35#include <duchamp/Cubes/cubes.hh>
36#include <duchamp/Cubes/cubeUtils.hh>
37#include <duchamp/Detection/detection.hh>
38#include <duchamp/Detection/ObjectGrower.hh>
39#include <duchamp/Utils/utils.hh>
40#include <duchamp/Utils/feedback.hh>
41
42using std::vector;
43using namespace PixelInfo;
44
45namespace duchamp
46{
47
48  void Cube::ObjectMerger()
49  {
50    /// @details
51    /// A Function that takes a Cube's list of Detections and
52    /// combines those that are close (according to the
53    /// thresholds specified in the parameter list par).
54    /// It also excludes those that do not make the minimum
55    /// number of channels requirement.
56    /// A front end to simpler functions mergeList and finaliseList,
57    ///  with code to cover the option of growing objects.
58
59    int startSize = this->objectList->size();
60
61    if(startSize > 0){
62
63      // make a vector "currentList", which starts as a copy of the Cube's
64      //  objectList, but is the one worked on.
65      vector <Detection> currentList(startSize);
66      for(int i=0;i<startSize;i++) currentList[i] = this->objectList->at(i);
67      this->objectList->clear();
68
69      if(this->par.getFlagRejectBeforeMerge())
70        finaliseList(currentList, this->par);
71
72      mergeList(currentList, this->par);
73
74      // Do growth stuff
75      if(this->par.getFlagGrowth()) {
76        ObjectGrower grower;
77        grower.define(this);
78        for(size_t i=0;i<currentList.size();i++){
79          if(this->par.isVerbose()){
80            std::cout.setf(std::ios::right);
81            std::cout << "Growing: " << std::setw(6) << i+1 << "/";       
82            std::cout.unsetf(std::ios::right);
83            std::cout.setf(std::ios::left);
84            std::cout << std::setw(6) << currentList.size() << std::flush;
85            printBackSpace(22);
86            std::cout << std::flush;
87          }
88          grower.grow(&currentList[i]);
89        }
90        std::cout.unsetf(std::ios::left);
91
92        // and do the merging again to pick up objects that have
93        //  grown into each other.
94        mergeList(currentList, this->par);
95      }
96
97      if(!this->par.getFlagRejectBeforeMerge())
98        finaliseList(currentList, this->par);
99
100      //     *this->objectList = currentList;
101      this->objectList->resize(currentList.size());
102      for(size_t i=0;i<currentList.size();i++)
103        this->objectList->at(i) = currentList[i];
104   
105      currentList.clear();
106
107    }
108  }
109
110  void ObjectMerger(vector<Detection> &objList, Param &par)
111  {
112    /// @details
113    ///   A simple front-end to the mergeList() and finaliseList() functions,
114    ///    so that if you want to merge a single list, it will
115    ///    do both the merging and the cleaning up afterwards.
116
117    mergeList(objList, par);
118    finaliseList(objList, par);
119  }
120
121  void mergeList(vector<Detection> &objList, Param &par)
122  {
123    /// @details
124    ///   A function that merges any objects in the list of
125    ///    Detections that are within stated threshold distances.
126    ///   Determination of whether objects are close is done by
127    ///    the function areClose.
128
129    if(objList.size() > 0){
130
131      bool isVerb = par.isVerbose();
132      vector <Detection>::iterator iter;
133
134      size_t counter=0, compCounter;
135      while( counter < (objList.size()-1) ){
136        if(isVerb){
137          std::cout.setf(std::ios::right);
138          std::cout << "Merging: " << std::setw(6) << counter+1 << "/" ;
139          std::cout.unsetf(std::ios::right);
140          std::cout.setf(std::ios::left);
141          std::cout << std::setw(6) << objList.size();
142          printBackSpace(22);
143          std::cout << std::flush;
144          std::cout.unsetf(std::ios::left);
145        }
146
147        compCounter = counter + 1;
148
149        do {
150
151          Detection obj1 = objList[counter];
152          Detection obj2 = objList[compCounter];
153          Detection newobj;
154
155          bool close = areClose(obj1, obj2, par);
156
157          if(close){
158            newobj = obj1 + obj2 ;
159            iter = objList.begin() + compCounter;
160            objList.erase(iter);
161            iter = objList.begin() + counter;
162            objList.erase(iter);
163            objList.push_back( newobj );
164
165            if(isVerb){
166              std::cout.setf(std::ios::right);
167              std::cout << "Merging: "
168                        << std::setw(6) << counter << "/";
169              std::cout.unsetf(std::ios::right);
170              std::cout.setf(std::ios::left);
171              std::cout << std::setw(6) << objList.size();
172              printBackSpace(22);
173              std::cout << std::flush;
174              std::cout.unsetf(std::ios::left);
175            }
176
177            compCounter = counter + 1;
178
179          }
180          else compCounter++;
181
182        } while( (compCounter<objList.size()) );
183
184        counter++;
185
186      }  // end of while(counter<(objList.size()-1)) loop
187    }
188  }
189
190
191  void finaliseList(vector<Detection> &objList, Param &par)
192  {
193    /// @details
194    ///  A function that looks at each object in the Detection vector
195    ///    and determines whether is passes the requirements for the
196    ///    minimum number of channels and spatial pixels, as provided by
197    ///    the Param set par.
198    ///   If it does not pass, it is removed from the list.
199    ///   In the process, the offsets are set.
200
201    if(par.isVerbose()){
202      std::cout << "Rejecting:" << std::setw(6) << objList.size();
203      printSpace(6);
204      printBackSpace(22);
205      std::cout << std::flush;
206    }
207
208    std::vector<Detection>::iterator obj = objList.begin();
209
210    while(obj < objList.end()){
211
212      obj->setOffsets(par);
213     
214      if( (obj->hasEnoughChannels(par.getMinChannels()))
215          && (obj->getSpatialSize() >= par.getMinPix())
216          && (obj->getSize() >= par.getMinVoxels() ) ){
217
218        obj++;
219
220      }     
221      else{
222     
223        objList.erase(obj);
224        if(par.isVerbose()){
225          std::cout << "Rejecting:" << std::setw(6) << objList.size();
226          printSpace(6);
227          printBackSpace(22);
228          std::cout << std::flush;
229        }
230
231      }
232    }
233  }
234
235
236}
Note: See TracBrowser for help on using the repository browser.