Skip to content

Commit 80c226e

Browse files
committed
Merge branch 'mlarson/neighest_neighbors'
2 parents 468dee7 + 13cd9a9 commit 80c226e

1 file changed

Lines changed: 32 additions & 47 deletions

File tree

kingmaker/wrapper.py

Lines changed: 32 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
from typing import Any, Dict, List, Optional, Tuple, Union, cast
1+
from typing import Any, Dict, List, Optional, Tuple, Union
22
import numpy.typing as npt
33

44
from os.path import exists
55
import logging
66
import numpy as np
77
import healpy as hp
8-
from scipy.interpolate import interpn
98

109
from .pdf import InterpolatedKingPDF, TemplateSmearedKingPDF
1110
from .fitting import KingPSFFitter
@@ -117,6 +116,15 @@ def __init__(
117116
self.parametrization_bins.items()
118117
except AttributeError:
119118
self.parametrization_bins = self.parametrization_bins.item()
119+
120+
# Extract the bin centers and keys for each event. The stored bins are
121+
# edges, but interpn requires coordinates matching the values shape.
122+
self.keys, self.bin_centers = [], []
123+
for key, edges in self.parametrization_bins.items():
124+
self.keys.append(key)
125+
self.bin_centers.append((edges[:-1] + edges[1:]) / 2)
126+
127+
# And grab the fitted alpha/beta arrays
120128
self.alpha_values = fitted_parameters["alpha"]
121129
self.beta_values = fitted_parameters["beta"]
122130

@@ -135,7 +143,7 @@ def __init__(
135143
def events_match(self, events: npt.NDArray[Any]):
136144
if self.events is None:
137145
return False
138-
return np.array_equal(self.events["ra"], events["ra"]) & np.array_equal(
146+
return np.array_equal(self.events["ra"], events["ra"]) and np.array_equal(
139147
self.events["dec"], events["dec"]
140148
)
141149

@@ -175,37 +183,16 @@ def set_events(
175183
"that these arrays have the same length when passing into set_events."
176184
)
177185

178-
# Begin by finding the per-event alpha and beta values via interpolation.
179-
# Extract the bin centers and keys for each event. The stored bins are
180-
# edges, but interpn requires coordinates matching the values shape.
181-
keys, bins, event_param_values = [], [], []
182-
for key, edges in self.parametrization_bins.items():
183-
keys.append(key)
184-
bins.append((edges[:-1] + edges[1:]) / 2)
185-
event_param_values.append(events[key])
186-
187-
# Get the event parameter values for each parameter
188-
event_param_values = np.array(event_param_values).T
189-
190186
# Interpolate to get the alpha and beta values for each spectral index for
191187
# each event in the given sample.
188+
def index(centers, values):
189+
i = np.searchsorted(centers, values).clip(1, len(centers) - 1)
190+
return np.where(values - centers[i - 1] < centers[i] - values, i - 1, i)
191+
192+
event_indices = [index(self.bin_centers[i], events[key]) for i, key in enumerate(self.keys)]
192193
for i, gamma in enumerate(self.spectral_indices):
193-
self.event_alpha[gamma] = interpn(
194-
bins,
195-
self.alpha_values[i],
196-
event_param_values,
197-
bounds_error=False,
198-
fill_value=None,
199-
method="nearest",
200-
)
201-
self.event_beta[gamma] = interpn(
202-
bins,
203-
self.beta_values[i],
204-
event_param_values,
205-
bounds_error=False,
206-
fill_value=None,
207-
method="nearest",
208-
)
194+
self.event_alpha[gamma] = self.alpha_values[i][*event_indices]
195+
self.event_beta[gamma] = self.beta_values[i][*event_indices]
209196

210197
# Start calculating the pvalues.
211198
# TODO: By assuming keys "ra" and "dec" exist and are usable here, we're
@@ -259,19 +246,17 @@ def evaluate_pdf(self, events: npt.NDArray[Any], gamma: float = 2) -> npt.NDArra
259246
" Please ensure that you call set_events with the same events that you later pass into evaluate_pdf."
260247
)
261248

262-
if gamma in self.spectral_indices:
263-
# If the requested gamma is one of the fitted spectral indices, we can directly use those parameters.
264-
return cast(npt.NDArray[np.floating], self.event_pvalue[gamma])
265-
else:
266-
# Otherwise we have to interpolate the gamma values.
267-
idx = np.clip(
268-
np.searchsorted(self.spectral_indices, gamma) - 1, 0, len(self.spectral_indices) - 2
269-
)
270-
gamma_low, gamma_high = self.spectral_indices[idx], self.spectral_indices[idx + 1]
271-
return _interp1d(
272-
gamma,
273-
gamma_low,
274-
gamma_high,
275-
self.event_pvalue[gamma_low],
276-
self.event_pvalue[gamma_high],
277-
)
249+
# Interpolate over gamma to get the final result for each event
250+
idx = np.clip(
251+
np.searchsorted(self.spectral_indices, gamma) - 1, 0, len(self.spectral_indices) - 2
252+
)
253+
254+
gamma_low, gamma_high = self.spectral_indices[idx], self.spectral_indices[idx + 1]
255+
result = _interp1d(
256+
gamma,
257+
gamma_low,
258+
gamma_high,
259+
self.event_pvalue[gamma_low],
260+
self.event_pvalue[gamma_high],
261+
)
262+
return result

0 commit comments

Comments
 (0)