Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pySC/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

"""

__version__ = "1.1.0"
__version__ = "1.1.1"

from .core.simulated_commissioning import SimulatedCommissioning
from .configuration.generation import generate_SC
Expand Down
11 changes: 9 additions & 2 deletions pySC/core/bpm_system.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from pydantic import BaseModel, PrivateAttr, ConfigDict, model_validator
from typing import TYPE_CHECKING, Optional, Union
from typing import TYPE_CHECKING, Optional, Union, Tuple
from .types import NPARRAY
import numpy as np
import warnings
Expand Down Expand Up @@ -62,9 +62,16 @@ def bpm_number(self, index: Optional[int] = None, name: Optional[str] = None) ->
bpm_number = int(np.where(np.array(self.indices) == index)[0][0])
else:
raise AssertionError('Exactly one of index and name must be defined.')

return bpm_number

def reconstruct_true_orbit(self, name: BPM_NAME_TYPE, x: float, y: float) -> Tuple[float,float]:
bpm_number = self.bpm_number(name=name)
rot_x = x/(1 + self.calibration_errors_x[bpm_number])
rot_y = y/(1 + self.calibration_errors_y[bpm_number])
reconstructed_x, reconstructed_y = np.matmul(self._rot_matrices[:,:,bpm_number].T, np.array([rot_x, rot_y]))
return reconstructed_x, reconstructed_y

def capture_orbit(self, bba=True, subtract_reference=True, use_design=False) -> tuple[np.ndarray, np.ndarray]:
'''
Simulates an orbit reading from the BPMs, applying calibration errors, offsets/rolls, and noise.
Expand Down
8 changes: 6 additions & 2 deletions pySC/core/lattice.py
Original file line number Diff line number Diff line change
Expand Up @@ -147,10 +147,14 @@ def get_orbit(self, indices: list[int] = None, use_design=False) -> dict:
indices = range(len(self._design))
ring = self._design if use_design else self._ring
if self.use_orbit_guess:
assert self.no_6d is False, "Using orbit guesses with a 4D lattice is not checked/implemented."
assert not self.no_6d, "Using orbit guesses with a 4D lattice is not checked/implemented."
_, orbit = at.find_orbit(ring, refpts=indices, guess=np.array(self.orbit_guess))
else:
_, orbit = at.find_orbit(ring, refpts=indices)
if self.no_6d and not use_design:
df = self.ring.get_rf_frequency() - self.design.get_rf_frequency()
_, orbit = at.find_orbit(ring, refpts=indices, df=df)
else:
_, orbit = at.find_orbit(ring, refpts=indices)

return orbit[:, [0,2]].T

Expand Down
28 changes: 20 additions & 8 deletions pySC/tuning/tuning_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -322,6 +322,8 @@ def do_trajectory_bba(self, bpm_names: Optional[list[str]] = None, shots_per_tra
offsets_y = np.zeros(n_bpm)
true_offsets_x = np.zeros(n_bpm)
true_offsets_y = np.zeros(n_bpm)
reconstructed_offsets_x = np.zeros(n_bpm)
reconstructed_offsets_y = np.zeros(n_bpm)
for ii, name in enumerate(bpm_names):
true_offset_x, true_offset_y = self.bba_to_quad_true_offset(bpm_name=name)
bpm_number = SC.bpm_system.bpm_number(name=name)
Expand All @@ -334,10 +336,11 @@ def do_trajectory_bba(self, bpm_names: Optional[list[str]] = None, shots_per_tra
true_offsets_y[ii] = true_offset_y
offsets_x[ii] = offset_x
offsets_y[ii] = offset_y
reconstructed_offsets_x[ii], reconstructed_offsets_y[ii] = SC.bpm_system.reconstruct_true_orbit(name=name, x=offset_x, y=offset_y)

if not skip_summary:
acc_x = 1e6 * np.nanstd(offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(offsets_y - true_offsets_y)
acc_x = 1e6 * np.nanstd(reconstructed_offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(reconstructed_offsets_y - true_offsets_y)
logger.info(f'Trajectory BBA accuracy, H: {acc_x:.1f} um, V: {acc_y:.1f} um')

for ii, bpm_number in enumerate(bpm_numbers):
Expand All @@ -356,6 +359,8 @@ def do_orbit_bba(self, bpm_names: Optional[list[str]] = None, shots_per_orbit: i
offsets_y = np.zeros(n_bpm)
true_offsets_x = np.zeros(n_bpm)
true_offsets_y = np.zeros(n_bpm)
reconstructed_offsets_x = np.zeros(n_bpm)
reconstructed_offsets_y = np.zeros(n_bpm)
for ii, name in enumerate(bpm_names):
true_offset_x, true_offset_y = self.bba_to_quad_true_offset(bpm_name=name)
bpm_number = SC.bpm_system.bpm_number(name=name)
Expand All @@ -368,10 +373,11 @@ def do_orbit_bba(self, bpm_names: Optional[list[str]] = None, shots_per_orbit: i
true_offsets_y[ii] = true_offset_y
offsets_x[ii] = offset_x
offsets_y[ii] = offset_y
reconstructed_offsets_x[ii], reconstructed_offsets_y[ii] = SC.bpm_system.reconstruct_true_orbit(name=name, x=offset_x, y=offset_y)

if not skip_summary:
acc_x = 1e6 * np.nanstd(offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(offsets_y - true_offsets_y)
acc_x = 1e6 * np.nanstd(reconstructed_offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(reconstructed_offsets_y - true_offsets_y)
logger.info(f'Orbit BBA accuracy, H: {acc_x:.1f} um, V: {acc_y:.1f} um')

for ii, bpm_number in enumerate(bpm_numbers):
Expand Down Expand Up @@ -417,19 +423,22 @@ def do_parallel_trajectory_bba(self, bpm_names: Optional[list[str]] = None, shot
offsets_y = np.zeros(n_bpm)
true_offsets_x = np.zeros(n_bpm)
true_offsets_y = np.zeros(n_bpm)
reconstructed_offsets_x = np.zeros(n_bpm)
reconstructed_offsets_y = np.zeros(n_bpm)
for bpm_names_chunk, offsets_x_chunk, offsets_y_chunk in rets:
for name, offset_x, offset_y in zip(bpm_names_chunk, offsets_x_chunk, offsets_y_chunk):
ii = bpm_mapping[name]
offsets_x[ii] = offset_x
offsets_y[ii] = offset_y
reconstructed_offsets_x[ii], reconstructed_offsets_y[ii] = SC.bpm_system.reconstruct_true_orbit(name=name, x=offset_x, y=offset_y)
true_offsets_x[ii], true_offsets_y[ii] = SC.tuning.bba_to_quad_true_offset(bpm_name=name)

# 4. CLEANUP
listener.stop()
logger.handlers.clear()

acc_x = 1e6 * np.nanstd(offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(offsets_y - true_offsets_y)
acc_x = 1e6 * np.nanstd(reconstructed_offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(reconstructed_offsets_y - true_offsets_y)
logger.info(f'Trajectory BBA accuracy, H: {acc_x:.1f} um, V: {acc_y:.1f} um')

bpm_numbers = [SC.bpm_system.bpm_number(name=name) for name in bpm_names]
Expand Down Expand Up @@ -475,19 +484,22 @@ def do_parallel_orbit_bba(self, bpm_names: Optional[list[str]] = None, shots_per
offsets_y = np.zeros(n_bpm)
true_offsets_x = np.zeros(n_bpm)
true_offsets_y = np.zeros(n_bpm)
reconstructed_offsets_x = np.zeros(n_bpm)
reconstructed_offsets_y = np.zeros(n_bpm)
for bpm_names_chunk, offsets_x_chunk, offsets_y_chunk in rets:
for name, offset_x, offset_y in zip(bpm_names_chunk, offsets_x_chunk, offsets_y_chunk):
ii = bpm_mapping[name]
offsets_x[ii] = offset_x
offsets_y[ii] = offset_y
reconstructed_offsets_x[ii], reconstructed_offsets_y[ii] = SC.bpm_system.reconstruct_true_orbit(name=name, x=offset_x, y=offset_y)
true_offsets_x[ii], true_offsets_y[ii] = SC.tuning.bba_to_quad_true_offset(bpm_name=name)

# 4. CLEANUP
listener.stop()
logger.handlers.clear()

acc_x = 1e6 * np.nanstd(offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(offsets_y - true_offsets_y)
acc_x = 1e6 * np.nanstd(reconstructed_offsets_x - true_offsets_x)
acc_y = 1e6 * np.nanstd(reconstructed_offsets_y - true_offsets_y)
logger.info(f'Orbit BBA accuracy, H: {acc_x:.1f} um, V: {acc_y:.1f} um')

bpm_numbers = [SC.bpm_system.bpm_number(name=name) for name in bpm_names]
Expand Down
4 changes: 2 additions & 2 deletions pySC/utils/rdt.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,8 +142,8 @@ def fjklm(SC: Optional["SimulatedCommissioning"] = None, j: int = 0, k: int = 0,
ii = 0
f = np.zeros_like(twiss['s'], dtype=complex)
for ii in range(len(twiss['s'])):
dphix = 2*np.pi*np.abs(twiss['mux'][ii] - mux)
dphiy = 2*np.pi*np.abs(twiss['muy'][ii] - muy)
dphix = np.abs(twiss['mux'][ii] - mux)
dphiy = np.abs(twiss['muy'][ii] - muy)
expo = np.exp(1.j * ( (j-k) * dphix + (l-m) * dphiy))
f[ii] = np.sum(hm * expo)
if normalized:
Expand Down