Skip to content

Commit f75a49c

Browse files
authored
Merge pull request #18 from pylhc/doros_lhc
Reader/writer for DOROS BPM data
2 parents c5aca3c + f571a3c commit f75a49c

File tree

15 files changed

+366
-51
lines changed

15 files changed

+366
-51
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ instance/
7171

7272
# Sphinx documentation
7373
docs/_build/
74+
doc/_build/
7475
doc_build/
7576

7677
# PyBuilder

doc/conf.py

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,21 @@
1111
#
1212
# All configuration values have a default; values that are commented out
1313
# serve to show the default.
14+
15+
# If extensions (or modules to document with autodoc) are in another directory,
16+
# add these directories to sys.path here. If the directory is relative to the
17+
# documentation root, use os.path.abspath to make it absolute, like shown here.
18+
#
1419
import pathlib
1520
import sys
1621

1722
# ignore numpy warnings, see:
1823
# https://stackoverflow.com/questions/40845304/runtimewarning-numpy-dtype-size-changed-may-indicate-binary-incompatibility
1924
import warnings
2025

21-
# If extensions (or modules to document with autodoc) are in another directory,
22-
# add these directories to sys.path here. If the directory is relative to the
23-
# documentation root, use os.path.abspath to make it absolute, like shown here.
26+
warnings.filterwarnings("ignore", message="numpy.dtype size changed")
27+
warnings.filterwarnings("ignore", message="numpy.ufunc size changed")
28+
2429

2530
TOPLEVEL_DIR = pathlib.Path(__file__).parent.parent.absolute()
2631
ABOUT_FILE = TOPLEVEL_DIR / "turn_by_turn" / "__init__.py"
@@ -63,6 +68,8 @@ def about_package(init_posixpath: pathlib.Path) -> dict:
6368
"sphinx.ext.githubpages",
6469
"sphinx.ext.napoleon",
6570
]
71+
autosectionlabel_prefix_document = True
72+
autosectionlabel_maxdepth = 2
6673

6774
# Add any paths that contain templates here, relative to this directory.
6875
# templates_path = ['_templates']
@@ -78,7 +85,7 @@ def about_package(init_posixpath: pathlib.Path) -> dict:
7885

7986
# General information about the project.
8087
project = ABOUT_TBT["__title__"]
81-
copyright_ = "2018-2021, pyLHC/OMC-TEAM"
88+
copyright_ = "2018-2024, pyLHC/OMC-TEAM"
8289
author = ABOUT_TBT["__author__"]
8390

8491
# Override link in 'Edit on Github'
@@ -100,7 +107,7 @@ def about_package(init_posixpath: pathlib.Path) -> dict:
100107
#
101108
# This is also used if you do content translation via gettext catalogs.
102109
# Usually you set "language" from the command line for these cases.
103-
language = None
110+
language = "en"
104111

105112
# List of patterns, relative to source directory, that match files and
106113
# directories to ignore when looking for source files.
@@ -120,13 +127,6 @@ def about_package(init_posixpath: pathlib.Path) -> dict:
120127
#
121128
html_theme = "sphinx_rtd_theme"
122129

123-
html_theme_options = {
124-
"collapse_navigation": False,
125-
"display_version": True,
126-
"logo_only": True,
127-
"navigation_depth": 2,
128-
}
129-
130130
html_logo = "_static/img/omc_logo.svg"
131131
html_static_path = ["_static"]
132132
html_context = {
@@ -147,13 +147,28 @@ def about_package(init_posixpath: pathlib.Path) -> dict:
147147
# further. For a list of options available for each theme, see the
148148
# documentation.
149149
#
150-
# html_theme_options = {}
150+
html_theme_options = {
151+
'collapse_navigation': False,
152+
'display_version': True,
153+
'logo_only': True,
154+
'navigation_depth': 1,
155+
}
151156

152157
# Add any paths that contain custom static files (such as style sheets) here,
153158
# relative to this directory. They are copied after the builtin static files,
154159
# so a file named "default.css" will overwrite the builtin "default.css".
155160
# html_static_path = ['_static']
156161

162+
# A dictionary of values to pass into the template engine’s context for all
163+
# pages. Single values can also be put in this dictionary using the
164+
# -A command-line option of sphinx-build.
165+
html_context = {
166+
'display_github': True,
167+
# the following are only needed if :github_url: is not set
168+
'github_user': author,
169+
'github_repo': project,
170+
'github_version': 'master/doc/',
171+
}
157172
# Custom sidebar templates, must be a dictionary that maps document names
158173
# to template names.
159174
#

doc/modules/index.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
.. automodule:: turn_by_turn.constants
22
:members:
3+
:noindex:
34

45

56
.. automodule:: turn_by_turn.io
67
:members:
8+
:noindex:
79

810

911
.. automodule:: turn_by_turn.structures
1012
:members:
13+
:noindex:
1114

1215

1316
.. automodule:: turn_by_turn.utils
1417
:members:
18+
:noindex:
1519

doc/readers/index.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
1+
.. automodule:: turn_by_turn.doros
2+
:members:
3+
:noindex:
4+
5+
16
.. automodule:: turn_by_turn.esrf
27
:members:
8+
:noindex:
39

410

511
.. automodule:: turn_by_turn.iota
612
:members:
13+
:noindex:
714

815

916
.. automodule:: turn_by_turn.lhc
1017
:members:
18+
:noindex:
19+
20+
21+
.. automodule:: turn_by_turn.sps
22+
:members:
23+
:noindex:
1124

1225

1326
.. automodule:: turn_by_turn.ptc
1427
:members:
28+
:noindex:
1529

1630

1731
.. automodule:: turn_by_turn.trackone
1832
:members:
19-
33+
:noindex:

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ exclude = [
1616
packages = ["turn_by_turn"]
1717

1818
[project]
19-
name = "tfs-turn_by_turn"
19+
name = "turn_by_turn"
2020
readme = "README.md"
2121
description = "Read and write turn-by-turn measurement files from different particle accelerator formats."
2222
authors = [

tests/inputs/test_doros.h5

2.31 MB
Binary file not shown.

tests/test_doros.py

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
2+
from datetime import datetime
3+
from pathlib import Path
4+
5+
import numpy as np
6+
import pandas as pd
7+
import pytest
8+
import h5py
9+
10+
from turn_by_turn.constants import PRINT_PRECISION
11+
from turn_by_turn.errors import DataTypeError
12+
from turn_by_turn.structures import TbtData, TransverseData
13+
from tests.test_lhc_and_general import create_data, compare_tbt
14+
15+
from turn_by_turn.doros import N_ORBIT_SAMPLES, read_tbt, write_tbt, DEFAULT_BUNCH_ID, POSITIONS
16+
17+
INPUTS_DIR = Path(__file__).parent / "inputs"
18+
19+
20+
def test_read_write_real_data(tmp_path):
21+
tbt = read_tbt(INPUTS_DIR / "test_doros.h5", bunch_id=10)
22+
23+
assert tbt.nbunches == 1
24+
assert len(tbt.matrices) == 1
25+
assert tbt.nturns == 50000
26+
assert tbt.matrices[0].X.shape == (3, tbt.nturns)
27+
assert tbt.matrices[0].Y.shape == (3, tbt.nturns)
28+
assert len(set(tbt.matrices[0].X.index)) == 3
29+
assert np.all(tbt.matrices[0].X.index == tbt.matrices[0].Y.index)
30+
31+
file_path = tmp_path / "test_file.h5"
32+
write_tbt(tbt, file_path)
33+
new = read_tbt(file_path, bunch_id=10)
34+
compare_tbt(tbt, new, no_binary=False)
35+
36+
37+
def test_write_read(tmp_path):
38+
tbt = _tbt_data()
39+
file_path = tmp_path / "test_file.h5"
40+
write_tbt(tbt, file_path)
41+
new = read_tbt(file_path)
42+
compare_tbt(tbt, new, no_binary=False)
43+
44+
45+
def test_read_raises_different_bpm_lengths(tmp_path):
46+
tbt = _tbt_data()
47+
file_path = tmp_path / "test_file.h5"
48+
write_tbt(tbt, file_path)
49+
50+
bpm = tbt.matrices[0].X.index[0]
51+
52+
# modify the BPM lengths in the file
53+
with h5py.File(file_path, "r+") as h5f:
54+
delta = 10
55+
del h5f[bpm][N_ORBIT_SAMPLES]
56+
h5f[bpm][N_ORBIT_SAMPLES] = [tbt.matrices[0].X.shape[1] - delta]
57+
for key in POSITIONS.values():
58+
data = h5f[bpm][key][:-delta]
59+
del h5f[bpm][key]
60+
h5f[bpm][key] = data
61+
62+
with pytest.raises(ValueError) as e:
63+
read_tbt(file_path)
64+
assert "Not all BPMs have the same number of turns!" in str(e)
65+
66+
67+
def test_read_raises_on_different_bpm_lengths_in_data(tmp_path):
68+
tbt = _tbt_data()
69+
file_path = tmp_path / "test_file.h5"
70+
write_tbt(tbt, file_path)
71+
72+
bpms = [tbt.matrices[0].X.index[i] for i in (0, 2)]
73+
74+
# modify the BPM lengths in the file
75+
with h5py.File(file_path, "r+") as h5f:
76+
for bpm in bpms:
77+
del h5f[bpm][N_ORBIT_SAMPLES]
78+
h5f[bpm][N_ORBIT_SAMPLES] = [tbt.matrices[0].X.shape[1] + 10]
79+
80+
with pytest.raises(ValueError) as e:
81+
read_tbt(file_path)
82+
assert "Found BPMs with different data lengths" in str(e)
83+
assert all(bpm in str(e) for bpm in bpms)
84+
85+
86+
def _tbt_data() -> TbtData:
87+
"""TbT data for testing. Adding random noise, so that the data is different per BPM."""
88+
nturns = 2000
89+
bpms = ["TBPM1", "TBPM2", "TBPM3", "TBPM4"]
90+
91+
return TbtData(
92+
matrices=[
93+
TransverseData(
94+
X=pd.DataFrame(
95+
index=bpms,
96+
data=create_data(
97+
np.linspace(-np.pi, np.pi, nturns, endpoint=False),
98+
nbpm=len(bpms), function=np.sin, noise=0.02
99+
),
100+
dtype=float,
101+
),
102+
Y=pd.DataFrame(
103+
index=bpms,
104+
data=create_data(
105+
np.linspace(-np.pi, np.pi, nturns, endpoint=False),
106+
nbpm=len(bpms), function=np.cos, noise=0.015
107+
),
108+
dtype=float,
109+
),
110+
)
111+
],
112+
date=datetime.now(),
113+
bunch_ids=[DEFAULT_BUNCH_ID],
114+
nturns=nturns,
115+
)

tests/test_lhc_and_general.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@ def compare_tbt(origin: TbtData, new: TbtData, no_binary: bool, max_deviation =
7272
assert np.all(origin_mat == new_mat)
7373

7474

75-
def create_data(phases, nbpm, function) -> np.ndarray:
76-
return np.ones((nbpm, len(phases))) * function(phases)
75+
def create_data(phases, nbpm, function, noise: float = 0) -> np.ndarray:
76+
return np.ones((nbpm, len(phases))) * function(phases) + noise * np.random.randn(nbpm, len(phases))
7777

7878

7979
@pytest.fixture()

turn_by_turn/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
__title__ = "turn_by_turn"
66
__description__ = "Read and write turn-by-turn measurement files from different particle accelerator formats."
77
__url__ = "https://github.com/pylhc/turn_by_turn"
8-
__version__ = "0.6.0"
8+
__version__ = "0.7.0"
99
__author__ = "pylhc"
1010
__author_email__ = "pylhc@github.com"
1111
__license__ = "MIT"

0 commit comments

Comments
 (0)