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

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

A large bunch of changes related to #102. The starting point was fixing the way the merging worked, to avoid using erase() and do the addition of sources in-place. This led on to optimising the testing functions that look at whether objects should be merged, and a number of new in-class functions were created to do this more transparently. The file areClose.cc now doesn't contain anything useful, and can be deleted. Code is a lot quicker now :)

File size: 7.3 KB
RevLine 
[299]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// -----------------------------------------------------------------------
[3]29#include <iostream>
[258]30#include <fstream>
[3]31#include <iomanip>
32#include <math.h>
33#include <vector>
[393]34#include <duchamp/PixelMap/Object3D.hh>
35#include <duchamp/Cubes/cubes.hh>
[463]36#include <duchamp/Cubes/cubeUtils.hh>
[393]37#include <duchamp/Detection/detection.hh>
[744]38#include <duchamp/Detection/ObjectGrower.hh>
[393]39#include <duchamp/Utils/utils.hh>
40#include <duchamp/Utils/feedback.hh>
[3]41
[232]42using std::vector;
[258]43using namespace PixelInfo;
[232]44
[378]45namespace duchamp
[3]46{
47
[378]48  void Cube::ObjectMerger()
49  {
[528]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.
[3]58
[378]59    int startSize = this->objectList->size();
[258]60
[378]61    if(startSize > 0){
[3]62
[378]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();
[3]68
[672]69      if(this->par.getFlagRejectBeforeMerge())
70        finaliseList(currentList, this->par);
71
[423]72      mergeList(currentList, this->par);
[378]73
74      // Do growth stuff
75      if(this->par.getFlagGrowth()) {
[744]76        ObjectGrower grower;
77        grower.define(this);
[623]78        for(size_t i=0;i<currentList.size();i++){
[629]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          }
[744]88          grower.grow(&currentList[i]);
[378]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.
[423]94        mergeList(currentList, this->par);
[137]95      }
[3]96
[672]97      if(!this->par.getFlagRejectBeforeMerge())
98        finaliseList(currentList, this->par);
[3]99
[378]100      //     *this->objectList = currentList;
101      this->objectList->resize(currentList.size());
[623]102      for(size_t i=0;i<currentList.size();i++)
[378]103        this->objectList->at(i) = currentList[i];
[291]104   
[378]105      currentList.clear();
[3]106
[378]107    }
[137]108  }
[3]109
[378]110  void ObjectMerger(vector<Detection> &objList, Param &par)
111  {
[528]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
[378]117    mergeList(objList, par);
118    finaliseList(objList, par);
119  }
[138]120
[378]121  void mergeList(vector<Detection> &objList, Param &par)
122  {
[528]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.
[86]128
[378]129    if(objList.size() > 0){
[3]130
[378]131      bool isVerb = par.isVerbose();
132      vector <Detection>::iterator iter;
[770]133     
134      std::vector<bool> isValid(objList.size(),true);
135      int numRemoved=0;
[3]136
[770]137      size_t counter=0, compCounter,goodCounter=0;
138
[378]139      while( counter < (objList.size()-1) ){
140        if(isVerb){
141          std::cout.setf(std::ios::right);
[770]142          std::cout << "Merging: " << std::setw(6) << goodCounter+1 << "/" ;
[378]143          std::cout.unsetf(std::ios::right);
144          std::cout.setf(std::ios::left);
[770]145          std::cout << std::setw(6) << objList.size()-numRemoved;
[378]146          printBackSpace(22);
147          std::cout << std::flush;
148          std::cout.unsetf(std::ios::left);
149        }
[3]150
[770]151        if(isValid[counter]){
[3]152
[770]153          compCounter = counter + 1;
[3]154
[770]155          do {
[3]156
[770]157            if(isValid[compCounter]){
[137]158
[770]159              bool close = objList[counter].canMerge(objList[compCounter], par);
[137]160
[770]161              if(close){
162                objList[counter].addDetection(objList[compCounter]);
163                isValid[compCounter]=false;
164                numRemoved++;
[137]165
[770]166                if(isVerb){
167                  std::cout.setf(std::ios::right);
168                  std::cout << "Merging: "
169                            << std::setw(6) << goodCounter+1 << "/";
170                  std::cout.unsetf(std::ios::right);
171                  std::cout.setf(std::ios::left);
172                  std::cout << std::setw(6) << objList.size()-numRemoved;
173                  printBackSpace(22);
174                  std::cout << std::flush;
175                  std::cout.unsetf(std::ios::left);
176                }
177               
178                compCounter = counter + 1;
179               
180              }
181              else compCounter++;
182            }
183            else compCounter++;
[3]184
[770]185          } while( (compCounter<objList.size()) );
[3]186
[770]187        }
[378]188        counter++;
[770]189        if(isValid[counter]) goodCounter++;
[3]190
[378]191      }  // end of while(counter<(objList.size()-1)) loop
[770]192
193      std::vector<Detection> newlist(objList.size()-numRemoved);
194      size_t ct=0;
195      for(size_t i=0;i<objList.size();i++){
196        if(isValid[i]) newlist[ct++]=objList[i];
197      }
198      objList.clear();
199      objList=newlist;
200
[378]201    }
[137]202  }
[3]203
204
[378]205  void finaliseList(vector<Detection> &objList, Param &par)
206  {
[528]207    /// @details
208    ///  A function that looks at each object in the Detection vector
209    ///    and determines whether is passes the requirements for the
210    ///    minimum number of channels and spatial pixels, as provided by
211    ///    the Param set par.
212    ///   If it does not pass, it is removed from the list.
[728]213    ///   In the process, the offsets are set.
[3]214
[637]215    if(par.isVerbose()){
216      std::cout << "Rejecting:" << std::setw(6) << objList.size();
217      printSpace(6);
218      printBackSpace(22);
219      std::cout << std::flush;
220    }
221
[770]222    std::vector<Detection> newlist;
223   
[577]224    std::vector<Detection>::iterator obj = objList.begin();
[770]225    int numRej=0;
226    for(;obj<objList.end();obj++){
[577]227      obj->setOffsets(par);
[570]228     
[577]229      if( (obj->hasEnoughChannels(par.getMinChannels()))
[720]230          && (obj->getSpatialSize() >= par.getMinPix())
[721]231          && (obj->getSize() >= par.getMinVoxels() ) ){
[139]232
[770]233        newlist.push_back(*obj);
[265]234
[378]235      }     
236      else{
[770]237        numRej++;
[378]238        if(par.isVerbose()){
[770]239          std::cout << "Rejecting:" << std::setw(6) << objList.size()-numRej;
[378]240          printSpace(6);
241          printBackSpace(22);
242          std::cout << std::flush;
243        }
244
[137]245      }
[265]246    }
[770]247
248    objList.clear();
249    objList = newlist;
250
[3]251  }
252
[137]253
[378]254}
Note: See TracBrowser for help on using the repository browser.