From 440b6103f76187b4e828cff60b07ed93820d62a3 Mon Sep 17 00:00:00 2001 From: rricesmith <39073117+rricesmith@users.noreply.github.com> Date: Fri, 16 Feb 2024 18:15:17 -0800 Subject: [PATCH 1/2] Update detector_base.py Modifications to function get_parallel_channels: -Fixed bug where it attempted to save differently sized numpy arrays into a single array, causing an error -Removed repeats of parallel or individual channels from being returned -Added a tolerance parameter, which allows for there to be deviation in parallel channels and still be counted as parallel. Necessary for detector descriptions of real experiments whose antennas may deviate by a few degrees --- NuRadioReco/detector/detector_base.py | 78 ++++++++++++++------------- 1 file changed, 42 insertions(+), 36 deletions(-) diff --git a/NuRadioReco/detector/detector_base.py b/NuRadioReco/detector/detector_base.py index fd4e2ffd4..b48714a72 100644 --- a/NuRadioReco/detector/detector_base.py +++ b/NuRadioReco/detector/detector_base.py @@ -607,42 +607,48 @@ def get_channel_ids(self, station_id): channel_ids.append(channel['channel_id']) return sorted(channel_ids) - def get_parallel_channels(self, station_id): - """ - get a list of parallel antennas - - Parameters - ---------- - station_id: int - the station id - - Returns list of list of ints - """ - res = self.__get_channels(station_id) - orientations = np.zeros((len(res), 4)) - antenna_types = [] - channel_ids = [] - for iCh, ch in enumerate(res.values()): - channel_id = ch['channel_id'] - channel_ids.append(channel_id) - antenna_types.append(self.get_antenna_type(station_id, channel_id)) - orientations[iCh] = self.get_antenna_orientation(station_id, channel_id) - orientations[iCh][3] = hp.get_normalized_angle(orientations[iCh][3], interval=np.deg2rad([0, 180])) - channel_ids = np.array(channel_ids) - antenna_types = np.array(antenna_types) - orientations = np.round(np.rad2deg(orientations)) # round to one degree to overcome rounding errors - parallel_antennas = [] - for antenna_type in np.unique(antenna_types): - for u_zen_ori in np.unique(orientations[:, 0]): - for u_az_ori in np.unique(orientations[:, 1]): - for u_zen_rot in np.unique(orientations[:, 2]): - for u_az_rot in np.unique(orientations[:, 3]): - mask = (antenna_types == antenna_type) \ - & (orientations[:, 0] == u_zen_ori) & (orientations[:, 1] == u_az_ori) \ - & (orientations[:, 2] == u_zen_rot) & (orientations[:, 3] == u_az_rot) - if np.sum(mask): - parallel_antennas.append(channel_ids[mask]) - return np.array(parallel_antennas) + def get_parallel_channels(self, station_id, tol=1*units.deg): + """ + get a list of parallel antennas + + Parameters + ---------- + station_id: int + the station id + tol: float + tolerance to difference in angles between parallel channels + + Returns list of list of ints + """ + res = self.__get_channels(station_id) + orientations = np.zeros((len(res), 4)) + antenna_types = [] + channel_ids = [] + for iCh, ch in enumerate(res.values()): + channel_id = ch['channel_id'] + channel_ids.append(channel_id) + antenna_types.append(self.get_antenna_type(station_id, channel_id)) + orientations[iCh] = self.get_antenna_orientation(station_id, channel_id) + orientations[iCh][3] = hp.get_normalized_angle(orientations[iCh][3], interval=np.deg2rad([0, 180])) + channel_ids = np.array(channel_ids) + antenna_types = np.array(antenna_types) + parallel_antennas = [] + for antenna_type in np.unique(antenna_types): + for u_zen_ori in np.unique(orientations[:, 0]): + for u_az_ori in np.unique(orientations[:, 1]): + for u_zen_rot in np.unique(orientations[:, 2]): + for u_az_rot in np.unique(orientations[:, 3]): + mask = (antenna_types == antenna_type) \ + & (np.abs(orientations[:, 0] - u_zen_ori) < tol) & (np.abs(orientations[:, 1] - u_az_ori) < tol) \ + & (np.abs(orientations[:, 2] - u_zen_rot) < tol) & (np.abs(orientations[:, 3] - u_az_rot) < tol) + if np.sum(mask): + match = False + for pair in parallel_antennas: + if np.array_equal(pair, channel_ids[mask]): + match = True + if not match: + parallel_antennas.append(channel_ids[mask]) + return parallel_antennas From 1cea1561827cd30aeb1a8a1bb3601ed1ef200f49 Mon Sep 17 00:00:00 2001 From: rricesmith <39073117+rricesmith@users.noreply.github.com> Date: Thu, 29 Feb 2024 12:55:09 -0800 Subject: [PATCH 2/2] Update detector_base.py -Added helper function for finding tolerance within periodicity of angles -Removed case where an antenna could be parallel in one orientation, but not another, resulting in a repeat of the channel. Ie before, it could return [[0, 1], [0]]. Now it only returns at minimum pairs, unless the channel is not parallel to any other channels. --- NuRadioReco/detector/detector_base.py | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/NuRadioReco/detector/detector_base.py b/NuRadioReco/detector/detector_base.py index b48714a72..394355171 100644 --- a/NuRadioReco/detector/detector_base.py +++ b/NuRadioReco/detector/detector_base.py @@ -607,7 +607,7 @@ def get_channel_ids(self, station_id): channel_ids.append(channel['channel_id']) return sorted(channel_ids) - def get_parallel_channels(self, station_id, tol=1*units.deg): + def get_parallel_channels(self, station_id, tol=1*units.deg, anti_parallel=False): """ get a list of parallel antennas @@ -617,9 +617,16 @@ def get_parallel_channels(self, station_id, tol=1*units.deg): the station id tol: float tolerance to difference in angles between parallel channels + atni-parallel: bool + if True, also returns anti-parallel channels Returns list of list of ints """ + def angle_diff(a, b, anti_parallel=False): + if anti_parallel: + return np.abs(hp.get_normalized_angle(a - b, interval=np.deg2rad([0, 90]))) + return np.abs(hp.get_normalized_angle(a - b, interval=np.deg2rad([0, 180]))) + res = self.__get_channels(station_id) orientations = np.zeros((len(res), 4)) antenna_types = [] @@ -639,12 +646,12 @@ def get_parallel_channels(self, station_id, tol=1*units.deg): for u_zen_rot in np.unique(orientations[:, 2]): for u_az_rot in np.unique(orientations[:, 3]): mask = (antenna_types == antenna_type) \ - & (np.abs(orientations[:, 0] - u_zen_ori) < tol) & (np.abs(orientations[:, 1] - u_az_ori) < tol) \ - & (np.abs(orientations[:, 2] - u_zen_rot) < tol) & (np.abs(orientations[:, 3] - u_az_rot) < tol) + & (angle_diff(orientations[:, 0], u_zen_ori, anti_parallel) <= tol) & (angle_diff(orientations[:, 1], u_az_ori, anti_parallel) <= tol) \ + & (angle_diff(orientations[:, 2], u_zen_rot, anti_parallel) <= tol) & (angle_diff(orientations[:, 3], u_az_rot, anti_parallel) <= tol) if np.sum(mask): match = False for pair in parallel_antennas: - if np.array_equal(pair, channel_ids[mask]): + if np.array_equal(pair, channel_ids[mask] or np.all(np.isin(channel_ids[mask], pair)): match = True if not match: parallel_antennas.append(channel_ids[mask])