1pub mod naive;
22pub mod geom;
24pub mod geom_tile;
26
27use crate::distance::Distance;
28use crate::pseudojet::PseudoJet;
29
30use std::cmp::Ord;
31use std::hash::Hash;
32
33use log::debug;
34
35use self::{naive::ClusterNaive, geom::ClusterGeom, geom_tile::ClusterGeomTile};
36
37#[deprecated = "Use `Cluster::cluster` instead"]
39pub fn cluster<D: Distance>(partons: Vec<PseudoJet>, d: &D) -> Vec<PseudoJet> {
40 partons.cluster_if(d, |_| true)
41}
42
43#[deprecated = "Use `Cluster::cluster_if` instead"]
46pub fn cluster_if<D, F>(
47 partons: Vec<PseudoJet>,
48 d: &D,
49 accept: F,
50) -> Vec<PseudoJet>
51where
52 D: Distance,
53 F: FnMut(PseudoJet) -> bool,
54{
55 partons.cluster_if(d, accept)
56}
57
58pub trait Cluster {
60 fn cluster<D: Distance>(self, d: D) -> Vec<PseudoJet>;
62
63 fn cluster_if<D, F>(self, d: D, accept: F) -> Vec<PseudoJet>
66 where
67 D: Distance,
68 F: FnMut(PseudoJet) -> bool;
69}
70
71impl Cluster for Vec<PseudoJet> {
72 fn cluster_if<D, F>(self, d: D, mut accept: F) -> Vec<PseudoJet>
73 where
74 D: Distance,
75 F: FnMut(PseudoJet) -> bool
76 {
77 debug!("clustering partons: {self:#?}");
78 let clustering = ClusterHistory::new(self, d);
79
80 clustering
81 .filter_map(|s| match s {
82 ClusterStep::Jet(jet) if accept(jet) => Some(jet),
83 _ => None,
84 })
85 .collect()
86 }
87
88 fn cluster<D: Distance>(self, d: D) -> Vec<PseudoJet> {
89 self.cluster_if(d, |_| true)
90 }
91}
92
93impl<'a, T> Cluster for &'a [T]
94where &'a T: Into<PseudoJet>
95{
96 fn cluster_if<D, F>(self, d: D, accept: F) -> Vec<PseudoJet>
97 where
98 D: Distance,
99 F: FnMut(PseudoJet) -> bool
100 {
101 let partons = Vec::from_iter(self.iter().map(|p| p.into()));
102 partons.cluster_if(d, accept)
103 }
104
105 fn cluster<D: Distance>(self, d: D) -> Vec<PseudoJet> {
106 self.cluster_if(d, |_| true)
107 }
108}
109
110#[derive(Clone, Debug, Ord, PartialOrd)]
112pub enum ClusterStep {
113 Combine([PseudoJet; 2]),
115 Jet(PseudoJet),
117}
118
119impl From<[PseudoJet; 2]> for ClusterStep {
120 fn from(source: [PseudoJet; 2]) -> Self {
121 Self::Combine(source)
122 }
123}
124
125impl From<PseudoJet> for ClusterStep {
126 fn from(jet: PseudoJet) -> Self {
127 Self::Jet(jet)
128 }
129}
130
131impl PartialEq for ClusterStep {
132 fn eq(&self, other: &Self) -> bool {
133 match (self, other) {
134 (Self::Combine(left), Self::Combine(right)) => left == right || (
135 (left[0] == right[1]) && (left[1] == right[0])
136 ),
137 (Self::Jet(l0), Self::Jet(r0)) => l0 == r0,
138 _ => false,
139 }
140 }
141}
142
143impl Eq for ClusterStep { }
144
145impl Hash for ClusterStep {
146 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
147 match self {
148 ClusterStep::Combine([p1, p2]) => {
149 if p1 < p2 {
150 [p1, p2].hash(state)
151 } else {
152 [p2, p1].hash(state)
153 }
154 },
155 ClusterStep::Jet(p1) => p1.hash(state),
156 }
157 }
158}
159
160pub trait ClusterHist: Iterator<Item = ClusterStep>{}
162
163impl<T> ClusterHist for T where T: Iterator<Item = ClusterStep> { }
164
165pub struct ClusterHistory<'a> (
167 Box<dyn ClusterHist + 'a>
168);
169
170impl<'a> ClusterHistory<'a> {
171 const START_GEOM_THRESHOLD: usize = 25;
172 const END_GEOM_THRESHOLD: usize = 49;
173 const START_TILE_THRESHOLD: usize = Self::END_GEOM_THRESHOLD + 1;
174
175 pub fn new<D: Distance + 'a>(partons: Vec<PseudoJet>, distance: D) -> Self {
177 let hist: Box<dyn ClusterHist> = match partons.len() {
178 Self::START_TILE_THRESHOLD.. =>
179 Box::new(ClusterGeomTile::new(partons, distance)),
180 Self::START_GEOM_THRESHOLD..=Self::END_GEOM_THRESHOLD =>
181 Box::new(ClusterGeom::new(partons, distance)),
182 _ => Box::new(ClusterNaive::new(partons, distance))
183 };
184 Self(hist)
185 }
186}
187
188impl<'a> Iterator for ClusterHistory<'a> {
189 type Item = ClusterStep;
190
191 fn next(&mut self) -> Option<Self::Item> {
193 self.0.next()
194 }
195}