Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Tune scan #49

Open
wants to merge 29 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
daa01d9
tune_scan function description added
Sep 26, 2023
2cd91c1
corrected
Sep 26, 2023
09a77c8
indents
simoneliuzzo Sep 26, 2023
7becaaf
minors for help
simoneliuzzo Sep 26, 2023
1ed4e9f
remove error message. Fix conflict.
Sep 26, 2023
1a5db63
added doc. Removed unexplained inputs of quadrupoles.
Sep 26, 2023
c596445
revert changes
Sep 26, 2023
025d3de
revert changes
Sep 26, 2023
21640de
corrected conflicts
Sep 26, 2023
0d783a9
Merge branch 'master' into tune_scan
linahv Sep 26, 2023
55013c6
fit_tune documentation
Sep 28, 2023
b41ef80
added description of fit_tune
Sep 28, 2023
71410bb
changes in fit_tune
Sep 28, 2023
87f4b27
testing in progress
Sep 29, 2023
db8f62d
quadrupole input now allows N number of families, each with different…
Oct 5, 2023
12ce744
test functions for tune and chroma correction
Oct 5, 2023
1faa6b4
typo
Oct 5, 2023
6c3935d
succesful test
Oct 5, 2023
2d18041
Merge branch 'master' into tune_scan
linahv Oct 5, 2023
2a4eb29
updated documentation
Oct 5, 2023
55c699b
Merge branch 'tune_scan' of https://github.com/lmalina/pySC into tune…
Oct 5, 2023
3eb4a1b
removed the function tune
Oct 5, 2023
1fc73bf
minor corrections
Oct 11, 2023
9e349c5
added the assess line
Oct 11, 2023
f10b0f1
simplified function and updated default values
Oct 11, 2023
9b58b02
assert test function added, test succesful
Oct 11, 2023
14f1f2e
Merge branch 'master' into tune_scan
lmalina Jan 24, 2024
92895a6
Merge branch 'master' into tune_scan
lmalina Jan 24, 2024
962b6ba
Little fixes
lmalina Jan 24, 2024
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
55 changes: 30 additions & 25 deletions pySC/correction/tune.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

from pySC.core.beam import beam_transmission, plot_transmission
from pySC.utils import logging_tools
from pySC.utils.at_wrapper import atlinopt


LOGGER = logging_tools.get_logger(__name__)

Expand Down Expand Up @@ -129,32 +129,37 @@ def plot_scan(fin_trans, max_turns, first_quads, rel_quad_changes):
return f, [ax1, ax2, ax3]


def fit_tune(SC, q_ords, target_tune=None, xtol=1E-4, ftol=1E-3, fit_integer=True):
# TODO check if experimantally feasible
def fit_tune(SC, q_ords, target_tune=None, init_step_size=np.array([0.0001, 0.0001]),xtol=1E-3, ftol=1E-3, fit_integer=True):
"""
Applies a tune correction using two quadrupole families.
Note: this is not beam based but assumes the tunes can be measured reasonably well.

Args:
SC: SimulatedCommissioning instance
q_ords: [2xN] array or list [[1 x NQ1],[1 x NQ2], [1 x NQ3], ...] of quadrupole ordinates
target_tune (optional, [1x2] array): Target tunes for correction. Default: tunes of 'SC.IDEALRING'
init_step_size ([1x2] array, optional): Initial step size for the solver. Default: [0.0001,0.0001]
xtol(float, optional): Step tolerance for solver. Default: 1e-3
ftol(float, optional): Merit tolerance for solver. Default: 1e-3
fit_integer(bool, optional): Flag specifying if the integer part should be fitted as well. Default: True.

Returns:
SC: SimulatedCommissioning instance with corrected tunes.
Example:
SC = fit_tune(SC, q_ords=[SCgetOrds(sc.RING, 'QF'), SCgetOrds(sc.RING, 'QD')], target_tune=numpy.array([0.16,0.21]))
"""
if target_tune is None:
target_tune = tune(SC, fit_integer, ideal=True)
LOGGER.debug(f'Fitting tunes from [{tune(SC, fit_integer)}] to [{target_tune}].')
SP0 = np.zeros((len(q_ords), len(q_ords[0]))) # TODO can the lengts vary
for nFam in range(len(q_ords)):
for n in range(len(q_ords[nFam])):
SP0[nFam][n] = SC.RING[q_ords[nFam][n]].SetPointB[1]
fun = lambda x: _fit_tune_fun(SC, q_ords, x, SP0, target_tune, fit_integer)
sol = fmin(fun, xtol=xtol, ftol=ftol)
SC.set_magnet_setpoints(q_ords, sol + SP0, False, 1, method='abs', dipole_compensation=True)
LOGGER.debug(f' Final tune: [{tune(SC, fit_integer)}]\n Setpoints change: [{sol}]')
target_tune = SC.IDEALRING.get_tune(get_integer=fit_integer)[:2]
LOGGER.debug(f'Fitting tunes from [{SC.RING.get_tune(get_integer=fit_integer)}] to [{target_tune}].')
fun = lambda x: _fit_tune_fun(SC, q_ords, x, target_tune, fit_integer)
sol = fmin(fun, init_step_size, xtol=xtol, ftol=ftol)
LOGGER.debug(f' Final tune: [{SC.RING.get_tune(get_integer=fit_integer)}]\n Setpoints change: [{sol}]')
return SC


def _fit_tune_fun(SC, q_ords, setpoints, init_setpoints, target, fit_integer):
SC.set_magnet_setpoints(q_ords, setpoints + init_setpoints, False, 1, method='abs', dipole_compensation=True)
nu = tune(SC, fit_integer)
def _fit_tune_fun(SC, q_ords, setpoints, target, fit_integer):
for nFam in range(len(q_ords)):
# TODO check the add method here
SC.set_magnet_setpoints(q_ords[nFam], setpoints[nFam], False, 1, method='add', dipole_compensation=True)
nu = SC.RING.get_tune(get_integer=fit_integer)[:2]
return np.sqrt(np.mean((nu - target) ** 2))


def tune(SC, fit_integer: bool = False, ideal: bool = False):
ring = SC.IDEALRING if ideal else SC.RING
if fit_integer:
ld, _, _ = atlinopt(ring, 0, range(len(ring) + 1))
return ld[-1].mu / 2 / np.pi
_, nu, _ = atlinopt(ring, 0)
return nu
24 changes: 24 additions & 0 deletions tests/test_tune.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import pytest
import numpy as np
from numpy.testing import assert_allclose
from tests.test_at_wrapper import at_lattice
from pySC.core.simulated_commissioning import SimulatedCommissioning
from pySC.correction.tune import fit_tune
from pySC.utils import sc_tools


def test_fit_tune(sc):
sc = fit_tune(sc, q_ords=[sc_tools.ords_from_regex(sc.RING, 'QF'),
sc_tools.ords_from_regex(sc.RING, 'QD')],
target_tune=sc.RING.get_tune(get_integer=True)[:2] + [0.005, -0.005], fit_integer=True)
# TODO with this tolerance it is not testing much
assert_allclose(actual=sc.RING.get_tune()[:2], desired=sc.RING.get_tune()[:2] + [0.005, -0.005], rtol=1e-2)
return sc


@pytest.fixture
def sc(at_lattice):
SC = SimulatedCommissioning(at_lattice)
SC.register_magnets(sc_tools.ords_from_regex(SC.RING, 'QF'))
SC.register_magnets(sc_tools.ords_from_regex(SC.RING, 'QD'))
return SC
Loading