31 #ifndef LSST_AP_CLUSTER_DETAIL_OPTICS_CC
32 #define LSST_AP_CLUSTER_DETAIL_OPTICS_CC
45 namespace lsst {
namespace ap {
namespace cluster {
namespace detail {
51 template <
int K,
typename RecordT>
56 double leafExtentThreshold,
63 _numPoints(numPoints),
64 _minNeighbors(minNeighbors),
66 _log(lsst::pex::logging::Log::getDefaultLog(),
"lsst.ap.cluster.detail")
69 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
70 "Input point array is null");
73 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
74 "Number of input points must be at least 1");
77 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
78 "OPTICS minNeighbors parameter value is negative");
81 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
82 "OPTICS epsilon parameter value is negative");
84 if (pointsPerLeaf <= 0) {
85 throw LSST_EXCEPT(lsst::pex::exceptions::InvalidParameterError,
86 "K-D tree pointsPerLeaf parameter must be positive");
91 points, numPoints, pointsPerLeaf, leafExtentThreshold));
93 "Created k-d tree for %d sources", numPoints);
97 boost::scoped_array<double> distances(
new double[
_minNeighbors]);
104 template <
int K,
typename RecordT>
110 template <
int K,
typename RecordT>
111 template <
typename MetricT>
113 std::vector<typename RecordT::Catalog> & clusters,
114 MetricT
const & metric)
117 throw LSST_EXCEPT(lsst::pex::exceptions::LogicError,
118 "OPTICS has already been run");
120 typename RecordT::Catalog
cluster(table);
121 size_t const s = clusters.size();
129 if (_seeds->empty()) {
131 for (i = scanFrom; i < _numPoints; ++i) {
137 if (i == _numPoints) {
141 expandClusterOrder(i, metric);
142 if (cluster.size() > 0) {
144 clusters.push_back(cluster);
147 cluster.push_back(_points[i].data);
151 expandClusterOrder(i, metric);
152 assert(_points[i].reach != std::numeric_limits<double>::infinity());
153 cluster.push_back(_points[i].data);
156 clusters.push_back(cluster);
158 static_cast<int>(clusters.size() - s));
161 template <
int K,
typename RecordT>
162 template <
typename MetricT>
166 int range = _tree->inRange(_points[i].coords, _epsilon, metric);
174 if (n < _minNeighbors) {
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);
185 if (n == _minNeighbors) {
188 double coreDist = _distances[0];
202 #endif // LSST_AP_CLUSTER_DETAIL_OPTICS_CC
void swap(Ellipse< DataT > &a, Ellipse< DataT > &b)
Optics(Point< K, boost::shared_ptr< RecordT > > *points, int numPoints, int minNeighbors, double epsilon, double leafExtentThreshold, int pointsPerLeaf)
Main OPTICS algorithm implementation class.
void swap(ImageBase< PixelT > &a, ImageBase< PixelT > &b)
std::vector< SourceCatalog > const cluster(SourceCatalog const &sources, ClusteringControl const &control)
lsst::pex::logging::Log _log
int next
Index of next range query result or -1.
Implementation of the SeedList class template.
int state
State of point ([un]processed or index in seed list)
boost::scoped_array< double > _distances
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)
void format(int importance, const char *fmt,...)
Implementation of the KDTree class template.
boost::scoped_ptr< KDTree< K, DataT > > _tree
#define LSST_EXCEPT(type,...)
void expandClusterOrder(int i, MetricT const &metric)
boost::scoped_ptr< SeedList< K, DataT > > _seeds
Point< K, DataT > * _points
Include files required for standard LSST Exception handling.
double dist
Distance to query point.