Skip to content

Commit

Permalink
Merge pull request #14 from T-Nicholls/bugFixes
Browse files Browse the repository at this point in the history
Bug fixes and volo related additions
  • Loading branch information
willrogers committed Aug 28, 2019
2 parents 318b11f + 6e1ca84 commit 82ccc20
Show file tree
Hide file tree
Showing 16 changed files with 815 additions and 432 deletions.
9 changes: 4 additions & 5 deletions INSTALL.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,13 @@ Initial Setup and Installation
$ cd <source-directory>
$ git clone https://github.com/atcollab/at.git
$ git clone https://github.com/dls-controls/pytac.git
$ git clone https://github.com/T-Nicholls/atip.git
$ git clone https://github.com/dls-controls/atip.git

2. Create a virtual enviroment and install the dependencies::
2. Create a pipenv and install the dependencies::

$ cd atip
$ virtualenv --no-site-packages venv
$ source venv/bin/activate
$ pip install -r requirements
$ pipenv install --dev
$ pipenv shell

3. Build AT's .so files::

Expand Down
129 changes: 67 additions & 62 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,32 @@
:target: https://coveralls.io/github/dls-controls/atip?branch=master
.. image:: https://readthedocs.org/projects/atip/badge/?version=latest
:target: https://atip.readthedocs.io/en/latest/?badge=latest
.. image:: https://badge.fury.io/py/atip.svg
:target: https://badge.fury.io/py/atip

==============================================
ATIP - Accelerator Toolbox Interface for Pytac
==============================================

ATIP is an addition to `Pytac <https://github.com/dls-controls/pytac>`_,
a framework for controlling particle accelerators.
ATIP adds a simulator to Pytac, which can be used and addressed in the same way
as a real accelerator.
a framework for controlling particle accelerators. ATIP adds a simulator to
Pytac, which can be used and addressed in the same way as a real accelerator.

ATIP enables the easy offline testing of high level accelerator
controls applications, by either of two methods:

* By replacing the real accelerator at the point where it is addressed in the
* By replacing the real accelerator at the point where it is addressed by the
software, in the Pytac lattice object;

* In a standalone application as a "virtual accelerator",
publishing the same control system interface as the live machine. At
Diamond Light Source this has been implemented with EPICS, and run on a
different port to the operational control system. So the only change required
to test software is to configure this EPICS port.
* In a standalone application as a "virtual accelerator", publishing the same
control system interface as the live machine. At Diamond Light Source this
has been implemented with EPICS, and run on a different port to the
operational control system. So the only change required to test software is
to configure this EPICS port.

The python implementation of
`Accelerator Toolbox <https://github.com/atcollab/at>`_ (pyAT) is used
for the simulation.
`Accelerator Toolbox <https://github.com/atcollab/at>`_ (pyAT) is used for the
simulation.

For further information on any of ATIP's functions or classes please read the
documentation `here <https://atip.readthedocs.io/en/latest/>`_.
Expand All @@ -41,48 +42,45 @@ See the ``INSTALL.rst`` document.
General Use:
------------

ATIP produces an "integrated lattice", which is a Pytac lattice object
with a simulation data source added.
The simulated data sources are added using the ``load()`` function
found in ``load_sim.py``.
ATIP produces an "integrated lattice", which is a Pytac lattice object with a
simulation data source added. The simulated data sources are added using the
``load()`` function found in ``load_sim.py``.

This adds ``pytac.SIM`` data sources on to the lattice and
each of the elements.
This adds ``pytac.SIM`` data sources on to the lattice and each of the
elements.

The integrated lattice acts like a normal Pytac lattice; the simulator can be
referenced
like the live machine but with the data source specified as ``pytac.SIM``
instead of ``pytac.LIVE``.
referenced like the live machine but with the data source specified as
``pytac.SIM`` instead of ``pytac.LIVE``.

For example, a get request to a BPM would be
``<bpm-element>.get_value('x', data_source=pytac.SIM)``.

The simulated data sources behave exactly like the live machine,
except for a few cases. For example, the simulator has a number of lattice
fields that the live accelerator doesn't have; and the live machine has a few
element fields that the simulator doesn't.
The simulated data sources behave exactly like the live machine, except for a
few cases. For example, the simulator has a number of lattice fields that the
live accelerator doesn't have; and the live machine has a few element fields
that the simulator doesn't.

Virtual Accelerator:
--------------------

Instructions for using ATIP as a virtual accelerator are found in
Instructions for using ATIP as a virtual accelerator can be found in
``virtac/README.rst``.

Implementation:
---------------

The accelerator data for the simulator is held in one
``ATSimulator`` object, which is referenced by the data sources of the lattice
and each element.
Each Pytac element has an equivalent pyAT element, held in a
``ATElementDataSource``;
when a get request is made, the
appropriate data from that AT element is returned.
All the accelerator data for the simulator is held in an ``ATSimulator``
object, which is referenced by the data sources of the lattice and each
element.Each Pytac element has an equivalent pyAT element, held in a
``ATElementDataSource``; when a get request is made, the appropriate data from
that AT element is returned.

The ``ATSimulator`` object has a queue of pending changes. When a set request
is received by an element, the element puts the changes onto the queue of the
``ATSimulator``. Inside the ``ATSimulator`` a Cothread thread
checks the length of the queue. When it sees changes on the queue, the thread
``ATSimulator``. Inside the ``ATSimulator`` a
`Cothread <https://github.com/dls-controls/cothread>`_ thread checks the
length of the queue. When it sees changes on the queue, the thread
recalculates the physics data of the lattice to ensure that it is up to date.
This means that the emittance and linear optics data held by ``ATSimulator``
is updated after every batch of changes, and that without excessive calculation
Expand Down Expand Up @@ -122,61 +120,68 @@ ATSimulator:
element from the central AT ring, N.B. An 'index' of 1 returns ring[0].
* ``get_at_lattice()`` - return a shallow copy of the entire centralised AT
lattice object.
* ``get_chrom(field)`` - return the specified plane of the lattice's
* ``get_s()`` - return the 's position' of every element in the lattice.
* ``get_total_bend_angle()`` - return the total bending angle of all the
dipoles in the lattice.
* ``get_total_absolute_bend_angle()`` - return the total absolute bending
angle of all the dipoles in the lattice.
* ``get_energy()`` - return the energy of the lattice.
* ``get_tune(field)`` - return the specified plane of the lattice's
'tune'; 'x' or 'y'.
* ``get_chromaticity(field)`` - return the specified plane of the lattice's
'chromaticity'; 'x' or 'y'.
* ``get_emit(field)`` - return the specified plane of the lattice's
'emittance'; 'x' or 'y'.
* ``get_orbit(field)`` - return the specified plane of the lattice's
'closed orbit'; 'x', 'phase_x', 'y', or 'phase_y'.
* ``get_tune(field)`` - return the specified plane of the lattice's
'tune'; 'x' or 'y'.
* ``get_disp()`` - return the 'dispersion' at every element in the lattice.
* ``get_s()`` - return the 's position' of every element in the lattice.
* ``get_energy()`` - return the energy of the lattice.
* ``get_dispersion()`` - return the 'dispersion' vector for every element
in the lattice.
* ``get_alpha()`` - return the 'alpha' vector at every element in the
lattice.
* ``get_beta()`` - return the 'beta' vector at every element in the
lattice.
* ``get_mu()`` - return 'mu' at every element in the lattice.
* ``get_m44()`` - return the 4x4 transfer matrix for every element in the
lattice.
* ``get_mu()`` - return 'mu' at every element in the lattice.
* ``get_emittance(field)`` - return the specified plane of the lattice's
'emittance'; 'x' or 'y'.
* ``get_radiation_integrals()`` - return the 5 Synchrotron Integrals for
the lattice.
* ``get_momentum_compaction()`` - return the momentum compaction factor
for the lattice.
* ``get_energy_spread()`` - return the energy spread for the lattice.
* ``get_mcf()`` - return the momentum compaction factor for the lattice.
* ``get_energy_loss()`` - return the energy loss per turn of the lattice.
* ``get_damping_times()`` - return the damping times for the lattice's
three normal modes.
* ``get_damping_partition_numbers()`` - return the damping partition
numbers for the lattice's three normal modes.
* ``get_total_bend_angle()`` - return the total bending angle of all the
dipoles in the lattice.
* ``get_total_absolute_bend_angle()`` - return the total absolute bending
angle of all the dipoles in the lattice.
* ``get_damping_times()`` - return the damping times for the lattice's
three normal modes.
* ``get_linear_dispersion_action()`` - return the Linear Dispersion Action
("curly H") for the lattice.
* ``get_horizontal_emittance()`` - return the horizontal ('x') emittance
for the lattice calculated from the radiation integrals.


Specific Notes:
---------------

In order for ATIP to function correctly, the AT and Pytac lattices used must
be directly equivalent, i.e. they must have the same length and elements in the
In order for ATIP to function correctly, the AT and Pytac lattices used must be
directly equivalent, i.e. they must have the same length and elements in the
same positions.

If local (not pip) installations are used, ATIP, AT, and Pytac must all be
located in the same source directory in order for ATIP to function correctly.

The methods on ATIP's data sources that take ``handle`` and ``throw``
arguments do so only to conform with the Pytac ``DataSource`` base class from
which they inherit. Inside ATIP they are not used and can be ignored.
The methods on ATIP's data sources that take ``handle`` and ``throw`` arguments
do so only to conform with the Pytac ``DataSource`` base class from which they
inherit. Inside ATIP they are not used and can be ignored.

To interpret which data is to be returned or set,
both ``ATElementDataSource`` and ``ATLatticeDataSource`` use a dictionary of
functions corresponding to fields. In the case where a cell needs to be passed
to the data handling
To interpret which data is to be returned or set, both ``ATElementDataSource``
and ``ATLatticeDataSource`` use a dictionary of functions corresponding to
fields. In the case where a cell needs to be passed to the data handling
functions, for further specification, functools' ``partial()`` is used.

The physics data is received from AT all together; to make it easier to manage,
it is split by ATIP and accessed by a number of methods of the
``ATSimulator`` object. This aims to be more convenient for the user
but does result in the ATSimulator object having a large number of methods.
it is split by ATIP and accessed by a number of methods of the ``ATSimulator``
object. This aims to be more convenient for the user but does result in the
ATSimulator object having a large number of methods.

A number of functions that perform tasks that are frequent or long-winded are
included in ``utils.py`` to make life easier for the user.
8 changes: 2 additions & 6 deletions atip/load_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@


# List of all the element fields that can be currently simulated.
SIMULATED_FIELDS = ['a1', 'b0', 'b1', 'b2', 'x', 'y', 'f', 'x_kick', 'y_kick']
SIMULATED_FIELDS = {'a1', 'b0', 'b1', 'b2', 'x', 'y', 'f', 'x_kick', 'y_kick'}


def load_from_filepath(pytac_lattice, at_lattice_filepath, callback=None):
Expand Down Expand Up @@ -56,11 +56,7 @@ def load(pytac_lattice, at_lattice, callback=None):
# Load the sim onto each element.
for e in pytac_lattice:
# Determine which fields each simulated element should have.
sim_fields = []
live_fields = list(e.get_fields()[pytac.LIVE])
for x in range(len(live_fields)):
if live_fields[x] in SIMULATED_FIELDS:
sim_fields.append(live_fields[x])
sim_fields = list(set(e.get_fields()[pytac.LIVE]) & SIMULATED_FIELDS)
# Set the simulator data source on each element.
e.set_data_source(ATElementDataSource(at_lattice[e.index - 1], e.index,
atsim, sim_fields), pytac.SIM)
Expand Down

0 comments on commit 82ccc20

Please sign in to comment.