LSSTApplications  1.1.2+25,10.0+13,10.0+132,10.0+133,10.0+224,10.0+41,10.0+8,10.0-1-g0f53050+14,10.0-1-g4b7b172+19,10.0-1-g61a5bae+98,10.0-1-g7408a83+3,10.0-1-gc1e0f5a+19,10.0-1-gdb4482e+14,10.0-11-g3947115+2,10.0-12-g8719d8b+2,10.0-15-ga3f480f+1,10.0-2-g4f67435,10.0-2-gcb4bc6c+26,10.0-28-gf7f57a9+1,10.0-3-g1bbe32c+14,10.0-3-g5b46d21,10.0-4-g027f45f+5,10.0-4-g86f66b5+2,10.0-4-gc4fccf3+24,10.0-40-g4349866+2,10.0-5-g766159b,10.0-5-gca2295e+25,10.0-6-g462a451+1
LSSTDataManagementBasePackage
Optics.cc
Go to the documentation of this file.
1 // -*- lsst-c++ -*-
2 
3 /*
4  * LSST Data Management System
5  * Copyright 2008, 2009, 2010 LSST Corporation.
6  *
7  * This product includes software developed by the
8  * LSST Project (http://www.lsst.org/).
9  *
10  * This program is free software: you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation, either version 3 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the LSST License Statement and
21  * the GNU General Public License along with this program. If not,
22  * see <http://www.lsstcorp.org/LegalNotices/>.
23  */
24 
31 #ifndef LSST_AP_CLUSTER_DETAIL_OPTICS_CC
32 #define LSST_AP_CLUSTER_DETAIL_OPTICS_CC
33 
34 #include "Optics.h"
35 
36 #include <algorithm>
37 #include <limits>
38 
39 #include "lsst/pex/exceptions.h"
40 
41 #include "KDTree.cc"
42 #include "SeedList.cc"
43 
44 
45 namespace lsst { namespace ap { namespace cluster { namespace detail {
46 
47 
51 template <int K, typename RecordT>
52 Optics<K, RecordT>::Optics(Point<K, boost::shared_ptr<RecordT> > * points,
53  int numPoints,
54  int minNeighbors,
55  double epsilon,
56  double leafExtentThreshold,
57  int pointsPerLeaf) :
58  _points(points),
59  _tree(),
60  _seeds(),
61  _distances(),
62  _epsilon(epsilon),
63  _numPoints(numPoints),
64  _minNeighbors(minNeighbors),
65  _ran(false),
66  _log(lsst::pex::logging::Log::getDefaultLog(), "lsst.ap.cluster.detail")
67 {
68  if (_points == 0) {
69  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
70  "Input point array is null");
71  }
72  if (_numPoints <= 0) {
73  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
74  "Number of input points must be at least 1");
75  }
76  if (_minNeighbors < 0) {
77  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
78  "OPTICS minNeighbors parameter value is negative");
79  }
80  if (_epsilon < 0.0) {
81  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
82  "OPTICS epsilon parameter value is negative");
83  }
84  if (pointsPerLeaf <= 0) {
85  throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
86  "K-D tree pointsPerLeaf parameter must be positive");
87  }
88 
89  _log.log(lsst::pex::logging::Log::INFO, "Building k-d tree for sources");
90  boost::scoped_ptr<KDTree<K, DataT> > tree(new KDTree<K, DataT>(
91  points, numPoints, pointsPerLeaf, leafExtentThreshold));
93  "Created k-d tree for %d sources", numPoints);
94 
95  boost::scoped_ptr<SeedList<K, DataT> > seeds(new SeedList<K, DataT>(
96  points, numPoints));
97  boost::scoped_array<double> distances(new double[_minNeighbors]);
98  using std::swap;
99  swap(_tree, tree);
100  swap(_seeds, seeds);
101  swap(_distances, distances);
102 }
103 
104 template <int K, typename RecordT>
106 
110 template <int K, typename RecordT>
111  template <typename MetricT>
112 void Optics<K, RecordT>::run(boost::shared_ptr<typename RecordT::Table> table,
113  std::vector<typename RecordT::Catalog> & clusters,
114  MetricT const & metric)
115 {
116  if (_ran) {
117  throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
118  "OPTICS has already been run");
119  }
120  typename RecordT::Catalog cluster(table);
121  size_t const s = clusters.size();
122  int scanFrom = 0;
123 
124  _log.log(lsst::pex::logging::Log::INFO, "Clustering sources using OPTICS");
125  _ran = true;
126 
127  while (true) {
128  int i;
129  if (_seeds->empty()) {
130  // find next unprocessed point
131  for (i = scanFrom; i < _numPoints; ++i) {
132  if (_points[i].state == Point<K, DataT>::UNPROCESSED) {
133  scanFrom = i + 1;
134  break;
135  }
136  }
137  if (i == _numPoints) {
138  break;
139  }
140  _points[i].state = Point<K, DataT>::PROCESSED;
141  expandClusterOrder(i, metric);
142  if (cluster.size() > 0) {
143  // clusters of size 1 are generated for noise sources
144  clusters.push_back(cluster);
145  cluster.clear();
146  }
147  cluster.push_back(_points[i].data);
148  } else {
149  // expand cluster around seed with smallest reachability-distance
150  i = _seeds->pop();
151  expandClusterOrder(i, metric);
152  assert(_points[i].reach != std::numeric_limits<double>::infinity());
153  cluster.push_back(_points[i].data);
154  }
155  }
156  clusters.push_back(cluster);
157  _log.format(lsst::pex::logging::Log::INFO, "Produced %d clusters",
158  static_cast<int>(clusters.size() - s));
159 }
160 
161 template <int K, typename RecordT>
162  template <typename MetricT>
163 void Optics<K, RecordT>::expandClusterOrder(int i, MetricT const & metric)
164 {
165  // find epsilon neighborhood of point i
166  int range = _tree->inRange(_points[i].coords, _epsilon, metric);
167  // compute core-distance
168  int n = 0;
169  int j = range;
170  while (j != -1) {
171  Point<K, DataT> * p = _points + j;
172  if (j != i) {
173  double d = p->dist;
174  if (n < _minNeighbors) {
175  _distances[n++] = d;
176  std::push_heap(_distances.get(), _distances.get() + n);
177  } else if (_distances[0] > d) {
178  std::pop_heap(_distances.get(), _distances.get() + n);
179  _distances[n - 1] = d;
180  std::push_heap(_distances.get(), _distances.get() + n);
181  }
182  }
183  j = p->next;
184  }
185  if (n == _minNeighbors) {
186  // point i is a core-object. Update reachability-distance of all
187  // points in the epsilon-neighborhood of point i.
188  double coreDist = _distances[0];
189  j = range;
190  while (j != -1) {
191  Point<K, DataT> * p = _points + j;
192  if (p->state != Point<K, DataT>::PROCESSED) {
193  _seeds->update(j, std::max(coreDist, p->dist));
194  }
195  j = p->next;
196  }
197  }
198 }
199 
200 }}}} // namespace lsst:ap::cluster::detail
201 
202 #endif // LSST_AP_CLUSTER_DETAIL_OPTICS_CC
static const int INFO
Definition: Log.h:171
void swap(Ellipse< DataT > &a, Ellipse< DataT > &b)
Definition: EllipseTypes.h:90
Optics(Point< K, boost::shared_ptr< RecordT > > *points, int numPoints, int minNeighbors, double epsilon, double leafExtentThreshold, int pointsPerLeaf)
Definition: Optics.cc:52
Main OPTICS algorithm implementation class.
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
Definition: Image.cc:291
std::vector< SourceCatalog > const cluster(SourceCatalog const &sources, ClusteringControl const &control)
Definition: clustering.cc:578
lsst::pex::logging::Log _log
Definition: Optics.h:86
int next
Index of next range query result or -1.
Definition: KDTree.h:90
Implementation of the SeedList class template.
int state
State of point ([un]processed or index in seed list)
Definition: KDTree.h:91
int d
Definition: KDTree.cc:89
boost::scoped_array< double > _distances
Definition: Optics.h:81
double max
Definition: attributes.cc:218
void log(int importance, const std::string &message, const lsst::daf::base::PropertySet &properties)
void run(boost::shared_ptr< typename RecordT::Table > table, std::vector< typename RecordT::Catalog > &clusters, MetricT const &metric)
Definition: Optics.cc:112
void format(int importance, const char *fmt,...)
Implementation of the KDTree class template.
boost::scoped_ptr< KDTree< K, DataT > > _tree
Definition: Optics.h:79
#define LSST_EXCEPT(type,...)
Definition: Exception.h:46
void expandClusterOrder(int i, MetricT const &metric)
Definition: Optics.cc:163
boost::scoped_ptr< SeedList< K, DataT > > _seeds
Definition: Optics.h:80
Point< K, DataT > * _points
Definition: Optics.h:78
Include files required for standard LSST Exception handling.
double dist
Distance to query point.
Definition: KDTree.h:87