Skip to content

Commit aff66c3

Browse files
authored
Merge pull request #111 from fact-project/neighbors
Add function to return pixel neighborhood matrix
2 parents 3c6ad08 + 9fdee64 commit aff66c3

File tree

4 files changed

+73
-4
lines changed

4 files changed

+73
-4
lines changed

fact/VERSION

+1-1
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
0.20.1
1+
0.21.0

fact/instrument/camera.py

+43-3
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,12 @@
22
import numpy as np
33
from functools import lru_cache
44
import pandas as pd
5+
from scipy.sparse import csr_matrix
6+
from scipy.spatial import cKDTree
57

68
from .constants import (
79
FOCAL_LENGTH_MM, PINCUSHION_DISTORTION_SLOPE,
8-
PIXEL_SPACING_MM, FOV_PER_PIXEL_DEG
10+
PIXEL_SPACING_MM, FOV_PER_PIXEL_DEG, N_PIXEL
911
)
1012

1113

@@ -172,8 +174,10 @@ def combine_bias_patch_current_to_trigger_patch_current(bias_patch_currents):
172174
fivers = pi[pi.bias_patch_size == 5].sort_values('trigger_patch_id')
173175

174176
b_c = bias_patch_currents # just to shorten the name
175-
t_c = b_c[fourers.bias_patch_id.values] * 4/9 + b_c[fivers.bias_patch_id.values] * 5/9
176-
177+
t_c = (
178+
b_c[fourers.bias_patch_id.values] * 4 / 9
179+
+ b_c[fivers.bias_patch_id.values] * 5 / 9
180+
)
177181
trigger_patch_currents = t_c # unshorten the name
178182
return trigger_patch_currents
179183

@@ -190,3 +194,39 @@ def take_apart_trigger_values_for_bias_patches(trigger_rates):
190194
pi = patch_indices().sort_values('bias_patch_id')
191195

192196
return trigger_rates[pi.trigger_patch_id.values]
197+
198+
199+
@lru_cache(maxsize=1)
200+
def get_neighbor_matrix():
201+
'''
202+
Returns a sparse boolean neighbor matrix with n[chid, other_chid] = is neighbor.
203+
'''
204+
xy = get_pixel_dataframe().loc[:, ['x', 'y']].values
205+
tree = cKDTree(xy)
206+
neighbors = tree.query_ball_tree(tree, r=10)
207+
208+
n_neighbors = [len(n) for n in neighbors]
209+
col = np.repeat(np.arange(N_PIXEL), n_neighbors)
210+
row = [pix for n in neighbors for pix in n]
211+
data = np.ones(len(row))
212+
m = csr_matrix((data, (row, col)), shape=(N_PIXEL, N_PIXEL), dtype=bool)
213+
m.setdiag(False)
214+
return m
215+
216+
217+
@lru_cache(maxsize=1)
218+
def get_num_neighbors():
219+
'''
220+
Return a numpy array with the number of neighbors for each pixel in chid order
221+
'''
222+
return get_neighbor_matrix().sum(axis=0).A1
223+
224+
225+
@lru_cache()
226+
def get_border_pixel_mask(width=1):
227+
if width == 1:
228+
return get_num_neighbors() < 6
229+
230+
n = get_neighbor_matrix().todense().A
231+
232+
return (n & get_border_pixel_mask(width - 1)).any(axis=1)

fact/instrument/constants.py

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
from astropy.coordinates import EarthLocation
66
import astropy.units as u
77

8+
N_PIXEL = 1440
89
#: The inner diameter of the hexagonal pixels in mm.
910
#: This is also the grid constant of the hex grid.
1011
PIXEL_SPACING_MM = 9.5

tests/test_camera.py

+28
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import numpy as np
2+
3+
4+
def test_neighbors():
5+
from fact.instrument.camera import get_neighbor_matrix
6+
7+
neighbors = get_neighbor_matrix()
8+
9+
assert neighbors[1144, 259]
10+
assert neighbors[1144, 1143]
11+
assert neighbors[1144, 1146]
12+
assert neighbors[1144, 1147]
13+
assert neighbors[1144, 287]
14+
assert neighbors[1144, 284]
15+
assert not neighbors[1144, 256]
16+
assert not neighbors[1144, 281]
17+
18+
assert np.all(neighbors.diagonal() == 0)
19+
20+
21+
def test_n_neighbors():
22+
from fact.instrument.camera import get_num_neighbors
23+
24+
n_neighbors = get_num_neighbors()
25+
26+
assert n_neighbors[54] == 3
27+
assert n_neighbors[86] == 3
28+
assert n_neighbors[81] == 4

0 commit comments

Comments
 (0)