-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #1 from mihofer/main
add XY grid and set coordinates functions, to_pandas, unit tests, readme
- Loading branch information
Showing
6 changed files
with
310 additions
and
16 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,48 @@ | ||
# xdyna | ||
|
||
Tools to study beam dynamics in xtrack simulations, like dynamic aperture calculations, PYTHIA integration, dynamic indicators, ... | ||
|
||
## Dynamic aperture studies | ||
|
||
The `xdyna` package provides the `DA` class which serves as a simple front-end for setting up and running dynamic aperture studies. | ||
|
||
To start, a `xtrack.line` object is required. | ||
The following code then sets up the study and launches the tracking | ||
|
||
```python | ||
|
||
import xdyna as xd | ||
|
||
da = xd.DA( | ||
name='name_of_your_study', # used to generate a directory where files are stored | ||
normalised_emittance=[1,1], # provide normalized emittance for particle initialization in [m] | ||
max_turns=1e5, # number of turns to track | ||
use_files=False | ||
# in case DA studies should run on HTC condor, files are used to collect the information | ||
# if the tracking is performed locally, no files are needed | ||
) | ||
|
||
# initialize a grid of particles using 5 angles in x-y space, in a range from 0 to 20 sigmas in steps of 5 sigma. | ||
da.generate_initial_radial(angles=5, r_min=0, r_max=20, r_step=5, delta=0.) | ||
|
||
da.line = line # associate prev. created line, holding the lattice and context, with DA object | ||
|
||
da.track_job() # start the tracking | ||
|
||
da.survival_data # returns a dataframe with the number of survived turns for the initial position of each particle | ||
|
||
``` | ||
|
||
To use on a platform like HTCondor, perform the same setup as before but using `use_files=True`. | ||
Each HTCondor job then only requires the following lines | ||
|
||
```python | ||
import xdyna as xd | ||
# This will load the existing DA based on the meta file with the same name found in the working directory. | ||
# If the script is ran somewhere else, the path to the metafile can be passed with 'path=...'. | ||
DA = xd.DA(name=study, use_files=True) | ||
|
||
# Do the tracking, here for 100 particles. | ||
# The code will automatically look for particles that are not-submitted yet and use these. | ||
DA.track_job(npart=100) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
import pytest | ||
import pandas as pd | ||
from pandas.testing import assert_frame_equal | ||
import xdyna as xd | ||
|
||
|
||
SURV_COLUMNS = ['ang_xy', 'r_xy', 'nturns', 'x_norm_in', 'y_norm_in', 'px_norm_in', | ||
'py_norm_in', 'zeta_in', 'delta_in', 'x_out', 'y_out', 'px_out', | ||
'py_out', 'zeta_out', 'delta_out', 's_out', 'state', 'submitted', | ||
'finished'] | ||
|
||
|
||
|
||
def test_mismatch_user_coordinates(): | ||
|
||
DA = xd.DA(name='user_coordinates', | ||
normalised_emittance=[1,1], | ||
max_turns=2, | ||
use_files=False) | ||
with pytest.raises(AssertionError): | ||
DA.set_coordinates(x=[1], y = [1,2]) | ||
|
||
|
||
def test_user_coordinates(): | ||
|
||
DA = xd.DA(name='user_coordinates', | ||
normalised_emittance=[1,1], | ||
max_turns=2, | ||
use_files=False) | ||
DA.set_coordinates(x=[1,2], y = [3,4], px=[5,6]) | ||
|
||
assert_frame_equal(DA.survival_data[['x', 'y', 'px', 'py', 'delta']], | ||
pd.DataFrame(data={ | ||
'x':[1,2], | ||
'y':[3,4], | ||
'px':[5,6], | ||
'py':[0,0], | ||
'delta':[0,0] | ||
}) ) | ||
|
||
|
||
def test_xy_grid(): | ||
|
||
DA = xd.DA(name='user_coordinates', | ||
normalised_emittance=[1,1], | ||
max_turns=2, | ||
use_files=False) | ||
DA.generate_initial_grid( | ||
x_min=0, x_max=2, x_step=2, | ||
y_min=0, y_max=2, y_step=2, | ||
) | ||
assert_frame_equal(DA.survival_data[['x', 'y']], | ||
pd.DataFrame(data={'x':[0.,2.,0.,2.], 'y':[0.,0.,2.,2.]}) ) | ||
|
||
|
||
def test_radial_grid(): | ||
|
||
DA = xd.DA(name='user_coordinates', | ||
normalised_emittance=[1,1], | ||
max_turns=2, | ||
use_files=False) | ||
DA.generate_initial_radial( | ||
r_min=0, r_max=2, r_step=2, | ||
ang_min=0, ang_max=90, angles=2, | ||
) | ||
assert_frame_equal(DA.survival_data[['amplitude', 'angle']], | ||
pd.DataFrame(data={'amplitude':[0.,2.,0.,2.], 'angle':[0.,0.,90.,90.]}) ) | ||
|
||
|
||
def test_pandas(): | ||
|
||
DA = xd.DA(name='user_coordinates', | ||
normalised_emittance=[1,1], | ||
max_turns=2, | ||
use_files=False) | ||
DA.generate_initial_radial( | ||
r_min=0, r_max=2, r_step=2, | ||
ang_min=0, ang_max=90, angles=2, | ||
) | ||
|
||
assert_frame_equal(DA.survival_data, | ||
DA.to_pandas()) | ||
assert all(elem in DA.to_pandas(full=True).columns for elem in SURV_COLUMNS) |
Oops, something went wrong.