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

Last change on this file since 1026 was 984, checked in by MatthewWhiting, 12 years ago

Making sure the growing stage updates the detection map, so that the detection map shows all the grown pixels as well (it previously didn't!)

File size: 7.4 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/param.hh>
35#include <duchamp/PixelMap/Object3D.hh>
36#include <duchamp/Cubes/cubes.hh>
37#include <duchamp/Cubes/cubeUtils.hh>
38#include <duchamp/Detection/detection.hh>
39#include <duchamp/Detection/ObjectGrower.hh>
40#include <duchamp/Utils/utils.hh>
41#include <duchamp/Utils/feedback.hh>
42
43using std::vector;
44using namespace PixelInfo;
45
46namespace duchamp
47{
48
49  void Cube::ObjectMerger()
50  {
51    /// @details
52    /// A Function that takes a Cube's list of Detections and
53    /// combines those that are close (according to the
54    /// thresholds specified in the parameter list par).
55    /// It also excludes those that do not make the minimum
56    /// number of channels requirement.
57    /// A front end to simpler functions mergeList and finaliseList,
58    ///  with code to cover the option of growing objects.
59
60    int startSize = this->objectList->size();
61
62    if(startSize > 0){
63
64      // make a vector "currentList", which starts as a copy of the Cube's
65      //  objectList, but is the one worked on.
66      vector <Detection> currentList(startSize);
67      for(int i=0;i<startSize;i++) currentList[i] = this->objectList->at(i);
68      this->objectList->clear();
69
70      if(this->par.getFlagRejectBeforeMerge())
71        finaliseList(currentList, this->par);
72
73      mergeList(currentList, this->par);
74
75      // Do growth stuff
76      if(this->par.getFlagGrowth()) {
77        ObjectGrower grower;
78        grower.define(this);
79        for(size_t i=0;i<currentList.size();i++){
80          if(this->par.isVerbose()){
81            std::cout.setf(std::ios::right);
82            std::cout << "Growing: " << std::setw(6) << i+1 << "/";       
83            std::cout.unsetf(std::ios::right);
84            std::cout.setf(std::ios::left);
85            std::cout << std::setw(6) << currentList.size() << std::flush;
86            printBackSpace(22);
87            std::cout << std::flush;
88          }
89          grower.grow(&currentList[i]);
90        }
91        grower.updateDetectMap(this->detectMap);
92        std::cout.unsetf(std::ios::left);
93
94        // and do the merging again to pick up objects that have
95        //  grown into each other.
96        mergeList(currentList, this->par);
97      }
98
99      if(!this->par.getFlagRejectBeforeMerge())
100        finaliseList(currentList, this->par);
101
102      //     *this->objectList = currentList;
103      this->objectList->resize(currentList.size());
104      for(size_t i=0;i<currentList.size();i++)
105        this->objectList->at(i) = currentList[i];
106   
107      currentList.clear();
108
109    }
110  }
111
112  void ObjectMerger(vector<Detection> &objList, Param &par)
113  {
114    /// @details
115    ///   A simple front-end to the mergeList() and finaliseList() functions,
116    ///    so that if you want to merge a single list, it will
117    ///    do both the merging and the cleaning up afterwards.
118
119    mergeList(objList, par);
120    finaliseList(objList, par);
121  }
122
123  void mergeList(vector<Detection> &objList, Param &par)
124  {
125    /// @details
126    ///   A function that merges any objects in the list of
127    ///    Detections that are within stated threshold distances.
128    ///   Determination of whether objects are close is done by
129    ///    the function areClose.
130
131    if(objList.size() > 0){
132
133      bool isVerb = par.isVerbose();
134      vector <Detection>::iterator iter;
135     
136      std::vector<bool> isValid(objList.size(),true);
137      int numRemoved=0;
138
139      size_t counter=0, compCounter,goodCounter=0;
140
141      while( counter < (objList.size()-1) ){
142        if(isVerb){
143          std::cout.setf(std::ios::right);
144          std::cout << "Merging: " << std::setw(6) << goodCounter+1 << "/" ;
145          std::cout.unsetf(std::ios::right);
146          std::cout.setf(std::ios::left);
147          std::cout << std::setw(6) << objList.size()-numRemoved;
148          printBackSpace(22);
149          std::cout << std::flush;
150          std::cout.unsetf(std::ios::left);
151        }
152
153        if(isValid[counter]){
154
155          compCounter = counter + 1;
156
157          do {
158
159            if(isValid[compCounter]){
160
161              bool close = objList[counter].canMerge(objList[compCounter], par);
162
163              if(close){
164                objList[counter].addDetection(objList[compCounter]);
165                isValid[compCounter]=false;
166                numRemoved++;
167
168                if(isVerb){
169                  std::cout.setf(std::ios::right);
170                  std::cout << "Merging: "
171                            << std::setw(6) << goodCounter+1 << "/";
172                  std::cout.unsetf(std::ios::right);
173                  std::cout.setf(std::ios::left);
174                  std::cout << std::setw(6) << objList.size()-numRemoved;
175                  printBackSpace(22);
176                  std::cout << std::flush;
177                  std::cout.unsetf(std::ios::left);
178                }
179               
180                compCounter = counter + 1;
181               
182              }
183              else compCounter++;
184            }
185            else compCounter++;
186
187          } while( (compCounter<objList.size()) );
188
189        }
190        counter++;
191        if(isValid[counter]) goodCounter++;
192
193      }  // end of while(counter<(objList.size()-1)) loop
194
195      std::vector<Detection> newlist(objList.size()-numRemoved);
196      size_t ct=0;
197      for(size_t i=0;i<objList.size();i++){
198        if(isValid[i]) newlist[ct++]=objList[i];
199      }
200      objList.clear();
201      objList=newlist;
202
203    }
204  }
205
206
207  void finaliseList(vector<Detection> &objList, Param &par)
208  {
209    /// @details
210    ///  A function that looks at each object in the Detection vector
211    ///    and determines whether is passes the requirements for the
212    ///    minimum number of channels and spatial pixels, as provided by
213    ///    the Param set par.
214    ///   If it does not pass, it is removed from the list.
215    ///   In the process, the offsets are set.
216
217    if(par.isVerbose()){
218      std::cout << "Rejecting:" << std::setw(6) << objList.size();
219      printSpace(6);
220      printBackSpace(22);
221      std::cout << std::flush;
222    }
223
224    std::vector<Detection> newlist;
225   
226    std::vector<Detection>::iterator obj = objList.begin();
227    int numRej=0;
228    for(;obj<objList.end();obj++){
229      obj->setOffsets(par);
230     
231      if( (obj->hasEnoughChannels(par.getMinChannels()))
232          && (obj->getSpatialSize() >= par.getMinPix())
233          && (obj->getSize() >= par.getMinVoxels() ) ){
234
235        newlist.push_back(*obj);
236
237      }     
238      else{
239        numRej++;
240        if(par.isVerbose()){
241          std::cout << "Rejecting:" << std::setw(6) << objList.size()-numRej;
242          printSpace(6);
243          printBackSpace(22);
244          std::cout << std::flush;
245        }
246
247      }
248    }
249
250    objList.clear();
251    objList = newlist;
252
253  }
254
255
256}
Note: See TracBrowser for help on using the repository browser.