From 00b63a2f0339f6862a10a0ea885ed81b585de123 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 14 Aug 2026 09:56:07 -0300 Subject: [PATCH 1/9] add local orbit distortion filter --- siriuspy/siriuspy/devices/sofb.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index ffec4e613..11d5f731f 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1155,6 +1155,21 @@ def wait_drive(self, timeout=None): 'DriveState-Sts', self._data.DriveState.Open, timeout=timeout ) + def filter_local_distortions(self, corr_idcs, dorb=None, respmat=None): + """Filters local distortions. + Returns orbit distortion due to local perturbation. + """ + respmat = respmat or self.respmat + if dorb is None: + orb = _np.concatenate((self.orbx, self.orby)) + dorb = orb - _np.concatenate((self.refx, self.refy)) + proj_mat = proj_mat = _np.zeros((respmat.shape[1], respmat.shape[1])) + proj_mat[corr_idcs, corr_idcs] = 1 + kick = _np.linalg.pinv(respmat) @ dorb.T + kick_sel = _np.dot(proj_mat, kick) + dorb_filtered = (respmat @ kick_sel).T + return dorb_filtered + @staticmethod def si_calculate_bumps( orbx, From 0c2548afbfac87817389d97a86ed1bbbb86024e6 Mon Sep 17 00:00:00 2001 From: Gabrielrezende-asc <99893658+Gabrielrezende-asc@users.noreply.github.com> Date: Fri, 14 Aug 2026 13:16:21 -0300 Subject: [PATCH 2/9] Update siriuspy/siriuspy/devices/sofb.py Following Fernando suggestions Co-authored-by: fernandohds564 --- siriuspy/siriuspy/devices/sofb.py | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index 11d5f731f..5bb667f48 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1163,12 +1163,11 @@ def filter_local_distortions(self, corr_idcs, dorb=None, respmat=None): if dorb is None: orb = _np.concatenate((self.orbx, self.orby)) dorb = orb - _np.concatenate((self.refx, self.refy)) - proj_mat = proj_mat = _np.zeros((respmat.shape[1], respmat.shape[1])) - proj_mat[corr_idcs, corr_idcs] = 1 - kick = _np.linalg.pinv(respmat) @ dorb.T - kick_sel = _np.dot(proj_mat, kick) - dorb_filtered = (respmat @ kick_sel).T - return dorb_filtered + kicks = _np.linalg.lstsq(respmat, dorb, rcond=None)[0] + sel = _np.zeros(kicks.shape, dtype=bool) + sel[corr_idcs] = True + kicks[~sel] = 0 + return respmat @ kicks @staticmethod def si_calculate_bumps( From 9f164edb12044ce14449ead48fba488627f5e84b Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 14 Aug 2026 13:22:50 -0300 Subject: [PATCH 3/9] add functions to find corrs indices --- siriuspy/siriuspy/devices/sofb.py | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index 5bb667f48..5d30151ec 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1194,6 +1194,28 @@ def si_calculate_bumps( minsingval=minsingval, ) + @staticmethod + def find_closest_corrs_ss(ss, nr_ch, nr_cv): + """Find the closest correctors indices to a given sector indices in SOFB matrix.""" + nch = 6 + ncv = 8 + idx_upstream = (ss-1)*nch + idx_downstream = (ss-1)*nch + 1 + idcs_ch_up = idx_upstream - _np.arange(int(nr_ch/2)) + idcs_ch_dw = idx_downstream + _np.arange(int(nr_ch/2)) + idcs_ch = _np.sort(_np.concatenate((idcs_ch_up, idcs_ch_dw))) + idcs_ch = _np.mod(idcs_ch, 120) + + idx_upstream = (ss-1)*ncv + idx_downstream = (ss-1)*ncv + 1 + idcs_cv_up = idx_upstream - _np.arange(int(nr_cv/2)) + idcs_cv_dw = idx_downstream + _np.arange(int(nr_cv/2)) + idcs_cv = _np.sort(_np.concatenate((idcs_cv_up, idcs_cv_dw))) + idcs_cv = _np.mod(idcs_cv, 160) + 120 + + idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) + return idcs_corrs + @property def trajx(self): """.""" From baa3ffad7f94b29972fde770df347d02b3aa3471 Mon Sep 17 00:00:00 2001 From: Gabrielrezende-asc <99893658+Gabrielrezende-asc@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:59:27 -0300 Subject: [PATCH 4/9] Update siriuspy/siriuspy/devices/sofb.py Co-authored-by: fernandohds564 --- siriuspy/siriuspy/devices/sofb.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index 5d30151ec..0ef75c46a 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1214,6 +1214,8 @@ def find_closest_corrs_ss(ss, nr_ch, nr_cv): idcs_cv = _np.mod(idcs_cv, 160) + 120 idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) + if inc_rf: + idcs_corrs = _np.r[idcs_corrs, 281] return idcs_corrs @property From 067bfae49e1b7f17d0765a28e99420914ea406fc Mon Sep 17 00:00:00 2001 From: Gabrielrezende-asc <99893658+Gabrielrezende-asc@users.noreply.github.com> Date: Fri, 14 Aug 2026 15:59:36 -0300 Subject: [PATCH 5/9] Update siriuspy/siriuspy/devices/sofb.py Co-authored-by: fernandohds564 --- siriuspy/siriuspy/devices/sofb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index 0ef75c46a..ce876c3b6 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1195,7 +1195,7 @@ def si_calculate_bumps( ) @staticmethod - def find_closest_corrs_ss(ss, nr_ch, nr_cv): + def find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=False): """Find the closest correctors indices to a given sector indices in SOFB matrix.""" nch = 6 ncv = 8 From 76adeb81526a952ef16e72243e716808975d7f8a Mon Sep 17 00:00:00 2001 From: Gabriel Date: Mon, 17 Aug 2026 12:34:22 -0300 Subject: [PATCH 6/9] update sofb orbit filter to work with dorbs with more dimensions --- siriuspy/siriuspy/devices/sofb.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index ce876c3b6..2a6d0cba0 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -1164,7 +1164,7 @@ def filter_local_distortions(self, corr_idcs, dorb=None, respmat=None): orb = _np.concatenate((self.orbx, self.orby)) dorb = orb - _np.concatenate((self.refx, self.refy)) kicks = _np.linalg.lstsq(respmat, dorb, rcond=None)[0] - sel = _np.zeros(kicks.shape, dtype=bool) + sel = _np.zeros(respmat.shape[1], dtype=bool) sel[corr_idcs] = True kicks[~sel] = 0 return respmat @ kicks From 91c89bed038fa470079955248db08e93bccc571a Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 18 Aug 2026 11:08:55 -0300 Subject: [PATCH 7/9] move filter functions to sofb.utils --- siriuspy/siriuspy/devices/sofb.py | 33 ++++++--------------------- siriuspy/siriuspy/sofb/utils.py | 37 +++++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/siriuspy/siriuspy/devices/sofb.py b/siriuspy/siriuspy/devices/sofb.py index 2a6d0cba0..1bdb7b38c 100644 --- a/siriuspy/siriuspy/devices/sofb.py +++ b/siriuspy/siriuspy/devices/sofb.py @@ -6,6 +6,8 @@ from ..sofb.csdev import SOFBFactory from ..sofb.utils import si_calculate_bump as _si_calculate_bump +from ..sofb.utils import filter_local_distortions as _filter_local_distortions +from ..sofb.utils import find_closest_corrs_ss as _find_closest_corrs_ss from .device import Device as _Device @@ -1157,17 +1159,15 @@ def wait_drive(self, timeout=None): def filter_local_distortions(self, corr_idcs, dorb=None, respmat=None): """Filters local distortions. + Returns orbit distortion due to local perturbation. """ respmat = respmat or self.respmat if dorb is None: orb = _np.concatenate((self.orbx, self.orby)) dorb = orb - _np.concatenate((self.refx, self.refy)) - kicks = _np.linalg.lstsq(respmat, dorb, rcond=None)[0] - sel = _np.zeros(respmat.shape[1], dtype=bool) - sel[corr_idcs] = True - kicks[~sel] = 0 - return respmat @ kicks + dorb_filtered = _filter_local_distortions(corr_idcs, dorb, respmat) + return dorb_filtered @staticmethod def si_calculate_bumps( @@ -1194,28 +1194,9 @@ def si_calculate_bumps( minsingval=minsingval, ) - @staticmethod - def find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=False): + def find_closest_corrs_ssection(self, ss, nr_ch, nr_cv, inc_rf=False): """Find the closest correctors indices to a given sector indices in SOFB matrix.""" - nch = 6 - ncv = 8 - idx_upstream = (ss-1)*nch - idx_downstream = (ss-1)*nch + 1 - idcs_ch_up = idx_upstream - _np.arange(int(nr_ch/2)) - idcs_ch_dw = idx_downstream + _np.arange(int(nr_ch/2)) - idcs_ch = _np.sort(_np.concatenate((idcs_ch_up, idcs_ch_dw))) - idcs_ch = _np.mod(idcs_ch, 120) - - idx_upstream = (ss-1)*ncv - idx_downstream = (ss-1)*ncv + 1 - idcs_cv_up = idx_upstream - _np.arange(int(nr_cv/2)) - idcs_cv_dw = idx_downstream + _np.arange(int(nr_cv/2)) - idcs_cv = _np.sort(_np.concatenate((idcs_cv_up, idcs_cv_dw))) - idcs_cv = _np.mod(idcs_cv, 160) + 120 - - idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) - if inc_rf: - idcs_corrs = _np.r[idcs_corrs, 281] + idcs_corrs = _find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=inc_rf) return idcs_corrs @property diff --git a/siriuspy/siriuspy/sofb/utils.py b/siriuspy/siriuspy/sofb/utils.py index f70cb7d62..8452012b2 100644 --- a/siriuspy/siriuspy/sofb/utils.py +++ b/siriuspy/siriuspy/sofb/utils.py @@ -74,3 +74,40 @@ def si_calculate_bump( orby[bpm1] += pos_bpm[2] orby[bpm2] += pos_bpm[3] return orbx, orby + + +def find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=False): + """Find the closest correctors indices to a given sector indices in SOFB matrix.""" + nch = 6 + ncv = 8 + idx_upstream = (ss-1)*nch + idx_downstream = (ss-1)*nch + 1 + idcs_ch_up = idx_upstream - _np.arange(int(nr_ch/2)) + idcs_ch_dw = idx_downstream + _np.arange(int(nr_ch/2)) + idcs_ch = _np.sort(_np.concatenate((idcs_ch_up, idcs_ch_dw))) + idcs_ch = _np.mod(idcs_ch, 120) + + idx_upstream = (ss-1)*ncv + idx_downstream = (ss-1)*ncv + 1 + idcs_cv_up = idx_upstream - _np.arange(int(nr_cv/2)) + idcs_cv_dw = idx_downstream + _np.arange(int(nr_cv/2)) + idcs_cv = _np.sort(_np.concatenate((idcs_cv_up, idcs_cv_dw))) + idcs_cv = _np.mod(idcs_cv, 160) + 120 + + idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) + if inc_rf: + idcs_corrs = _np.r[idcs_corrs, 281] + return idcs_corrs + + +def filter_local_distortions(corr_idcs, dorb=None, respmat=None): + """Filters local distortions. + + Returns orbit distortion due to local perturbation. + """ + kicks = _np.linalg.lstsq(respmat, dorb.T, rcond=None)[0] + sel = _np.zeros(respmat.shape[1], dtype=bool) + sel[corr_idcs] = True + kicks[~sel] = 0 + dorb_filt = respmat @ kicks + return dorb_filt.T From 0168724e25b57dc6cca76ee7218ea34fa3a7337e Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 21 Aug 2026 09:50:24 -0300 Subject: [PATCH 8/9] fix bug with np.r_ functions --- siriuspy/siriuspy/sofb/utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/siriuspy/siriuspy/sofb/utils.py b/siriuspy/siriuspy/sofb/utils.py index 8452012b2..ba356d453 100644 --- a/siriuspy/siriuspy/sofb/utils.py +++ b/siriuspy/siriuspy/sofb/utils.py @@ -96,7 +96,7 @@ def find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=False): idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) if inc_rf: - idcs_corrs = _np.r[idcs_corrs, 281] + idcs_corrs = _np.r_[idcs_corrs, 281] return idcs_corrs From f6bcd70fbdcabf1dda7c98b5c1f37a5877323eee Mon Sep 17 00:00:00 2001 From: Gabriel Date: Fri, 21 Aug 2026 12:14:26 -0300 Subject: [PATCH 9/9] improve documentation and fix bug --- siriuspy/siriuspy/sofb/utils.py | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/siriuspy/siriuspy/sofb/utils.py b/siriuspy/siriuspy/sofb/utils.py index ba356d453..764e9fe83 100644 --- a/siriuspy/siriuspy/sofb/utils.py +++ b/siriuspy/siriuspy/sofb/utils.py @@ -96,14 +96,25 @@ def find_closest_corrs_ss(ss, nr_ch, nr_cv, inc_rf=False): idcs_corrs = _np.concatenate((idcs_ch, idcs_cv)) if inc_rf: - idcs_corrs = _np.r_[idcs_corrs, 281] + idcs_corrs = _np.r_[idcs_corrs, 280] return idcs_corrs def filter_local_distortions(corr_idcs, dorb=None, respmat=None): - """Filters local distortions. - - Returns orbit distortion due to local perturbation. + """Filter local orbit distortions. + + Args: + corr_idcs (numpy 1D array or list): Indices of correctors to use. + dorb (2D or 1D numpy array, optional): array containing orbit + distortions x and y, in the case of a 2D array, + the second dimension must have length 320, + ie. (npts, 320). Defaults to None. + respmat (2D numpy array, optional): Orbit response matrix. + Defaults to None. + + Returns: + (2D or 1D numpy array): Returns the orbit distortion filtered + in an array with the same chape as the dorb array, ie (npts, 320). """ kicks = _np.linalg.lstsq(respmat, dorb.T, rcond=None)[0] sel = _np.zeros(respmat.shape[1], dtype=bool)