diff --git a/docs/source/_static/_logo/pyaml-logo.svg b/docs/source/_static/_logo/pyaml-logo.svg
index bf5ac623a..783e705af 100644
--- a/docs/source/_static/_logo/pyaml-logo.svg
+++ b/docs/source/_static/_logo/pyaml-logo.svg
@@ -33,8 +33,8 @@
inkscape:cy="306.36035"
inkscape:window-width="1746"
inkscape:window-height="1229"
- inkscape:window-x="2377"
- inkscape:window-y="152"
+ inkscape:window-x="798"
+ inkscape:window-y="124"
inkscape:window-maximized="0"
inkscape:current-layer="layer1"
showguides="false" />pyAMLpyAML logo str:
# Main code
sr = Accelerator.from_dict(acc_config)
-tm1 = sr.live.get_betatron_tune_monitor("MY_TUNE_MONITOR")
+tm1 = sr.live.diagnostic.get("MY_TUNE_MONITOR")
print(tm1.tune.get())
print(tm1.frequency.get())
diff --git a/examples/use_cases/01-tune_correction.ipynb b/examples/use_cases/01-tune_correction.ipynb
index dfba75bb0..4e20ff1f9 100644
--- a/examples/use_cases/01-tune_correction.ipynb
+++ b/examples/use_cases/01-tune_correction.ipynb
@@ -207,7 +207,7 @@
}
],
"source": [
- "tune_monitor = SR.get_betatron_tune_monitor(\"BETATRON_TUNE\")\n",
+ "tune_monitor = SR.diagnostic.get(\"BETATRON_TUNE\")\n",
"print(f\"Current tune: {tune_monitor.tune.get()}\")\n",
"tune_monitor # string representation"
]
@@ -282,83 +282,15 @@
"cell_type": "markdown",
"id": "04431246",
"metadata": {},
- "source": [
- "### Standard tune correction tool\n",
- "\n",
- "`SR.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.\n",
- "\n",
- "Before correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file."
- ]
+ "source": "### Standard tune correction tool\n\n`SR.tool.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.tool.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.\n\nBefore correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file."
},
{
"cell_type": "code",
- "execution_count": 8,
+ "execution_count": null,
"id": "5c57ef30",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "Tune(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', response_matrix=array([[ 0.17853128, 0.17890919, 0.17917984, 0.17843061, 0.17932054,\n",
- " 0.17884878, 0.1786898 , 0.17950221, 0.17836418, 0.1790288 ,\n",
- " 0.17907229, 0.17845344, 0.17936885, 0.1787317 , 0.17880339,\n",
- " 0.1793422 , 0.17843576, 0.17914062, 0.17895506, 0.17850485,\n",
- " 0.15843663, 0.1575313 , 0.15237977, 0.15250702, 0.17830408,\n",
- " 0.17955648, 0.1784584 , 0.17880469, 0.17936621, 0.17824945,\n",
- " 0.17941811, 0.17905372, 0.17841113, 0.17957284, 0.17835113,\n",
- " 0.17897118, 0.17923226, 0.17825399, 0.17950825, 0.17876573,\n",
- " 0.17866201, 0.17954684, 0.17827911, 0.17925585, 0.17897151,\n",
- " 0.17830041, 0.17956082, 0.17873061, 0.17871689, 0.17948152,\n",
- " 0.15577439, 0.15662709, 0.178933 , 0.17847488, 0.17937198,\n",
- " 0.17881763, 0.17874021, 0.17931638, 0.17843723, 0.17929549,\n",
- " 0.17880609, 0.17853484, 0.59082023, 0.59180433, 0.59274339,\n",
- " 0.59079241, 0.59387998, 0.59265135, 0.59209988, 0.59391444,\n",
- " 0.59072413, 0.59219559, 0.59234655, 0.59073497, 0.59391106,\n",
- " 0.59225191, 0.59250056, 0.59390362, 0.59075881, 0.59259427,\n",
- " 0.5919504 , 0.59077803, 0.52411485, 0.52163044, 0.50248335,\n",
- " 0.50266086, 0.59115919, 0.59419444, 0.59038465, 0.59128648,\n",
- " 0.59323464, 0.59032653, 0.59438116, 0.59313174, 0.59165988,\n",
- " 0.5944257 , 0.59018699, 0.59180163, 0.59270748, 0.59015999,\n",
- " 0.59451179, 0.5925782 , 0.59221837, 0.59452251, 0.59012406,\n",
- " 0.59236712, 0.59213945, 0.59013148, 0.59450445, 0.59204248,\n",
- " 0.59275305, 0.59448392, 0.51467256, 0.51681741, 0.59219055,\n",
- " 0.59076114, 0.59387372, 0.59213029, 0.59261978, 0.59385979,\n",
- " 0.59080955, 0.59274399, 0.59180476, 0.59083819],\n",
- " [-1.26055967, -1.26031469, -1.2598023 , -1.26083158, -1.25981216,\n",
- " -1.26160634, -1.26143231, -1.25920552, -1.26001143, -1.26105243,\n",
- " -1.26026455, -1.26115601, -1.26145837, -1.25972946, -1.26035568,\n",
- " -1.26035017, -1.25972691, -1.26145864, -1.2611518 , -1.26026992,\n",
- " -1.28718859, -1.28580227, -1.29551207, -1.29591315, -1.26023455,\n",
- " -1.26119118, -1.2611013 , -1.26019174, -1.26077014, -1.26007772,\n",
- " -1.25987122, -1.260857 , -1.2609502 , -1.26075456, -1.26134921,\n",
- " -1.25965397, -1.25996982, -1.26071455, -1.25976978, -1.26108183,\n",
- " -1.26034272, -1.26107775, -1.26118967, -1.25922595, -1.25959951,\n",
- " -1.26157551, -1.26072113, -1.26058879, -1.26193197, -1.25939288,\n",
- " -1.28878699, -1.28913722, -1.26030408, -1.26116608, -1.26092241,\n",
- " -1.25960761, -1.2599948 , -1.26128422, -1.26055622, -1.26012439,\n",
- " -1.26052166, -1.2609009 , -0.49429912, -0.49420118, -0.49402884,\n",
- " -0.49444032, -0.49392715, -0.49464442, -0.49464248, -0.49384803,\n",
- " -0.4940031 , -0.49450349, -0.49410766, -0.49446404, -0.49461625,\n",
- " -0.49392508, -0.49424032, -0.49423811, -0.49392437, -0.49461667,\n",
- " -0.4944622 , -0.49410966, -0.49580432, -0.4952599 , -0.49584758,\n",
- " -0.49606291, -0.49405329, -0.49450455, -0.4944593 , -0.49409569,\n",
- " -0.49438685, -0.49411004, -0.49400608, -0.49449611, -0.4942921 ,\n",
- " -0.49429813, -0.49459747, -0.49391976, -0.49407876, -0.49437648,\n",
- " -0.49398646, -0.49451098, -0.49413892, -0.49443276, -0.49457543,\n",
- " -0.49388618, -0.49382348, -0.49469773, -0.49426765, -0.49431067,\n",
- " -0.49473566, -0.49380506, -0.49553592, -0.49574219, -0.49407224,\n",
- " -0.4944902 , -0.4944531 , -0.49402325, -0.49396739, -0.49456722,\n",
- " -0.49428634, -0.49420954, -0.49415863, -0.49439461]]), _tm=BetatronTuneMonitor(tune_h='srdiag/beam-tune/main/Qh', tune_v='srdiag/beam-tune/main/Qv', name='BETATRON_TUNE'), _quads=[Quadrupole(peer='Simulator:design', name='QD2E-C04', model_name='QD2E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C05', model_name='QD2A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C05', model_name='QD2E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C06', model_name='QD2A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C06', model_name='QD2E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C07', model_name='QD2A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C07', model_name='QD2E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C08', model_name='QD2A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C08', model_name='QD2E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C09', model_name='QD2A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C09', model_name='QD2E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C10', model_name='QD2A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C10', model_name='QD2E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C11', model_name='QD2A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C11', model_name='QD2E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C12', model_name='QD2A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C12', model_name='QD2E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C13', model_name='QD2A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C13', model_name='QD2E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C14', model_name='QD2A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C14', model_name='QD2E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C15', model_name='QD2A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C15', model_name='QD2E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C16', model_name='QD2A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C16', model_name='QD2E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C17', model_name='QD2A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C17', model_name='QD2E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C18', model_name='QD2A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C18', model_name='QD2E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C19', model_name='QD2A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C19', model_name='QD2E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C20', model_name='QD2A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C20', model_name='QD2E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C21', model_name='QD2A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C21', model_name='QD2E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C22', model_name='QD2A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C22', model_name='QD2E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C23', model_name='QD2A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C23', model_name='QD2E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C24', model_name='QD2A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C24', model_name='QD2E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C25', model_name='QD2A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C25', model_name='QD2E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C26', model_name='QD2A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C26', model_name='QD2E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C27', model_name='QD2A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C27', model_name='QD2E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C28', model_name='QD2A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C28', model_name='QD2E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C29', model_name='QD2A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C29', model_name='QD2E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C30', model_name='QD2A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C30', model_name='QD2E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C31', model_name='QD2A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C31', model_name='QD2E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C32', model_name='QD2A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C32', model_name='QD2E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C01', model_name='QD2A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C01', model_name='QD2E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C02', model_name='QD2A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C02', model_name='QD2E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C03', model_name='QD2A-C03', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C04', model_name='QF1E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C05', model_name='QF1A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C05', model_name='QF1E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C06', model_name='QF1A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C06', model_name='QF1E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C07', model_name='QF1A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C07', model_name='QF1E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C08', model_name='QF1A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C08', model_name='QF1E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C09', model_name='QF1A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C09', model_name='QF1E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C10', model_name='QF1A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C10', model_name='QF1E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C11', model_name='QF1A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C11', model_name='QF1E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C12', model_name='QF1A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C12', model_name='QF1E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C13', model_name='QF1A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C13', model_name='QF1E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C14', model_name='QF1A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C14', model_name='QF1E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C15', model_name='QF1A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C15', model_name='QF1E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C16', model_name='QF1A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C16', model_name='QF1E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C17', model_name='QF1A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C17', model_name='QF1E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C18', model_name='QF1A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C18', model_name='QF1E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C19', model_name='QF1A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C19', model_name='QF1E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C20', model_name='QF1A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C20', model_name='QF1E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C21', model_name='QF1A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C21', model_name='QF1E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C22', model_name='QF1A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C22', model_name='QF1E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C23', model_name='QF1A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C23', model_name='QF1E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C24', model_name='QF1A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C24', model_name='QF1E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C25', model_name='QF1A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C25', model_name='QF1E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C26', model_name='QF1A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C26', model_name='QF1E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C27', model_name='QF1A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C27', model_name='QF1E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C28', model_name='QF1A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C28', model_name='QF1E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C29', model_name='QF1A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C29', model_name='QF1E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C30', model_name='QF1A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C30', model_name='QF1E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C31', model_name='QF1A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C31', model_name='QF1E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C32', model_name='QF1A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C32', model_name='QF1E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C01', model_name='QF1A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C01', model_name='QF1E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C02', model_name='QF1A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C02', model_name='QF1E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C03', model_name='QF1A-C03', magnet_model=LinearMagnetModel)], name='DEFAULT_TUNE_CORRECTION')"
- ]
- },
- "execution_count": 8,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SR.tune # string representation"
- ]
+ "outputs": [],
+ "source": "SR.tool.tune # string representation"
},
{
"cell_type": "markdown",
@@ -391,142 +323,25 @@
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": null,
"id": "c81cdb05",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Response matrix loaded.\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "TuneResponseMatrix(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', quad_delta=0.0001, n_step=1, sleep_between_step=0.0, n_avg_meas=1, sleep_between_meas=0.0, name='DEFAULT_TUNE_RESPONSE_MATRIX')"
- ]
- },
- "execution_count": 10,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "if SR.tune.response_matrix is None:\n",
- " SR.trm.measure(sleep_between_step=wait_time, callback=tune_callback)\n",
- " SR.trm.save(CONFIG_DIR / \"trm.json\")\n",
- "\n",
- "SR.tune.load(CONFIG_DIR / \"trm.json\")\n",
- "print(\"Response matrix loaded.\")\n",
- "SR.trm # string representation"
- ]
+ "outputs": [],
+ "source": "if SR.tool.tune.response_matrix is None:\n SR.tool.trm.measure(sleep_between_step=wait_time, callback=tune_callback)\n SR.tool.trm.save(CONFIG_DIR / \"trm.json\")\n\nSR.tool.tune.load(CONFIG_DIR / \"trm.json\")\nprint(\"Response matrix loaded.\")\nSR.tool.trm # string representation"
},
{
"cell_type": "markdown",
"id": "ef7d7ce4",
"metadata": {},
- "source": [
- "#### Correcting the tune\n",
- "\n",
- "`SR.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls the number of iterations and `wait_time` the settling time between each iteration."
- ]
+ "source": "#### Correcting the tune\n\n`SR.tool.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls the number of iterations and `wait_time` the settling time between each iteration."
},
{
"cell_type": "code",
- "execution_count": 11,
+ "execution_count": null,
"id": "6b8bcf91",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "Tune before correction: [0.16000001 0.33999986]\n",
- "\n",
- "Setting tune to [0.19, 0.28]\n",
- "Tune after correction: [0.19 0.28]\n",
- "\n",
- "Setting tune to [0.21, 0.3]\n",
- "Tune after correction: [0.21 0.3 ]\n"
- ]
- },
- {
- "data": {
- "text/plain": [
- "Tune(quad_array_name='QForTune', betatron_tune_name='BETATRON_TUNE', response_matrix=array([[ 0.17853128, 0.17890919, 0.17917984, 0.17843061, 0.17932054,\n",
- " 0.17884878, 0.1786898 , 0.17950221, 0.17836418, 0.1790288 ,\n",
- " 0.17907229, 0.17845344, 0.17936885, 0.1787317 , 0.17880339,\n",
- " 0.1793422 , 0.17843576, 0.17914062, 0.17895506, 0.17850485,\n",
- " 0.15843663, 0.1575313 , 0.15237977, 0.15250702, 0.17830408,\n",
- " 0.17955648, 0.1784584 , 0.17880469, 0.17936621, 0.17824945,\n",
- " 0.17941811, 0.17905372, 0.17841113, 0.17957284, 0.17835113,\n",
- " 0.17897118, 0.17923226, 0.17825399, 0.17950825, 0.17876573,\n",
- " 0.17866201, 0.17954684, 0.17827911, 0.17925585, 0.17897151,\n",
- " 0.17830041, 0.17956082, 0.17873061, 0.17871689, 0.17948152,\n",
- " 0.15577439, 0.15662709, 0.178933 , 0.17847488, 0.17937198,\n",
- " 0.17881763, 0.17874021, 0.17931638, 0.17843723, 0.17929549,\n",
- " 0.17880609, 0.17853484, 0.59082023, 0.59180433, 0.59274339,\n",
- " 0.59079241, 0.59387998, 0.59265135, 0.59209988, 0.59391444,\n",
- " 0.59072413, 0.59219559, 0.59234655, 0.59073497, 0.59391106,\n",
- " 0.59225191, 0.59250056, 0.59390362, 0.59075881, 0.59259427,\n",
- " 0.5919504 , 0.59077803, 0.52411485, 0.52163044, 0.50248335,\n",
- " 0.50266086, 0.59115919, 0.59419444, 0.59038465, 0.59128648,\n",
- " 0.59323464, 0.59032653, 0.59438116, 0.59313174, 0.59165988,\n",
- " 0.5944257 , 0.59018699, 0.59180163, 0.59270748, 0.59015999,\n",
- " 0.59451179, 0.5925782 , 0.59221837, 0.59452251, 0.59012406,\n",
- " 0.59236712, 0.59213945, 0.59013148, 0.59450445, 0.59204248,\n",
- " 0.59275305, 0.59448392, 0.51467256, 0.51681741, 0.59219055,\n",
- " 0.59076114, 0.59387372, 0.59213029, 0.59261978, 0.59385979,\n",
- " 0.59080955, 0.59274399, 0.59180476, 0.59083819],\n",
- " [-1.26055967, -1.26031469, -1.2598023 , -1.26083158, -1.25981216,\n",
- " -1.26160634, -1.26143231, -1.25920552, -1.26001143, -1.26105243,\n",
- " -1.26026455, -1.26115601, -1.26145837, -1.25972946, -1.26035568,\n",
- " -1.26035017, -1.25972691, -1.26145864, -1.2611518 , -1.26026992,\n",
- " -1.28718859, -1.28580227, -1.29551207, -1.29591315, -1.26023455,\n",
- " -1.26119118, -1.2611013 , -1.26019174, -1.26077014, -1.26007772,\n",
- " -1.25987122, -1.260857 , -1.2609502 , -1.26075456, -1.26134921,\n",
- " -1.25965397, -1.25996982, -1.26071455, -1.25976978, -1.26108183,\n",
- " -1.26034272, -1.26107775, -1.26118967, -1.25922595, -1.25959951,\n",
- " -1.26157551, -1.26072113, -1.26058879, -1.26193197, -1.25939288,\n",
- " -1.28878699, -1.28913722, -1.26030408, -1.26116608, -1.26092241,\n",
- " -1.25960761, -1.2599948 , -1.26128422, -1.26055622, -1.26012439,\n",
- " -1.26052166, -1.2609009 , -0.49429912, -0.49420118, -0.49402884,\n",
- " -0.49444032, -0.49392715, -0.49464442, -0.49464248, -0.49384803,\n",
- " -0.4940031 , -0.49450349, -0.49410766, -0.49446404, -0.49461625,\n",
- " -0.49392508, -0.49424032, -0.49423811, -0.49392437, -0.49461667,\n",
- " -0.4944622 , -0.49410966, -0.49580432, -0.4952599 , -0.49584758,\n",
- " -0.49606291, -0.49405329, -0.49450455, -0.4944593 , -0.49409569,\n",
- " -0.49438685, -0.49411004, -0.49400608, -0.49449611, -0.4942921 ,\n",
- " -0.49429813, -0.49459747, -0.49391976, -0.49407876, -0.49437648,\n",
- " -0.49398646, -0.49451098, -0.49413892, -0.49443276, -0.49457543,\n",
- " -0.49388618, -0.49382348, -0.49469773, -0.49426765, -0.49431067,\n",
- " -0.49473566, -0.49380506, -0.49553592, -0.49574219, -0.49407224,\n",
- " -0.4944902 , -0.4944531 , -0.49402325, -0.49396739, -0.49456722,\n",
- " -0.49428634, -0.49420954, -0.49415863, -0.49439461]]), _tm=BetatronTuneMonitor(tune_h='srdiag/beam-tune/main/Qh', tune_v='srdiag/beam-tune/main/Qv', name='BETATRON_TUNE'), _quads=[Quadrupole(peer='Simulator:design', name='QD2E-C04', model_name='QD2E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C05', model_name='QD2A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C05', model_name='QD2E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C06', model_name='QD2A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C06', model_name='QD2E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C07', model_name='QD2A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C07', model_name='QD2E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C08', model_name='QD2A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C08', model_name='QD2E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C09', model_name='QD2A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C09', model_name='QD2E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C10', model_name='QD2A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C10', model_name='QD2E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C11', model_name='QD2A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C11', model_name='QD2E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C12', model_name='QD2A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C12', model_name='QD2E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C13', model_name='QD2A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C13', model_name='QD2E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C14', model_name='QD2A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C14', model_name='QD2E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C15', model_name='QD2A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C15', model_name='QD2E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C16', model_name='QD2A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C16', model_name='QD2E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C17', model_name='QD2A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C17', model_name='QD2E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C18', model_name='QD2A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C18', model_name='QD2E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C19', model_name='QD2A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C19', model_name='QD2E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C20', model_name='QD2A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C20', model_name='QD2E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C21', model_name='QD2A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C21', model_name='QD2E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C22', model_name='QD2A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C22', model_name='QD2E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C23', model_name='QD2A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C23', model_name='QD2E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C24', model_name='QD2A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C24', model_name='QD2E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C25', model_name='QD2A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C25', model_name='QD2E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C26', model_name='QD2A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C26', model_name='QD2E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C27', model_name='QD2A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C27', model_name='QD2E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C28', model_name='QD2A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C28', model_name='QD2E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C29', model_name='QD2A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C29', model_name='QD2E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C30', model_name='QD2A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C30', model_name='QD2E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C31', model_name='QD2A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C31', model_name='QD2E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C32', model_name='QD2A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C32', model_name='QD2E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C01', model_name='QD2A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C01', model_name='QD2E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C02', model_name='QD2A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2E-C02', model_name='QD2E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QD2A-C03', model_name='QD2A-C03', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C04', model_name='QF1E-C04', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C05', model_name='QF1A-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C05', model_name='QF1E-C05', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C06', model_name='QF1A-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C06', model_name='QF1E-C06', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C07', model_name='QF1A-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C07', model_name='QF1E-C07', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C08', model_name='QF1A-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C08', model_name='QF1E-C08', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C09', model_name='QF1A-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C09', model_name='QF1E-C09', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C10', model_name='QF1A-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C10', model_name='QF1E-C10', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C11', model_name='QF1A-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C11', model_name='QF1E-C11', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C12', model_name='QF1A-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C12', model_name='QF1E-C12', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C13', model_name='QF1A-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C13', model_name='QF1E-C13', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C14', model_name='QF1A-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C14', model_name='QF1E-C14', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C15', model_name='QF1A-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C15', model_name='QF1E-C15', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C16', model_name='QF1A-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C16', model_name='QF1E-C16', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C17', model_name='QF1A-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C17', model_name='QF1E-C17', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C18', model_name='QF1A-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C18', model_name='QF1E-C18', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C19', model_name='QF1A-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C19', model_name='QF1E-C19', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C20', model_name='QF1A-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C20', model_name='QF1E-C20', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C21', model_name='QF1A-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C21', model_name='QF1E-C21', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C22', model_name='QF1A-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C22', model_name='QF1E-C22', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C23', model_name='QF1A-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C23', model_name='QF1E-C23', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C24', model_name='QF1A-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C24', model_name='QF1E-C24', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C25', model_name='QF1A-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C25', model_name='QF1E-C25', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C26', model_name='QF1A-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C26', model_name='QF1E-C26', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C27', model_name='QF1A-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C27', model_name='QF1E-C27', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C28', model_name='QF1A-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C28', model_name='QF1E-C28', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C29', model_name='QF1A-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C29', model_name='QF1E-C29', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C30', model_name='QF1A-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C30', model_name='QF1E-C30', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C31', model_name='QF1A-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C31', model_name='QF1E-C31', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C32', model_name='QF1A-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C32', model_name='QF1E-C32', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C01', model_name='QF1A-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C01', model_name='QF1E-C01', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C02', model_name='QF1A-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1E-C02', model_name='QF1E-C02', magnet_model=LinearMagnetModel), Quadrupole(peer='Simulator:design', name='QF1A-C03', model_name='QF1A-C03', magnet_model=LinearMagnetModel)], name='DEFAULT_TUNE_CORRECTION')"
- ]
- },
- "execution_count": 11,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "print(f\"Tune before correction: {SR.tune.readback()}\")\n",
- "\n",
- "qx, qy = 0.19, 0.28\n",
- "print(f\"\\nSetting tune to [{qx}, {qy}]\")\n",
- "SR.tune.set([qx, qy], iter=10, wait_time=wait_time)\n",
- "print(f\"Tune after correction: {SR.tune.readback()}\")\n",
- "\n",
- "qx, qy = 0.21, 0.30\n",
- "print(f\"\\nSetting tune to [{qx}, {qy}]\")\n",
- "SR.tune.set([qx, qy], iter=10, wait_time=wait_time)\n",
- "print(f\"Tune after correction: {SR.tune.readback()}\")\n",
- "\n",
- "SR.tune # string representation"
- ]
+ "outputs": [],
+ "source": "print(f\"Tune before correction: {SR.tool.tune.readback()}\")\n\nqx, qy = 0.19, 0.28\nprint(f\"\\nSetting tune to [{qx}, {qy}]\")\nSR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)\nprint(f\"Tune after correction: {SR.tool.tune.readback()}\")\n\nqx, qy = 0.21, 0.30\nprint(f\"\\nSetting tune to [{qx}, {qy}]\")\nSR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)\nprint(f\"Tune after correction: {SR.tool.tune.readback()}\")\n\nSR.tool.tune # string representation"
},
{
"cell_type": "code",
diff --git a/examples/use_cases/01-tune_correction.py b/examples/use_cases/01-tune_correction.py
index d77cb3671..1525b993a 100644
--- a/examples/use_cases/01-tune_correction.py
+++ b/examples/use_cases/01-tune_correction.py
@@ -80,7 +80,7 @@
# In[4]:
-tune_monitor = SR.get_betatron_tune_monitor("BETATRON_TUNE")
+tune_monitor = SR.diagnostic.get("BETATRON_TUNE")
print(f"Current tune: {tune_monitor.tune.get()}")
print(tune_monitor) # string representation
@@ -112,14 +112,14 @@
# ### Standard tune correction tool
#
-# `SR.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.
+# `SR.tool.tune` is the `DEFAULT_TUNE_CORRECTION` tool. `SR.tool.trm` is the `DEFAULT_TUNE_RESPONSE_MATRIX` tool.
#
# Before correcting the tune you need a response matrix. It can be measured (below) or loaded from a previously saved file.
# In[7]:
-print(SR.tune) # string representation
+print(SR.tool.tune) # string representation
# #### Measuring the tune response matrix
@@ -145,36 +145,36 @@ def tune_callback(action: int, cb_data: dict):
# In[9]:
-if SR.tune.response_matrix is None:
- SR.trm.measure(sleep_between_step=wait_time, callback=tune_callback)
- SR.trm.save(CONFIG_DIR / "trm.json")
+if SR.tool.tune.response_matrix is None:
+ SR.tool.trm.measure(sleep_between_step=wait_time, callback=tune_callback)
+ SR.tool.trm.save(CONFIG_DIR / "trm.json")
-SR.tune.load(CONFIG_DIR / "trm.json")
+SR.tool.tune.load(CONFIG_DIR / "trm.json")
print("Response matrix loaded.")
-print(SR.trm) # string representation
+print(SR.tool.trm) # string representation
# #### Correcting the tune
#
-# `SR.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls
+# `SR.tool.tune.set([qx, qy])` runs the correction iteratively. The `iter` parameter controls
# the number of iterations and `wait_time` the settling time between each iteration.
# In[10]:
-print(f"Tune before correction: {SR.tune.readback()}")
+print(f"Tune before correction: {SR.tool.tune.readback()}")
qx, qy = 0.19, 0.28
print(f"\nSetting tune to [{qx}, {qy}]")
-SR.tune.set([qx, qy], iter=10, wait_time=wait_time)
-print(f"Tune after correction: {SR.tune.readback()}")
+SR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)
+print(f"Tune after correction: {SR.tool.tune.readback()}")
qx, qy = 0.21, 0.30
print(f"\nSetting tune to [{qx}, {qy}]")
-SR.tune.set([qx, qy], iter=10, wait_time=wait_time)
-print(f"Tune after correction: {SR.tune.readback()}")
+SR.tool.tune.set([qx, qy], iter=10, wait_time=wait_time)
+print(f"Tune after correction: {SR.tool.tune.readback()}")
-print(SR.tune) # string representation
+print(SR.tool.tune) # string representation
# In[ ]:
diff --git a/examples/use_cases/02-chromaticity_measurement.ipynb b/examples/use_cases/02-chromaticity_measurement.ipynb
index 9ac1afca7..05ea57a2c 100644
--- a/examples/use_cases/02-chromaticity_measurement.ipynb
+++ b/examples/use_cases/02-chromaticity_measurement.ipynb
@@ -267,7 +267,7 @@
}
],
"source": [
- "chroma_monitor = SR.get_chromaticity_monitor(\"CHROMATICITY_MONITOR\")\n",
+ "chroma_monitor = SR.tool.get(\"CHROMATICITY_MONITOR\")\n",
"\n",
"chroma_monitor.measure(\n",
" callback=chroma_callback,\n",
diff --git a/examples/use_cases/02-chromaticity_measurement.py b/examples/use_cases/02-chromaticity_measurement.py
index 966b23ef3..320aa0b94 100644
--- a/examples/use_cases/02-chromaticity_measurement.py
+++ b/examples/use_cases/02-chromaticity_measurement.py
@@ -109,7 +109,7 @@ def chroma_callback(action: int, cb_data: dict):
# In[17]:
-chroma_monitor = SR.get_chromaticity_monitor("CHROMATICITY_MONITOR")
+chroma_monitor = SR.tool.get("CHROMATICITY_MONITOR")
chroma_monitor.measure(
callback=chroma_callback,
diff --git a/examples/use_cases/03-orbit_correction.ipynb b/examples/use_cases/03-orbit_correction.ipynb
index e476b7a0e..9121fd64a 100644
--- a/examples/use_cases/03-orbit_correction.ipynb
+++ b/examples/use_cases/03-orbit_correction.ipynb
@@ -185,163 +185,33 @@
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": null,
"id": "6adb7436",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "BPMs: 320, H correctors: 288, V correctors: 288\n"
- ]
- }
- ],
- "source": [
- "bpms = SR.bpms.get(\"BPM\")\n",
- "hcorr = SR.magnets.get(\"HCorr\")\n",
- "vcorr = SR.magnets.get(\"VCorr\")\n",
- "print(f\"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}\")"
- ]
+ "outputs": [],
+ "source": "bpms = SR.diagnostic.bpms.get(\"BPM\")\nhcorr = SR.magnets.get(\"HCorr\")\nvcorr = SR.magnets.get(\"VCorr\")\nprint(f\"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}\")"
},
{
"cell_type": "markdown",
"id": "808334df",
"metadata": {},
- "source": [
- "### Orbit response matrix\n",
- "\n",
- "The ORM can be saved in multiple formats. Load it into `SR.orbit` before correcting."
- ]
+ "source": "### Orbit response matrix\n\nThe ORM can be saved in multiple formats. Load it into `SR.tool.orbit` before correcting."
},
{
"cell_type": "code",
- "execution_count": 7,
+ "execution_count": null,
"id": "33636af2",
"metadata": {},
- "outputs": [
- {
- "data": {
- "text/plain": [
- "OrbitResponseMatrix(bpm_array_name='BPM', hcorr_array_name='HCorr', vcorr_array_name='VCorr', corrector_delta=1e-06, n_step=1, sleep_between_step=0.0, n_avg_meas=1, sleep_between_meas=0.0, name='DEFAULT_ORBIT_RESPONSE_MATRIX')"
- ]
- },
- "execution_count": 7,
- "metadata": {},
- "output_type": "execute_result"
- }
- ],
- "source": [
- "SR.orm # string representation"
- ]
+ "outputs": [],
+ "source": "SR.tool.orm # string representation"
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f9dcb18",
"metadata": {},
- "outputs": [
- {
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "14 Sep 2026, 15:10:12 | INFO | Measuring correctors from the default arrays: HCorr and VCorr.\n",
- "14 Sep 2026, 15:10:14 | INFO | Measured response of SH1A-C04-H.\n",
- "14 Sep 2026, 15:10:16 | INFO | Measured response of SJ1A-C04-H.\n",
- "14 Sep 2026, 15:10:17 | INFO | Measured response of SJ2A-C04-H.\n",
- "14 Sep 2026, 15:10:18 | INFO | Measured response of SJ1B-C04-H.\n",
- "14 Sep 2026, 15:10:19 | INFO | Measured response of SH2B-C04-H.\n",
- "14 Sep 2026, 15:10:21 | INFO | Measured response of SJ1D-C04-H.\n",
- "14 Sep 2026, 15:10:22 | INFO | Measured response of SJ2E-C04-H.\n",
- "14 Sep 2026, 15:10:23 | INFO | Measured response of SJ1E-C04-H.\n",
- "14 Sep 2026, 15:10:24 | INFO | Measured response of SH3E-C04-H.\n",
- "14 Sep 2026, 15:10:26 | INFO | Measured response of SH1A-C05-H.\n",
- "14 Sep 2026, 15:10:27 | INFO | Measured response of SD1A-C05-H.\n",
- "14 Sep 2026, 15:10:28 | INFO | Measured response of SF2A-C05-H.\n",
- "14 Sep 2026, 15:10:29 | INFO | Measured response of SD1B-C05-H.\n",
- "14 Sep 2026, 15:10:31 | INFO | Measured response of SH2B-C05-H.\n",
- "14 Sep 2026, 15:10:32 | INFO | Measured response of SD1D-C05-H.\n",
- "14 Sep 2026, 15:10:33 | INFO | Measured response of SF2E-C05-H.\n",
- "14 Sep 2026, 15:10:34 | INFO | Measured response of SD1E-C05-H.\n",
- "14 Sep 2026, 15:10:36 | INFO | Measured response of SH3E-C05-H.\n",
- "14 Sep 2026, 15:10:37 | INFO | Measured response of SH1A-C06-H.\n",
- "14 Sep 2026, 15:10:38 | INFO | Measured response of SD1A-C06-H.\n",
- "14 Sep 2026, 15:10:39 | INFO | Measured response of SF2A-C06-H.\n",
- "14 Sep 2026, 15:10:41 | INFO | Measured response of SD1B-C06-H.\n",
- "14 Sep 2026, 15:10:42 | INFO | Measured response of SH2B-C06-H.\n",
- "14 Sep 2026, 15:10:43 | INFO | Measured response of SD1D-C06-H.\n",
- "14 Sep 2026, 15:10:44 | INFO | Measured response of SF2E-C06-H.\n",
- "14 Sep 2026, 15:10:45 | INFO | Measured response of SD1E-C06-H.\n",
- "14 Sep 2026, 15:10:47 | INFO | Measured response of SH3E-C06-H.\n",
- "14 Sep 2026, 15:10:48 | INFO | Measured response of SH1A-C07-H.\n",
- "14 Sep 2026, 15:10:49 | INFO | Measured response of SD1A-C07-H.\n",
- "14 Sep 2026, 15:10:50 | INFO | Measured response of SF2A-C07-H.\n",
- "14 Sep 2026, 15:10:52 | INFO | Measured response of SD1B-C07-H.\n",
- "14 Sep 2026, 15:10:53 | INFO | Measured response of SH2B-C07-H.\n",
- "14 Sep 2026, 15:10:54 | INFO | Measured response of SD1D-C07-H.\n",
- "14 Sep 2026, 15:10:55 | INFO | Measured response of SF2E-C07-H.\n",
- "14 Sep 2026, 15:10:56 | INFO | Measured response of SD1E-C07-H.\n",
- "14 Sep 2026, 15:10:57 | INFO | Measured response of SH3E-C07-H.\n",
- "14 Sep 2026, 15:10:59 | INFO | Measured response of SH1A-C08-H.\n",
- "14 Sep 2026, 15:11:00 | INFO | Measured response of SD1A-C08-H.\n",
- "14 Sep 2026, 15:11:01 | INFO | Measured response of SF2A-C08-H.\n",
- "14 Sep 2026, 15:11:02 | INFO | Measured response of SD1B-C08-H.\n",
- "14 Sep 2026, 15:11:04 | INFO | Measured response of SH2B-C08-H.\n",
- "14 Sep 2026, 15:11:05 | INFO | Measured response of SD1D-C08-H.\n",
- "14 Sep 2026, 15:11:06 | INFO | Measured response of SF2E-C08-H.\n",
- "14 Sep 2026, 15:11:07 | INFO | Measured response of SD1E-C08-H.\n",
- "14 Sep 2026, 15:11:08 | INFO | Measured response of SH3E-C08-H.\n",
- "14 Sep 2026, 15:11:10 | INFO | Measured response of SH1A-C09-H.\n",
- "14 Sep 2026, 15:11:11 | INFO | Measured response of SD1A-C09-H.\n",
- "14 Sep 2026, 15:11:12 | INFO | Measured response of SF2A-C09-H.\n",
- "14 Sep 2026, 15:11:13 | INFO | Measured response of SD1B-C09-H.\n",
- "14 Sep 2026, 15:11:14 | INFO | Measured response of SH2B-C09-H.\n",
- "14 Sep 2026, 15:11:16 | INFO | Measured response of SD1D-C09-H.\n",
- "14 Sep 2026, 15:11:17 | INFO | Measured response of SF2E-C09-H.\n",
- "14 Sep 2026, 15:11:18 | INFO | Measured response of SD1E-C09-H.\n",
- "14 Sep 2026, 15:11:19 | INFO | Measured response of SH3E-C09-H.\n",
- "14 Sep 2026, 15:11:21 | INFO | Measured response of SH1A-C10-H.\n",
- "14 Sep 2026, 15:11:22 | INFO | Measured response of SD1A-C10-H.\n",
- "14 Sep 2026, 15:11:23 | INFO | Measured response of SF2A-C10-H.\n",
- "14 Sep 2026, 15:11:24 | INFO | Measured response of SD1B-C10-H.\n",
- "14 Sep 2026, 15:11:26 | INFO | Measured response of SH2B-C10-H.\n",
- "14 Sep 2026, 15:11:27 | INFO | Measured response of SD1D-C10-H.\n",
- "14 Sep 2026, 15:11:28 | INFO | Measured response of SF2E-C10-H.\n",
- "14 Sep 2026, 15:11:29 | INFO | Measured response of SD1E-C10-H.\n",
- "14 Sep 2026, 15:11:31 | INFO | Measured response of SH3E-C10-H.\n",
- "14 Sep 2026, 15:11:32 | INFO | Measured response of SH1A-C11-H.\n",
- "14 Sep 2026, 15:11:33 | INFO | Measured response of SD1A-C11-H.\n",
- "14 Sep 2026, 15:11:34 | INFO | Measured response of SF2A-C11-H.\n",
- "14 Sep 2026, 15:11:35 | INFO | Measured response of SD1B-C11-H.\n",
- "14 Sep 2026, 15:11:37 | INFO | Measured response of SH2B-C11-H.\n",
- "14 Sep 2026, 15:11:38 | INFO | Measured response of SD1D-C11-H.\n",
- "14 Sep 2026, 15:11:39 | INFO | Measured response of SF2E-C11-H.\n",
- "14 Sep 2026, 15:11:40 | INFO | Measured response of SD1E-C11-H.\n",
- "14 Sep 2026, 15:11:41 | INFO | Measured response of SH3E-C11-H.\n",
- "14 Sep 2026, 15:11:43 | INFO | Measured response of SH1A-C12-H.\n",
- "14 Sep 2026, 15:11:44 | INFO | Measured response of SD1A-C12-H.\n",
- "14 Sep 2026, 15:11:45 | INFO | Measured response of SF2A-C12-H.\n",
- "14 Sep 2026, 15:11:46 | INFO | Measured response of SD1B-C12-H.\n",
- "14 Sep 2026, 15:11:47 | INFO | Measured response of SH2B-C12-H.\n",
- "14 Sep 2026, 15:11:49 | INFO | Measured response of SD1D-C12-H.\n",
- "14 Sep 2026, 15:11:50 | INFO | Measured response of SF2E-C12-H.\n",
- "14 Sep 2026, 15:11:51 | INFO | Measured response of SD1E-C12-H.\n",
- "14 Sep 2026, 15:11:52 | INFO | Measured response of SH3E-C12-H.\n",
- "14 Sep 2026, 15:11:54 | INFO | Measured response of SH1A-C13-H.\n",
- "14 Sep 2026, 15:11:55 | INFO | Measured response of SD1A-C13-H.\n",
- "14 Sep 2026, 15:11:56 | INFO | Measured response of SF2A-C13-H.\n"
- ]
- }
- ],
- "source": [
- "SR.orm.measure(sleep_between_step=wait_time)\n",
- "SR.orm.save(CONFIG_DIR / \"orm.json\")\n",
- "SR.orm.save(CONFIG_DIR / \"orm.yaml\", with_type=\"yaml\")\n",
- "SR.orm.save(CONFIG_DIR / \"orm.npz\", with_type=\"npz\")\n",
- "\n",
- "SR.orbit.load(CONFIG_DIR / \"orm.json\")\n",
- "print(\"ORM measured, saved and loaded.\")"
- ]
+ "outputs": [],
+ "source": "SR.tool.orm.measure(sleep_between_step=wait_time)\nSR.tool.orm.save(CONFIG_DIR / \"orm.json\")\nSR.tool.orm.save(CONFIG_DIR / \"orm.yaml\", with_type=\"yaml\")\nSR.tool.orm.save(CONFIG_DIR / \"orm.npz\", with_type=\"npz\")\n\nSR.tool.orbit.load(CONFIG_DIR / \"orm.json\")\nprint(\"ORM measured, saved and loaded.\")"
},
{
"cell_type": "markdown",
@@ -357,15 +227,7 @@
"id": "942f8f3b",
"metadata": {},
"outputs": [],
- "source": [
- "orm_data = SR.orm.get()\n",
- "plt.imshow(np.array(orm_data[\"matrix\"]))\n",
- "plt.colorbar()\n",
- "plt.title(\"Orbit response matrix\")\n",
- "plt.xlabel(\"Corrector index\")\n",
- "plt.ylabel(\"BPM index\")\n",
- "plt.show()"
- ]
+ "source": "orm_data = SR.tool.orm.get()\nplt.imshow(np.array(orm_data[\"matrix\"]))\nplt.colorbar()\nplt.title(\"Orbit response matrix\")\nplt.xlabel(\"Corrector index\")\nplt.ylabel(\"BPM index\")\nplt.show()"
},
{
"cell_type": "markdown",
@@ -383,28 +245,7 @@
"id": "693fc409",
"metadata": {},
"outputs": [],
- "source": [
- "# Uncomment to measure and visualise dispersion\n",
- "\n",
- "# def disp_callback(action: int, cb_data) -> bool:\n",
- "# from pyaml.common.constants import Action\n",
- "# if action == Action.APPLY:\n",
- "# print(\"Changing RF frequency\")\n",
- "# elif action == Action.MEASURE:\n",
- "# print(\"Reading orbit\")\n",
- "# elif action == Action.RESTORE:\n",
- "# print(\"Restoring RF frequency\")\n",
- "# return True\n",
- "\n",
- "# SR.dispersion.measure(callback=disp_callback)\n",
- "# disp_data = SR.dispersion.get()\n",
- "# plt.plot(disp_data[\"frequency_response_x\"], label=\"H dispersion\")\n",
- "# plt.plot(disp_data[\"frequency_response_y\"], label=\"V dispersion\")\n",
- "# plt.xlabel(\"BPM index\")\n",
- "# plt.ylabel(\"Orbit / Δf [m/Hz]\")\n",
- "# plt.legend()\n",
- "# plt.show()"
- ]
+ "source": "# Uncomment to measure and visualise dispersion\n\n# def disp_callback(action: int, cb_data) -> bool:\n# from pyaml.common.constants import Action\n# if action == Action.APPLY:\n# print(\"Changing RF frequency\")\n# elif action == Action.MEASURE:\n# print(\"Reading orbit\")\n# elif action == Action.RESTORE:\n# print(\"Restoring RF frequency\")\n# return True\n\n# SR.tool.dispersion.measure(callback=disp_callback)\n# disp_data = SR.tool.dispersion.get()\n# plt.plot(disp_data[\"frequency_response_x\"], label=\"H dispersion\")\n# plt.plot(disp_data[\"frequency_response_y\"], label=\"V dispersion\")\n# plt.xlabel(\"BPM index\")\n# plt.ylabel(\"Orbit / Δf [m/Hz]\")\n# plt.legend()\n# plt.show()"
},
{
"cell_type": "markdown",
@@ -477,16 +318,7 @@
"cell_type": "markdown",
"id": "cf49c543",
"metadata": {},
- "source": [
- "### Correct the orbit\n",
- "\n",
- "Standard correction: `SR.orbit.correct(reference=reference)`.\n",
- "\n",
- "Optional variants (uncomment to use):\n",
- "- **Virtual corrector weight**: down-weights correctors that are already at large strengths.\n",
- "- **RF correction**: also adjusts the RF frequency to minimise dispersion-driven orbit.\n",
- "- **Live unit mismatch**: if BESSY2 BPMs read in nm, pass `gain=1e-9`."
- ]
+ "source": "### Correct the orbit\n\nStandard correction: `SR.tool.orbit.correct(reference=reference)`.\n\nOptional variants (uncomment to use):\n- **Virtual corrector weight**: down-weights correctors that are already at large strengths.\n- **RF correction**: also adjusts the RF frequency to minimise dispersion-driven orbit.\n- **Live unit mismatch**: if BESSY2 BPMs read in nm, pass `gain=1e-9`."
},
{
"cell_type": "code",
@@ -494,22 +326,7 @@
"id": "93135a4c",
"metadata": {},
"outputs": [],
- "source": [
- "# Standard correction\n",
- "SR.orbit.correct(reference=reference)\n",
- "\n",
- "# With virtual corrector weight (ESRF style):\n",
- "# SR.orbit.set_virtual_weight(1000)\n",
- "# SR.orbit.correct(reference=reference)\n",
- "\n",
- "# With RF orbit correction (ESRF style, requires dispersion in ORM):\n",
- "# SR.orbit.correct(reference=reference, rf=True)\n",
- "\n",
- "# BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch:\n",
- "# SR.orbit.correct(reference=reference, gain=1e-9)\n",
- "\n",
- "sleep(wait_time)"
- ]
+ "source": "# Standard correction\nSR.tool.orbit.correct(reference=reference)\n\n# With virtual corrector weight (ESRF style):\n# SR.tool.orbit.set_virtual_weight(1000)\n# SR.tool.orbit.correct(reference=reference)\n\n# With RF orbit correction (ESRF style, requires dispersion in ORM):\n# SR.tool.orbit.correct(reference=reference, rf=True)\n\n# BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch:\n# SR.tool.orbit.correct(reference=reference, gain=1e-9)\n\nsleep(wait_time)"
},
{
"cell_type": "code",
diff --git a/examples/use_cases/03-orbit_correction.py b/examples/use_cases/03-orbit_correction.py
index ceef8ec18..7271f26fb 100644
--- a/examples/use_cases/03-orbit_correction.py
+++ b/examples/use_cases/03-orbit_correction.py
@@ -84,7 +84,7 @@
# In[4]:
-bpms = SR.bpms.get("BPM")
+bpms = SR.diagnostic.bpms.get("BPM")
hcorr = SR.magnets.get("HCorr")
vcorr = SR.magnets.get("VCorr")
print(f"BPMs: {len(bpms)}, H correctors: {len(hcorr)}, V correctors: {len(vcorr)}")
@@ -92,23 +92,23 @@
# ### Orbit response matrix
#
-# The ORM can be saved in multiple formats. Load it into `SR.orbit` before correcting.
+# The ORM can be saved in multiple formats. Load it into `SR.tool.orbit` before correcting.
# In[5]:
-print(SR.orm) # string representation
+print(SR.tool.orm) # string representation
# In[6]:
-SR.orm.measure(sleep_between_step=wait_time)
-SR.orm.save(CONFIG_DIR / "orm.json")
-SR.orm.save(CONFIG_DIR / "orm.yaml", with_type="yaml")
-SR.orm.save(CONFIG_DIR / "orm.npz", with_type="npz")
+SR.tool.orm.measure(sleep_between_step=wait_time)
+SR.tool.orm.save(CONFIG_DIR / "orm.json")
+SR.tool.orm.save(CONFIG_DIR / "orm.yaml", with_type="yaml")
+SR.tool.orm.save(CONFIG_DIR / "orm.npz", with_type="npz")
-SR.orbit.load(CONFIG_DIR / "orm.json")
+SR.tool.orbit.load(CONFIG_DIR / "orm.json")
print("ORM measured, saved and loaded.")
@@ -117,7 +117,7 @@
# In[7]:
-orm_data = SR.orm.get()
+orm_data = SR.tool.orm.get()
plt.imshow(np.array(orm_data["matrix"]))
plt.colorbar()
plt.title("Orbit response matrix")
@@ -147,8 +147,8 @@
# print("Restoring RF frequency")
# return True
-# SR.dispersion.measure(callback=disp_callback)
-# disp_data = SR.dispersion.get()
+# SR.tool.dispersion.measure(callback=disp_callback)
+# disp_data = SR.tool.dispersion.get()
# plt.plot(disp_data["frequency_response_x"], label="H dispersion")
# plt.plot(disp_data["frequency_response_y"], label="V dispersion")
# plt.xlabel("BPM index")
@@ -202,7 +202,7 @@
# ### Correct the orbit
#
-# Standard correction: `SR.orbit.correct(reference=reference)`.
+# Standard correction: `SR.tool.orbit.correct(reference=reference)`.
#
# Optional variants (uncomment to use):
# - **Virtual corrector weight**: down-weights correctors that are already at large strengths.
@@ -213,17 +213,17 @@
# Standard correction
-SR.orbit.correct(reference=reference)
+SR.tool.orbit.correct(reference=reference)
# With virtual corrector weight (ESRF style):
-# SR.orbit.set_virtual_weight(1000)
-# SR.orbit.correct(reference=reference)
+# SR.tool.orbit.set_virtual_weight(1000)
+# SR.tool.orbit.correct(reference=reference)
# With RF orbit correction (ESRF style, requires dispersion in ORM):
-# SR.orbit.correct(reference=reference, rf=True)
+# SR.tool.orbit.correct(reference=reference, rf=True)
# BESSY2 live mode — BPMs in nm, use gain to compensate unit mismatch:
-# SR.orbit.correct(reference=reference, gain=1e-9)
+# SR.tool.orbit.correct(reference=reference, gain=1e-9)
sleep(wait_time)
diff --git a/examples/use_cases/README.md b/examples/use_cases/README.md
index ebcfe8c99..6bc3076ed 100644
--- a/examples/use_cases/README.md
+++ b/examples/use_cases/README.md
@@ -89,8 +89,8 @@ In `design` mode all wait times can be set to `0.0`. In `live` mode use `wait_ti
| `BPM` | Beam position monitors |
| `BETATRON_TUNE` | Betatron tune monitor |
| `CHROMATICITY_MONITOR` | Chromaticity monitor |
-| `DEFAULT_TUNE_CORRECTION` | Tune correction tool → `SR.tune` |
-| `DEFAULT_TUNE_RESPONSE_MATRIX` | Tune response matrix tool → `SR.trm` |
-| `DEFAULT_ORBIT_CORRECTION` | Orbit correction tool → `SR.orbit` |
-| `DEFAULT_ORBIT_RESPONSE_MATRIX` | Orbit response matrix tool → `SR.orm` |
-| `DEFAULT_DISPERSION` | Dispersion measurement tool → `SR.dispersion` |
+| `DEFAULT_TUNE_CORRECTION` | Tune correction tool → `SR.tool.tune` |
+| `DEFAULT_TUNE_RESPONSE_MATRIX` | Tune response matrix tool → `SR.tool.trm` |
+| `DEFAULT_ORBIT_CORRECTION` | Orbit correction tool → `SR.tool.orbit` |
+| `DEFAULT_ORBIT_RESPONSE_MATRIX` | Orbit response matrix tool → `SR.tool.orm` |
+| `DEFAULT_DISPERSION` | Dispersion measurement tool → `SR.tool.dispersion` |
diff --git a/examples/use_cases/config/bessy2/bessy2.yaml b/examples/use_cases/config/bessy2/bessy2.yaml
index eb4938153..8d5d1f354 100644
--- a/examples/use_cases/config/bessy2/bessy2.yaml
+++ b/examples/use_cases/config/bessy2/bessy2.yaml
@@ -1356,495 +1356,495 @@ devices:
unit: 1/m
powerconverter: (VS3P1D1R:rdbk, VS3P1D1R:set)[A]
hardware_unit: A
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D1R
x_pos: ORBITCC:rdPos@0
y_pos: ORBITCC:rdPos@1
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D1R
x_pos: ORBITCC:rdPos@2
y_pos: ORBITCC:rdPos@3
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D1R
x_pos: ORBITCC:rdPos@4
y_pos: ORBITCC:rdPos@5
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T1R
x_pos: ORBITCC:rdPos@6
y_pos: ORBITCC:rdPos@7
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T1R
x_pos: ORBITCC:rdPos@8
y_pos: ORBITCC:rdPos@9
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T1R
x_pos: ORBITCC:rdPos@10
y_pos: ORBITCC:rdPos@11
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T1R
x_pos: ORBITCC:rdPos@12
y_pos: ORBITCC:rdPos@13
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41T1R
x_pos: ORBITCC:rdPos@14
y_pos: ORBITCC:rdPos@15
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T1R
x_pos: ORBITCC:rdPos@16
y_pos: ORBITCC:rdPos@17
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T1R
x_pos: ORBITCC:rdPos@18
y_pos: ORBITCC:rdPos@19
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T1R
x_pos: ORBITCC:rdPos@20
y_pos: ORBITCC:rdPos@21
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D2R
x_pos: ORBITCC:rdPos@22
y_pos: ORBITCC:rdPos@23
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D2R
x_pos: ORBITCC:rdPos@24
y_pos: ORBITCC:rdPos@25
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D2R
x_pos: ORBITCC:rdPos@26
y_pos: ORBITCC:rdPos@27
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D2R
x_pos: ORBITCC:rdPos@28
y_pos: ORBITCC:rdPos@29
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D2R
x_pos: ORBITCC:rdPos@30
y_pos: ORBITCC:rdPos@31
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D2R
x_pos: ORBITCC:rdPos@32
y_pos: ORBITCC:rdPos@33
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D2R
x_pos: ORBITCC:rdPos@34
y_pos: ORBITCC:rdPos@35
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T2R
x_pos: ORBITCC:rdPos@36
y_pos: ORBITCC:rdPos@37
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T2R
x_pos: ORBITCC:rdPos@38
y_pos: ORBITCC:rdPos@39
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T2R
x_pos: ORBITCC:rdPos@40
y_pos: ORBITCC:rdPos@41
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T2R
x_pos: ORBITCC:rdPos@42
y_pos: ORBITCC:rdPos@43
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41T2R
x_pos: ORBITCC:rdPos@44
y_pos: ORBITCC:rdPos@45
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ42T2R
x_pos: ORBITCC:rdPos@46
y_pos: ORBITCC:rdPos@47
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ43T2R
x_pos: ORBITCC:rdPos@48
y_pos: ORBITCC:rdPos@49
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T2R
x_pos: ORBITCC:rdPos@50
y_pos: ORBITCC:rdPos@51
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T2R
x_pos: ORBITCC:rdPos@52
y_pos: ORBITCC:rdPos@53
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T2R
x_pos: ORBITCC:rdPos@54
y_pos: ORBITCC:rdPos@55
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D3R
x_pos: ORBITCC:rdPos@56
y_pos: ORBITCC:rdPos@57
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D3R
x_pos: ORBITCC:rdPos@58
y_pos: ORBITCC:rdPos@59
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D3R
x_pos: ORBITCC:rdPos@60
y_pos: ORBITCC:rdPos@61
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D3R
x_pos: ORBITCC:rdPos@62
y_pos: ORBITCC:rdPos@63
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D3R
x_pos: ORBITCC:rdPos@64
y_pos: ORBITCC:rdPos@65
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D3R
x_pos: ORBITCC:rdPos@66
y_pos: ORBITCC:rdPos@67
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D3R
x_pos: ORBITCC:rdPos@68
y_pos: ORBITCC:rdPos@69
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T3R
x_pos: ORBITCC:rdPos@70
y_pos: ORBITCC:rdPos@71
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T3R
x_pos: ORBITCC:rdPos@72
y_pos: ORBITCC:rdPos@73
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T3R
x_pos: ORBITCC:rdPos@74
y_pos: ORBITCC:rdPos@75
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T3R
x_pos: ORBITCC:rdPos@76
y_pos: ORBITCC:rdPos@77
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T3R
x_pos: ORBITCC:rdPos@78
y_pos: ORBITCC:rdPos@79
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T3R
x_pos: ORBITCC:rdPos@80
y_pos: ORBITCC:rdPos@81
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T3R
x_pos: ORBITCC:rdPos@82
y_pos: ORBITCC:rdPos@83
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D4R
x_pos: ORBITCC:rdPos@84
y_pos: ORBITCC:rdPos@85
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D4R
x_pos: ORBITCC:rdPos@86
y_pos: ORBITCC:rdPos@87
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D4R
x_pos: ORBITCC:rdPos@88
y_pos: ORBITCC:rdPos@89
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D4R
x_pos: ORBITCC:rdPos@90
y_pos: ORBITCC:rdPos@91
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D4R
x_pos: ORBITCC:rdPos@92
y_pos: ORBITCC:rdPos@93
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D4R
x_pos: ORBITCC:rdPos@94
y_pos: ORBITCC:rdPos@95
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D4R
x_pos: ORBITCC:rdPos@96
y_pos: ORBITCC:rdPos@97
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T4R
x_pos: ORBITCC:rdPos@98
y_pos: ORBITCC:rdPos@99
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T4R
x_pos: ORBITCC:rdPos@100
y_pos: ORBITCC:rdPos@101
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T4R
x_pos: ORBITCC:rdPos@102
y_pos: ORBITCC:rdPos@103
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T4R
x_pos: ORBITCC:rdPos@104
y_pos: ORBITCC:rdPos@105
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T4R
x_pos: ORBITCC:rdPos@106
y_pos: ORBITCC:rdPos@107
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T4R
x_pos: ORBITCC:rdPos@108
y_pos: ORBITCC:rdPos@109
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T4R
x_pos: ORBITCC:rdPos@110
y_pos: ORBITCC:rdPos@111
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D5R
x_pos: ORBITCC:rdPos@112
y_pos: ORBITCC:rdPos@113
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D5R
x_pos: ORBITCC:rdPos@114
y_pos: ORBITCC:rdPos@115
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D5R
x_pos: ORBITCC:rdPos@116
y_pos: ORBITCC:rdPos@117
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D5R
x_pos: ORBITCC:rdPos@118
y_pos: ORBITCC:rdPos@119
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D5R
x_pos: ORBITCC:rdPos@120
y_pos: ORBITCC:rdPos@121
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D5R
x_pos: ORBITCC:rdPos@122
y_pos: ORBITCC:rdPos@123
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D5R
x_pos: ORBITCC:rdPos@124
y_pos: ORBITCC:rdPos@125
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T5R
x_pos: ORBITCC:rdPos@126
y_pos: ORBITCC:rdPos@127
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T5R
x_pos: ORBITCC:rdPos@128
y_pos: ORBITCC:rdPos@129
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T5R
x_pos: ORBITCC:rdPos@130
y_pos: ORBITCC:rdPos@131
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T5R
x_pos: ORBITCC:rdPos@132
y_pos: ORBITCC:rdPos@133
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T5R
x_pos: ORBITCC:rdPos@134
y_pos: ORBITCC:rdPos@135
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T5R
x_pos: ORBITCC:rdPos@136
y_pos: ORBITCC:rdPos@137
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T5R
x_pos: ORBITCC:rdPos@138
y_pos: ORBITCC:rdPos@139
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D6R
x_pos: ORBITCC:rdPos@140
y_pos: ORBITCC:rdPos@141
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D6R
x_pos: ORBITCC:rdPos@142
y_pos: ORBITCC:rdPos@143
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D6R
x_pos: ORBITCC:rdPos@144
y_pos: ORBITCC:rdPos@145
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D6R
x_pos: ORBITCC:rdPos@146
y_pos: ORBITCC:rdPos@147
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41D6R
x_pos: ORBITCC:rdPos@148
y_pos: ORBITCC:rdPos@149
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ42D6R
x_pos: ORBITCC:rdPos@150
y_pos: ORBITCC:rdPos@151
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ43D6R
x_pos: ORBITCC:rdPos@152
y_pos: ORBITCC:rdPos@153
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ44D6R
x_pos: ORBITCC:rdPos@154
y_pos: ORBITCC:rdPos@155
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D6R
x_pos: ORBITCC:rdPos@156
y_pos: ORBITCC:rdPos@157
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D6R
x_pos: ORBITCC:rdPos@158
y_pos: ORBITCC:rdPos@159
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T6R
x_pos: ORBITCC:rdPos@160
y_pos: ORBITCC:rdPos@161
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T6R
x_pos: ORBITCC:rdPos@162
y_pos: ORBITCC:rdPos@163
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T6R
x_pos: ORBITCC:rdPos@164
y_pos: ORBITCC:rdPos@165
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T6R
x_pos: ORBITCC:rdPos@166
y_pos: ORBITCC:rdPos@167
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41T6R
x_pos: ORBITCC:rdPos@168
y_pos: ORBITCC:rdPos@169
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T6R
x_pos: ORBITCC:rdPos@170
y_pos: ORBITCC:rdPos@171
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T6R
x_pos: ORBITCC:rdPos@172
y_pos: ORBITCC:rdPos@173
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T6R
x_pos: ORBITCC:rdPos@174
y_pos: ORBITCC:rdPos@175
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D7R
x_pos: ORBITCC:rdPos@176
y_pos: ORBITCC:rdPos@177
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D7R
x_pos: ORBITCC:rdPos@178
y_pos: ORBITCC:rdPos@179
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D7R
x_pos: ORBITCC:rdPos@180
y_pos: ORBITCC:rdPos@181
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D7R
x_pos: ORBITCC:rdPos@182
y_pos: ORBITCC:rdPos@183
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D7R
x_pos: ORBITCC:rdPos@184
y_pos: ORBITCC:rdPos@185
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D7R
x_pos: ORBITCC:rdPos@186
y_pos: ORBITCC:rdPos@187
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D7R
x_pos: ORBITCC:rdPos@188
y_pos: ORBITCC:rdPos@189
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T7R
x_pos: ORBITCC:rdPos@190
y_pos: ORBITCC:rdPos@191
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T7R
x_pos: ORBITCC:rdPos@192
y_pos: ORBITCC:rdPos@193
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T7R
x_pos: ORBITCC:rdPos@194
y_pos: ORBITCC:rdPos@195
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T7R
x_pos: ORBITCC:rdPos@196
y_pos: ORBITCC:rdPos@197
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41T7R
x_pos: ORBITCC:rdPos@198
y_pos: ORBITCC:rdPos@199
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T7R
x_pos: ORBITCC:rdPos@200
y_pos: ORBITCC:rdPos@201
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T7R
x_pos: ORBITCC:rdPos@202
y_pos: ORBITCC:rdPos@203
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T7R
x_pos: ORBITCC:rdPos@204
y_pos: ORBITCC:rdPos@205
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D8R
x_pos: ORBITCC:rdPos@206
y_pos: ORBITCC:rdPos@207
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D8R
x_pos: ORBITCC:rdPos@208
y_pos: ORBITCC:rdPos@209
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D8R
x_pos: ORBITCC:rdPos@210
y_pos: ORBITCC:rdPos@211
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D8R
x_pos: ORBITCC:rdPos@212
y_pos: ORBITCC:rdPos@213
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5D8R
x_pos: ORBITCC:rdPos@214
y_pos: ORBITCC:rdPos@215
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6D8R
x_pos: ORBITCC:rdPos@216
y_pos: ORBITCC:rdPos@217
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7D8R
x_pos: ORBITCC:rdPos@218
y_pos: ORBITCC:rdPos@219
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1T8R
x_pos: ORBITCC:rdPos@220
y_pos: ORBITCC:rdPos@221
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2T8R
x_pos: ORBITCC:rdPos@222
y_pos: ORBITCC:rdPos@223
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3T8R
x_pos: ORBITCC:rdPos@224
y_pos: ORBITCC:rdPos@225
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4T8R
x_pos: ORBITCC:rdPos@226
y_pos: ORBITCC:rdPos@227
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ5T8R
x_pos: ORBITCC:rdPos@228
y_pos: ORBITCC:rdPos@229
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ6T8R
x_pos: ORBITCC:rdPos@230
y_pos: ORBITCC:rdPos@231
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ7T8R
x_pos: ORBITCC:rdPos@232
y_pos: ORBITCC:rdPos@233
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ1D1R
x_pos: ORBITCC:rdPos@234
y_pos: ORBITCC:rdPos@235
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ2D1R
x_pos: ORBITCC:rdPos@236
y_pos: ORBITCC:rdPos@237
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ3D1R
x_pos: ORBITCC:rdPos@238
y_pos: ORBITCC:rdPos@239
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ4D1R
x_pos: ORBITCC:rdPos@240
y_pos: ORBITCC:rdPos@241
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ41D1R
x_pos: ORBITCC:rdPos@242
y_pos: ORBITCC:rdPos@243
-- class: pyaml.bpm.bpm.BPM
+- class: pyaml.diagnostics.bpm.bpm.BPM
name: BPMZ42D1R
x_pos: ORBITCC:rdPos@244
y_pos: ORBITCC:rdPos@245
diff --git a/examples/use_cases/config/esrf/catalogs/ebs_catalogs.yaml b/examples/use_cases/config/esrf/catalogs/ebs_catalogs.yaml
index d15349d6f..b3da9a0d4 100644
--- a/examples/use_cases/config/esrf/catalogs/ebs_catalogs.yaml
+++ b/examples/use_cases/config/esrf/catalogs/ebs_catalogs.yaml
@@ -1,8 +1,8 @@
type: tango.pyaml.static_catalog
entries:
- - catalogs/ebs_bpm_catalogs.yaml
- - catalogs/ebs_rf_catalogs.yaml
- - catalogs/ebs_diag_catalogs.yaml
- - catalogs/ebs_magnets_catalogs.yaml
- - catalogs/ebs_sh_catalogs.yaml
- - catalogs/ebs_sext_catalogs.yaml
+ - ${include:catalogs/ebs_bpm_catalogs.yaml}
+ - ${include:catalogs/ebs_rf_catalogs.yaml}
+ - ${include:catalogs/ebs_diag_catalogs.yaml}
+ - ${include:catalogs/ebs_magnets_catalogs.yaml}
+ - ${include:catalogs/ebs_sh_catalogs.yaml}
+ - ${include:catalogs/ebs_sext_catalogs.yaml}
diff --git a/examples/use_cases/config/esrf/esrf.yaml b/examples/use_cases/config/esrf/esrf.yaml
index a3bdba75a..bb8a929e0 100644
--- a/examples/use_cases/config/esrf/esrf.yaml
+++ b/examples/use_cases/config/esrf/esrf.yaml
@@ -11,7 +11,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
@@ -5713,1285 +5713,1285 @@ devices:
- srmag/ps-corr-sh3/c03-e-ch3/current
- srmag/ps-corr-sh3/c03-e-ch5/current
- srmag/ps-corr-sh3/c03-e-ch6/current
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-01
x_pos: srdiag/bpm/c04-01/SA_HPosition
y_pos: srdiag/bpm/c04-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-02
x_pos: srdiag/bpm/c04-02/SA_HPosition
y_pos: srdiag/bpm/c04-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-03
x_pos: srdiag/bpm/c04-03/SA_HPosition
y_pos: srdiag/bpm/c04-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-04
x_pos: srdiag/bpm/c04-04/SA_HPosition
y_pos: srdiag/bpm/c04-04/SA_VPosition
x_offset: srdiag/bpm/c04-04/HOffset
y_offset: srdiag/bpm/c04-04/VOffset
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-05
x_pos: srdiag/bpm/c04-05/SA_HPosition
y_pos: srdiag/bpm/c04-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-06
x_pos: srdiag/bpm/c04-06/SA_HPosition
y_pos: srdiag/bpm/c04-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-07
x_pos: srdiag/bpm/c04-07/SA_HPosition
y_pos: srdiag/bpm/c04-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-08
x_pos: srdiag/bpm/c04-08/SA_HPosition
y_pos: srdiag/bpm/c04-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-09
x_pos: srdiag/bpm/c04-09/SA_HPosition
y_pos: srdiag/bpm/c04-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-10
x_pos: srdiag/bpm/c04-10/SA_HPosition
y_pos: srdiag/bpm/c04-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-01
x_pos: srdiag/bpm/c05-01/SA_HPosition
y_pos: srdiag/bpm/c05-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-02
x_pos: srdiag/bpm/c05-02/SA_HPosition
y_pos: srdiag/bpm/c05-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-03
x_pos: srdiag/bpm/c05-03/SA_HPosition
y_pos: srdiag/bpm/c05-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-04
x_pos: srdiag/bpm/c05-04/SA_HPosition
y_pos: srdiag/bpm/c05-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-05
x_pos: srdiag/bpm/c05-05/SA_HPosition
y_pos: srdiag/bpm/c05-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-06
x_pos: srdiag/bpm/c05-06/SA_HPosition
y_pos: srdiag/bpm/c05-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-07
x_pos: srdiag/bpm/c05-07/SA_HPosition
y_pos: srdiag/bpm/c05-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-08
x_pos: srdiag/bpm/c05-08/SA_HPosition
y_pos: srdiag/bpm/c05-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-09
x_pos: srdiag/bpm/c05-09/SA_HPosition
y_pos: srdiag/bpm/c05-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-10
x_pos: srdiag/bpm/c05-10/SA_HPosition
y_pos: srdiag/bpm/c05-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-01
x_pos: srdiag/bpm/c06-01/SA_HPosition
y_pos: srdiag/bpm/c06-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-02
x_pos: srdiag/bpm/c06-02/SA_HPosition
y_pos: srdiag/bpm/c06-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-03
x_pos: srdiag/bpm/c06-03/SA_HPosition
y_pos: srdiag/bpm/c06-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-04
x_pos: srdiag/bpm/c06-04/SA_HPosition
y_pos: srdiag/bpm/c06-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-05
x_pos: srdiag/bpm/c06-05/SA_HPosition
y_pos: srdiag/bpm/c06-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-06
x_pos: srdiag/bpm/c06-06/SA_HPosition
y_pos: srdiag/bpm/c06-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-07
x_pos: srdiag/bpm/c06-07/SA_HPosition
y_pos: srdiag/bpm/c06-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-08
x_pos: srdiag/bpm/c06-08/SA_HPosition
y_pos: srdiag/bpm/c06-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-09
x_pos: srdiag/bpm/c06-09/SA_HPosition
y_pos: srdiag/bpm/c06-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-10
x_pos: srdiag/bpm/c06-10/SA_HPosition
y_pos: srdiag/bpm/c06-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-01
x_pos: srdiag/bpm/c07-01/SA_HPosition
y_pos: srdiag/bpm/c07-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-02
x_pos: srdiag/bpm/c07-02/SA_HPosition
y_pos: srdiag/bpm/c07-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-03
x_pos: srdiag/bpm/c07-03/SA_HPosition
y_pos: srdiag/bpm/c07-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-04
x_pos: srdiag/bpm/c07-04/SA_HPosition
y_pos: srdiag/bpm/c07-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-05
x_pos: srdiag/bpm/c07-05/SA_HPosition
y_pos: srdiag/bpm/c07-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-06
x_pos: srdiag/bpm/c07-06/SA_HPosition
y_pos: srdiag/bpm/c07-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-07
x_pos: srdiag/bpm/c07-07/SA_HPosition
y_pos: srdiag/bpm/c07-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-08
x_pos: srdiag/bpm/c07-08/SA_HPosition
y_pos: srdiag/bpm/c07-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-09
x_pos: srdiag/bpm/c07-09/SA_HPosition
y_pos: srdiag/bpm/c07-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-10
x_pos: srdiag/bpm/c07-10/SA_HPosition
y_pos: srdiag/bpm/c07-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-01
x_pos: srdiag/bpm/c08-01/SA_HPosition
y_pos: srdiag/bpm/c08-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-02
x_pos: srdiag/bpm/c08-02/SA_HPosition
y_pos: srdiag/bpm/c08-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-03
x_pos: srdiag/bpm/c08-03/SA_HPosition
y_pos: srdiag/bpm/c08-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-04
x_pos: srdiag/bpm/c08-04/SA_HPosition
y_pos: srdiag/bpm/c08-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-05
x_pos: srdiag/bpm/c08-05/SA_HPosition
y_pos: srdiag/bpm/c08-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-06
x_pos: srdiag/bpm/c08-06/SA_HPosition
y_pos: srdiag/bpm/c08-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-07
x_pos: srdiag/bpm/c08-07/SA_HPosition
y_pos: srdiag/bpm/c08-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-08
x_pos: srdiag/bpm/c08-08/SA_HPosition
y_pos: srdiag/bpm/c08-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-09
x_pos: srdiag/bpm/c08-09/SA_HPosition
y_pos: srdiag/bpm/c08-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-10
x_pos: srdiag/bpm/c08-10/SA_HPosition
y_pos: srdiag/bpm/c08-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-01
x_pos: srdiag/bpm/c09-01/SA_HPosition
y_pos: srdiag/bpm/c09-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-02
x_pos: srdiag/bpm/c09-02/SA_HPosition
y_pos: srdiag/bpm/c09-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-03
x_pos: srdiag/bpm/c09-03/SA_HPosition
y_pos: srdiag/bpm/c09-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-04
x_pos: srdiag/bpm/c09-04/SA_HPosition
y_pos: srdiag/bpm/c09-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-05
x_pos: srdiag/bpm/c09-05/SA_HPosition
y_pos: srdiag/bpm/c09-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-06
x_pos: srdiag/bpm/c09-06/SA_HPosition
y_pos: srdiag/bpm/c09-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-07
x_pos: srdiag/bpm/c09-07/SA_HPosition
y_pos: srdiag/bpm/c09-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-08
x_pos: srdiag/bpm/c09-08/SA_HPosition
y_pos: srdiag/bpm/c09-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-09
x_pos: srdiag/bpm/c09-09/SA_HPosition
y_pos: srdiag/bpm/c09-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-10
x_pos: srdiag/bpm/c09-10/SA_HPosition
y_pos: srdiag/bpm/c09-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-01
x_pos: srdiag/bpm/c10-01/SA_HPosition
y_pos: srdiag/bpm/c10-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-02
x_pos: srdiag/bpm/c10-02/SA_HPosition
y_pos: srdiag/bpm/c10-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-03
x_pos: srdiag/bpm/c10-03/SA_HPosition
y_pos: srdiag/bpm/c10-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-04
x_pos: srdiag/bpm/c10-04/SA_HPosition
y_pos: srdiag/bpm/c10-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-05
x_pos: srdiag/bpm/c10-05/SA_HPosition
y_pos: srdiag/bpm/c10-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-06
x_pos: srdiag/bpm/c10-06/SA_HPosition
y_pos: srdiag/bpm/c10-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-07
x_pos: srdiag/bpm/c10-07/SA_HPosition
y_pos: srdiag/bpm/c10-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-08
x_pos: srdiag/bpm/c10-08/SA_HPosition
y_pos: srdiag/bpm/c10-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-09
x_pos: srdiag/bpm/c10-09/SA_HPosition
y_pos: srdiag/bpm/c10-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-10
x_pos: srdiag/bpm/c10-10/SA_HPosition
y_pos: srdiag/bpm/c10-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-01
x_pos: srdiag/bpm/c11-01/SA_HPosition
y_pos: srdiag/bpm/c11-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-02
x_pos: srdiag/bpm/c11-02/SA_HPosition
y_pos: srdiag/bpm/c11-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-03
x_pos: srdiag/bpm/c11-03/SA_HPosition
y_pos: srdiag/bpm/c11-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-04
x_pos: srdiag/bpm/c11-04/SA_HPosition
y_pos: srdiag/bpm/c11-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-05
x_pos: srdiag/bpm/c11-05/SA_HPosition
y_pos: srdiag/bpm/c11-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-06
x_pos: srdiag/bpm/c11-06/SA_HPosition
y_pos: srdiag/bpm/c11-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-07
x_pos: srdiag/bpm/c11-07/SA_HPosition
y_pos: srdiag/bpm/c11-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-08
x_pos: srdiag/bpm/c11-08/SA_HPosition
y_pos: srdiag/bpm/c11-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-09
x_pos: srdiag/bpm/c11-09/SA_HPosition
y_pos: srdiag/bpm/c11-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-10
x_pos: srdiag/bpm/c11-10/SA_HPosition
y_pos: srdiag/bpm/c11-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-01
x_pos: srdiag/bpm/c12-01/SA_HPosition
y_pos: srdiag/bpm/c12-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-02
x_pos: srdiag/bpm/c12-02/SA_HPosition
y_pos: srdiag/bpm/c12-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-03
x_pos: srdiag/bpm/c12-03/SA_HPosition
y_pos: srdiag/bpm/c12-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-04
x_pos: srdiag/bpm/c12-04/SA_HPosition
y_pos: srdiag/bpm/c12-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-05
x_pos: srdiag/bpm/c12-05/SA_HPosition
y_pos: srdiag/bpm/c12-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-06
x_pos: srdiag/bpm/c12-06/SA_HPosition
y_pos: srdiag/bpm/c12-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-07
x_pos: srdiag/bpm/c12-07/SA_HPosition
y_pos: srdiag/bpm/c12-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-08
x_pos: srdiag/bpm/c12-08/SA_HPosition
y_pos: srdiag/bpm/c12-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-09
x_pos: srdiag/bpm/c12-09/SA_HPosition
y_pos: srdiag/bpm/c12-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-10
x_pos: srdiag/bpm/c12-10/SA_HPosition
y_pos: srdiag/bpm/c12-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-01
x_pos: srdiag/bpm/c13-01/SA_HPosition
y_pos: srdiag/bpm/c13-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-02
x_pos: srdiag/bpm/c13-02/SA_HPosition
y_pos: srdiag/bpm/c13-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-03
x_pos: srdiag/bpm/c13-03/SA_HPosition
y_pos: srdiag/bpm/c13-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-04
x_pos: srdiag/bpm/c13-04/SA_HPosition
y_pos: srdiag/bpm/c13-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-05
x_pos: srdiag/bpm/c13-05/SA_HPosition
y_pos: srdiag/bpm/c13-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-06
x_pos: srdiag/bpm/c13-06/SA_HPosition
y_pos: srdiag/bpm/c13-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-07
x_pos: srdiag/bpm/c13-07/SA_HPosition
y_pos: srdiag/bpm/c13-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-08
x_pos: srdiag/bpm/c13-08/SA_HPosition
y_pos: srdiag/bpm/c13-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-09
x_pos: srdiag/bpm/c13-09/SA_HPosition
y_pos: srdiag/bpm/c13-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-10
x_pos: srdiag/bpm/c13-10/SA_HPosition
y_pos: srdiag/bpm/c13-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-01
x_pos: srdiag/bpm/c14-01/SA_HPosition
y_pos: srdiag/bpm/c14-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-02
x_pos: srdiag/bpm/c14-02/SA_HPosition
y_pos: srdiag/bpm/c14-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-03
x_pos: srdiag/bpm/c14-03/SA_HPosition
y_pos: srdiag/bpm/c14-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-04
x_pos: srdiag/bpm/c14-04/SA_HPosition
y_pos: srdiag/bpm/c14-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-05
x_pos: srdiag/bpm/c14-05/SA_HPosition
y_pos: srdiag/bpm/c14-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-06
x_pos: srdiag/bpm/c14-06/SA_HPosition
y_pos: srdiag/bpm/c14-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-07
x_pos: srdiag/bpm/c14-07/SA_HPosition
y_pos: srdiag/bpm/c14-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-08
x_pos: srdiag/bpm/c14-08/SA_HPosition
y_pos: srdiag/bpm/c14-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-09
x_pos: srdiag/bpm/c14-09/SA_HPosition
y_pos: srdiag/bpm/c14-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-10
x_pos: srdiag/bpm/c14-10/SA_HPosition
y_pos: srdiag/bpm/c14-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-01
x_pos: srdiag/bpm/c15-01/SA_HPosition
y_pos: srdiag/bpm/c15-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-02
x_pos: srdiag/bpm/c15-02/SA_HPosition
y_pos: srdiag/bpm/c15-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-03
x_pos: srdiag/bpm/c15-03/SA_HPosition
y_pos: srdiag/bpm/c15-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-04
x_pos: srdiag/bpm/c15-04/SA_HPosition
y_pos: srdiag/bpm/c15-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-05
x_pos: srdiag/bpm/c15-05/SA_HPosition
y_pos: srdiag/bpm/c15-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-06
x_pos: srdiag/bpm/c15-06/SA_HPosition
y_pos: srdiag/bpm/c15-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-07
x_pos: srdiag/bpm/c15-07/SA_HPosition
y_pos: srdiag/bpm/c15-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-08
x_pos: srdiag/bpm/c15-08/SA_HPosition
y_pos: srdiag/bpm/c15-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-09
x_pos: srdiag/bpm/c15-09/SA_HPosition
y_pos: srdiag/bpm/c15-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-10
x_pos: srdiag/bpm/c15-10/SA_HPosition
y_pos: srdiag/bpm/c15-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-01
x_pos: srdiag/bpm/c16-01/SA_HPosition
y_pos: srdiag/bpm/c16-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-02
x_pos: srdiag/bpm/c16-02/SA_HPosition
y_pos: srdiag/bpm/c16-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-03
x_pos: srdiag/bpm/c16-03/SA_HPosition
y_pos: srdiag/bpm/c16-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-04
x_pos: srdiag/bpm/c16-04/SA_HPosition
y_pos: srdiag/bpm/c16-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-05
x_pos: srdiag/bpm/c16-05/SA_HPosition
y_pos: srdiag/bpm/c16-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-06
x_pos: srdiag/bpm/c16-06/SA_HPosition
y_pos: srdiag/bpm/c16-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-07
x_pos: srdiag/bpm/c16-07/SA_HPosition
y_pos: srdiag/bpm/c16-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-08
x_pos: srdiag/bpm/c16-08/SA_HPosition
y_pos: srdiag/bpm/c16-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-09
x_pos: srdiag/bpm/c16-09/SA_HPosition
y_pos: srdiag/bpm/c16-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-10
x_pos: srdiag/bpm/c16-10/SA_HPosition
y_pos: srdiag/bpm/c16-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-01
x_pos: srdiag/bpm/c17-01/SA_HPosition
y_pos: srdiag/bpm/c17-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-02
x_pos: srdiag/bpm/c17-02/SA_HPosition
y_pos: srdiag/bpm/c17-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-03
x_pos: srdiag/bpm/c17-03/SA_HPosition
y_pos: srdiag/bpm/c17-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-04
x_pos: srdiag/bpm/c17-04/SA_HPosition
y_pos: srdiag/bpm/c17-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-05
x_pos: srdiag/bpm/c17-05/SA_HPosition
y_pos: srdiag/bpm/c17-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-06
x_pos: srdiag/bpm/c17-06/SA_HPosition
y_pos: srdiag/bpm/c17-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-07
x_pos: srdiag/bpm/c17-07/SA_HPosition
y_pos: srdiag/bpm/c17-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-08
x_pos: srdiag/bpm/c17-08/SA_HPosition
y_pos: srdiag/bpm/c17-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-09
x_pos: srdiag/bpm/c17-09/SA_HPosition
y_pos: srdiag/bpm/c17-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-10
x_pos: srdiag/bpm/c17-10/SA_HPosition
y_pos: srdiag/bpm/c17-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-01
x_pos: srdiag/bpm/c18-01/SA_HPosition
y_pos: srdiag/bpm/c18-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-02
x_pos: srdiag/bpm/c18-02/SA_HPosition
y_pos: srdiag/bpm/c18-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-03
x_pos: srdiag/bpm/c18-03/SA_HPosition
y_pos: srdiag/bpm/c18-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-04
x_pos: srdiag/bpm/c18-04/SA_HPosition
y_pos: srdiag/bpm/c18-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-05
x_pos: srdiag/bpm/c18-05/SA_HPosition
y_pos: srdiag/bpm/c18-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-06
x_pos: srdiag/bpm/c18-06/SA_HPosition
y_pos: srdiag/bpm/c18-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-07
x_pos: srdiag/bpm/c18-07/SA_HPosition
y_pos: srdiag/bpm/c18-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-08
x_pos: srdiag/bpm/c18-08/SA_HPosition
y_pos: srdiag/bpm/c18-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-09
x_pos: srdiag/bpm/c18-09/SA_HPosition
y_pos: srdiag/bpm/c18-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-10
x_pos: srdiag/bpm/c18-10/SA_HPosition
y_pos: srdiag/bpm/c18-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-01
x_pos: srdiag/bpm/c19-01/SA_HPosition
y_pos: srdiag/bpm/c19-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-02
x_pos: srdiag/bpm/c19-02/SA_HPosition
y_pos: srdiag/bpm/c19-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-03
x_pos: srdiag/bpm/c19-03/SA_HPosition
y_pos: srdiag/bpm/c19-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-04
x_pos: srdiag/bpm/c19-04/SA_HPosition
y_pos: srdiag/bpm/c19-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-05
x_pos: srdiag/bpm/c19-05/SA_HPosition
y_pos: srdiag/bpm/c19-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-06
x_pos: srdiag/bpm/c19-06/SA_HPosition
y_pos: srdiag/bpm/c19-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-07
x_pos: srdiag/bpm/c19-07/SA_HPosition
y_pos: srdiag/bpm/c19-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-08
x_pos: srdiag/bpm/c19-08/SA_HPosition
y_pos: srdiag/bpm/c19-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-09
x_pos: srdiag/bpm/c19-09/SA_HPosition
y_pos: srdiag/bpm/c19-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-10
x_pos: srdiag/bpm/c19-10/SA_HPosition
y_pos: srdiag/bpm/c19-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-01
x_pos: srdiag/bpm/c20-01/SA_HPosition
y_pos: srdiag/bpm/c20-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-02
x_pos: srdiag/bpm/c20-02/SA_HPosition
y_pos: srdiag/bpm/c20-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-03
x_pos: srdiag/bpm/c20-03/SA_HPosition
y_pos: srdiag/bpm/c20-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-04
x_pos: srdiag/bpm/c20-04/SA_HPosition
y_pos: srdiag/bpm/c20-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-05
x_pos: srdiag/bpm/c20-05/SA_HPosition
y_pos: srdiag/bpm/c20-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-06
x_pos: srdiag/bpm/c20-06/SA_HPosition
y_pos: srdiag/bpm/c20-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-07
x_pos: srdiag/bpm/c20-07/SA_HPosition
y_pos: srdiag/bpm/c20-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-08
x_pos: srdiag/bpm/c20-08/SA_HPosition
y_pos: srdiag/bpm/c20-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-09
x_pos: srdiag/bpm/c20-09/SA_HPosition
y_pos: srdiag/bpm/c20-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-10
x_pos: srdiag/bpm/c20-10/SA_HPosition
y_pos: srdiag/bpm/c20-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-01
x_pos: srdiag/bpm/c21-01/SA_HPosition
y_pos: srdiag/bpm/c21-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-02
x_pos: srdiag/bpm/c21-02/SA_HPosition
y_pos: srdiag/bpm/c21-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-03
x_pos: srdiag/bpm/c21-03/SA_HPosition
y_pos: srdiag/bpm/c21-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-04
x_pos: srdiag/bpm/c21-04/SA_HPosition
y_pos: srdiag/bpm/c21-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-05
x_pos: srdiag/bpm/c21-05/SA_HPosition
y_pos: srdiag/bpm/c21-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-06
x_pos: srdiag/bpm/c21-06/SA_HPosition
y_pos: srdiag/bpm/c21-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-07
x_pos: srdiag/bpm/c21-07/SA_HPosition
y_pos: srdiag/bpm/c21-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-08
x_pos: srdiag/bpm/c21-08/SA_HPosition
y_pos: srdiag/bpm/c21-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-09
x_pos: srdiag/bpm/c21-09/SA_HPosition
y_pos: srdiag/bpm/c21-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-10
x_pos: srdiag/bpm/c21-10/SA_HPosition
y_pos: srdiag/bpm/c21-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-01
x_pos: srdiag/bpm/c22-01/SA_HPosition
y_pos: srdiag/bpm/c22-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-02
x_pos: srdiag/bpm/c22-02/SA_HPosition
y_pos: srdiag/bpm/c22-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-03
x_pos: srdiag/bpm/c22-03/SA_HPosition
y_pos: srdiag/bpm/c22-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-04
x_pos: srdiag/bpm/c22-04/SA_HPosition
y_pos: srdiag/bpm/c22-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-05
x_pos: srdiag/bpm/c22-05/SA_HPosition
y_pos: srdiag/bpm/c22-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-06
x_pos: srdiag/bpm/c22-06/SA_HPosition
y_pos: srdiag/bpm/c22-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-07
x_pos: srdiag/bpm/c22-07/SA_HPosition
y_pos: srdiag/bpm/c22-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-08
x_pos: srdiag/bpm/c22-08/SA_HPosition
y_pos: srdiag/bpm/c22-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-09
x_pos: srdiag/bpm/c22-09/SA_HPosition
y_pos: srdiag/bpm/c22-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-10
x_pos: srdiag/bpm/c22-10/SA_HPosition
y_pos: srdiag/bpm/c22-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-01
x_pos: srdiag/bpm/c23-01/SA_HPosition
y_pos: srdiag/bpm/c23-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-02
x_pos: srdiag/bpm/c23-02/SA_HPosition
y_pos: srdiag/bpm/c23-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-03
x_pos: srdiag/bpm/c23-03/SA_HPosition
y_pos: srdiag/bpm/c23-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-04
x_pos: srdiag/bpm/c23-04/SA_HPosition
y_pos: srdiag/bpm/c23-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-05
x_pos: srdiag/bpm/c23-05/SA_HPosition
y_pos: srdiag/bpm/c23-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-06
x_pos: srdiag/bpm/c23-06/SA_HPosition
y_pos: srdiag/bpm/c23-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-07
x_pos: srdiag/bpm/c23-07/SA_HPosition
y_pos: srdiag/bpm/c23-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-08
x_pos: srdiag/bpm/c23-08/SA_HPosition
y_pos: srdiag/bpm/c23-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-09
x_pos: srdiag/bpm/c23-09/SA_HPosition
y_pos: srdiag/bpm/c23-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-10
x_pos: srdiag/bpm/c23-10/SA_HPosition
y_pos: srdiag/bpm/c23-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-01
x_pos: srdiag/bpm/c24-01/SA_HPosition
y_pos: srdiag/bpm/c24-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-02
x_pos: srdiag/bpm/c24-02/SA_HPosition
y_pos: srdiag/bpm/c24-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-03
x_pos: srdiag/bpm/c24-03/SA_HPosition
y_pos: srdiag/bpm/c24-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-04
x_pos: srdiag/bpm/c24-04/SA_HPosition
y_pos: srdiag/bpm/c24-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-05
x_pos: srdiag/bpm/c24-05/SA_HPosition
y_pos: srdiag/bpm/c24-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-06
x_pos: srdiag/bpm/c24-06/SA_HPosition
y_pos: srdiag/bpm/c24-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-07
x_pos: srdiag/bpm/c24-07/SA_HPosition
y_pos: srdiag/bpm/c24-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-08
x_pos: srdiag/bpm/c24-08/SA_HPosition
y_pos: srdiag/bpm/c24-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-09
x_pos: srdiag/bpm/c24-09/SA_HPosition
y_pos: srdiag/bpm/c24-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-10
x_pos: srdiag/bpm/c24-10/SA_HPosition
y_pos: srdiag/bpm/c24-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-01
x_pos: srdiag/bpm/c25-01/SA_HPosition
y_pos: srdiag/bpm/c25-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-02
x_pos: srdiag/bpm/c25-02/SA_HPosition
y_pos: srdiag/bpm/c25-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-03
x_pos: srdiag/bpm/c25-03/SA_HPosition
y_pos: srdiag/bpm/c25-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-04
x_pos: srdiag/bpm/c25-04/SA_HPosition
y_pos: srdiag/bpm/c25-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-05
x_pos: srdiag/bpm/c25-05/SA_HPosition
y_pos: srdiag/bpm/c25-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-06
x_pos: srdiag/bpm/c25-06/SA_HPosition
y_pos: srdiag/bpm/c25-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-07
x_pos: srdiag/bpm/c25-07/SA_HPosition
y_pos: srdiag/bpm/c25-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-08
x_pos: srdiag/bpm/c25-08/SA_HPosition
y_pos: srdiag/bpm/c25-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-09
x_pos: srdiag/bpm/c25-09/SA_HPosition
y_pos: srdiag/bpm/c25-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-10
x_pos: srdiag/bpm/c25-10/SA_HPosition
y_pos: srdiag/bpm/c25-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-01
x_pos: srdiag/bpm/c26-01/SA_HPosition
y_pos: srdiag/bpm/c26-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-02
x_pos: srdiag/bpm/c26-02/SA_HPosition
y_pos: srdiag/bpm/c26-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-03
x_pos: srdiag/bpm/c26-03/SA_HPosition
y_pos: srdiag/bpm/c26-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-04
x_pos: srdiag/bpm/c26-04/SA_HPosition
y_pos: srdiag/bpm/c26-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-05
x_pos: srdiag/bpm/c26-05/SA_HPosition
y_pos: srdiag/bpm/c26-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-06
x_pos: srdiag/bpm/c26-06/SA_HPosition
y_pos: srdiag/bpm/c26-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-07
x_pos: srdiag/bpm/c26-07/SA_HPosition
y_pos: srdiag/bpm/c26-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-08
x_pos: srdiag/bpm/c26-08/SA_HPosition
y_pos: srdiag/bpm/c26-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-09
x_pos: srdiag/bpm/c26-09/SA_HPosition
y_pos: srdiag/bpm/c26-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-10
x_pos: srdiag/bpm/c26-10/SA_HPosition
y_pos: srdiag/bpm/c26-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-01
x_pos: srdiag/bpm/c27-01/SA_HPosition
y_pos: srdiag/bpm/c27-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-02
x_pos: srdiag/bpm/c27-02/SA_HPosition
y_pos: srdiag/bpm/c27-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-03
x_pos: srdiag/bpm/c27-03/SA_HPosition
y_pos: srdiag/bpm/c27-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-04
x_pos: srdiag/bpm/c27-04/SA_HPosition
y_pos: srdiag/bpm/c27-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-05
x_pos: srdiag/bpm/c27-05/SA_HPosition
y_pos: srdiag/bpm/c27-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-06
x_pos: srdiag/bpm/c27-06/SA_HPosition
y_pos: srdiag/bpm/c27-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-07
x_pos: srdiag/bpm/c27-07/SA_HPosition
y_pos: srdiag/bpm/c27-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-08
x_pos: srdiag/bpm/c27-08/SA_HPosition
y_pos: srdiag/bpm/c27-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-09
x_pos: srdiag/bpm/c27-09/SA_HPosition
y_pos: srdiag/bpm/c27-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-10
x_pos: srdiag/bpm/c27-10/SA_HPosition
y_pos: srdiag/bpm/c27-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-01
x_pos: srdiag/bpm/c28-01/SA_HPosition
y_pos: srdiag/bpm/c28-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-02
x_pos: srdiag/bpm/c28-02/SA_HPosition
y_pos: srdiag/bpm/c28-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-03
x_pos: srdiag/bpm/c28-03/SA_HPosition
y_pos: srdiag/bpm/c28-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-04
x_pos: srdiag/bpm/c28-04/SA_HPosition
y_pos: srdiag/bpm/c28-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-05
x_pos: srdiag/bpm/c28-05/SA_HPosition
y_pos: srdiag/bpm/c28-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-06
x_pos: srdiag/bpm/c28-06/SA_HPosition
y_pos: srdiag/bpm/c28-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-07
x_pos: srdiag/bpm/c28-07/SA_HPosition
y_pos: srdiag/bpm/c28-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-08
x_pos: srdiag/bpm/c28-08/SA_HPosition
y_pos: srdiag/bpm/c28-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-09
x_pos: srdiag/bpm/c28-09/SA_HPosition
y_pos: srdiag/bpm/c28-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-10
x_pos: srdiag/bpm/c28-10/SA_HPosition
y_pos: srdiag/bpm/c28-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-01
x_pos: srdiag/bpm/c29-01/SA_HPosition
y_pos: srdiag/bpm/c29-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-02
x_pos: srdiag/bpm/c29-02/SA_HPosition
y_pos: srdiag/bpm/c29-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-03
x_pos: srdiag/bpm/c29-03/SA_HPosition
y_pos: srdiag/bpm/c29-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-04
x_pos: srdiag/bpm/c29-04/SA_HPosition
y_pos: srdiag/bpm/c29-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-05
x_pos: srdiag/bpm/c29-05/SA_HPosition
y_pos: srdiag/bpm/c29-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-06
x_pos: srdiag/bpm/c29-06/SA_HPosition
y_pos: srdiag/bpm/c29-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-07
x_pos: srdiag/bpm/c29-07/SA_HPosition
y_pos: srdiag/bpm/c29-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-08
x_pos: srdiag/bpm/c29-08/SA_HPosition
y_pos: srdiag/bpm/c29-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-09
x_pos: srdiag/bpm/c29-09/SA_HPosition
y_pos: srdiag/bpm/c29-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-10
x_pos: srdiag/bpm/c29-10/SA_HPosition
y_pos: srdiag/bpm/c29-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-01
x_pos: srdiag/bpm/c30-01/SA_HPosition
y_pos: srdiag/bpm/c30-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-02
x_pos: srdiag/bpm/c30-02/SA_HPosition
y_pos: srdiag/bpm/c30-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-03
x_pos: srdiag/bpm/c30-03/SA_HPosition
y_pos: srdiag/bpm/c30-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-04
x_pos: srdiag/bpm/c30-04/SA_HPosition
y_pos: srdiag/bpm/c30-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-05
x_pos: srdiag/bpm/c30-05/SA_HPosition
y_pos: srdiag/bpm/c30-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-06
x_pos: srdiag/bpm/c30-06/SA_HPosition
y_pos: srdiag/bpm/c30-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-07
x_pos: srdiag/bpm/c30-07/SA_HPosition
y_pos: srdiag/bpm/c30-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-08
x_pos: srdiag/bpm/c30-08/SA_HPosition
y_pos: srdiag/bpm/c30-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-09
x_pos: srdiag/bpm/c30-09/SA_HPosition
y_pos: srdiag/bpm/c30-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-10
x_pos: srdiag/bpm/c30-10/SA_HPosition
y_pos: srdiag/bpm/c30-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-01
x_pos: srdiag/bpm/c31-01/SA_HPosition
y_pos: srdiag/bpm/c31-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-02
x_pos: srdiag/bpm/c31-02/SA_HPosition
y_pos: srdiag/bpm/c31-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-03
x_pos: srdiag/bpm/c31-03/SA_HPosition
y_pos: srdiag/bpm/c31-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-04
x_pos: srdiag/bpm/c31-04/SA_HPosition
y_pos: srdiag/bpm/c31-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-05
x_pos: srdiag/bpm/c31-05/SA_HPosition
y_pos: srdiag/bpm/c31-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-06
x_pos: srdiag/bpm/c31-06/SA_HPosition
y_pos: srdiag/bpm/c31-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-07
x_pos: srdiag/bpm/c31-07/SA_HPosition
y_pos: srdiag/bpm/c31-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-08
x_pos: srdiag/bpm/c31-08/SA_HPosition
y_pos: srdiag/bpm/c31-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-09
x_pos: srdiag/bpm/c31-09/SA_HPosition
y_pos: srdiag/bpm/c31-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-10
x_pos: srdiag/bpm/c31-10/SA_HPosition
y_pos: srdiag/bpm/c31-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-01
x_pos: srdiag/bpm/c32-01/SA_HPosition
y_pos: srdiag/bpm/c32-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-02
x_pos: srdiag/bpm/c32-02/SA_HPosition
y_pos: srdiag/bpm/c32-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-03
x_pos: srdiag/bpm/c32-03/SA_HPosition
y_pos: srdiag/bpm/c32-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-04
x_pos: srdiag/bpm/c32-04/SA_HPosition
y_pos: srdiag/bpm/c32-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-05
x_pos: srdiag/bpm/c32-05/SA_HPosition
y_pos: srdiag/bpm/c32-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-06
x_pos: srdiag/bpm/c32-06/SA_HPosition
y_pos: srdiag/bpm/c32-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-07
x_pos: srdiag/bpm/c32-07/SA_HPosition
y_pos: srdiag/bpm/c32-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-08
x_pos: srdiag/bpm/c32-08/SA_HPosition
y_pos: srdiag/bpm/c32-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-09
x_pos: srdiag/bpm/c32-09/SA_HPosition
y_pos: srdiag/bpm/c32-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-10
x_pos: srdiag/bpm/c32-10/SA_HPosition
y_pos: srdiag/bpm/c32-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-01
x_pos: srdiag/bpm/c01-01/SA_HPosition
y_pos: srdiag/bpm/c01-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-02
x_pos: srdiag/bpm/c01-02/SA_HPosition
y_pos: srdiag/bpm/c01-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-03
x_pos: srdiag/bpm/c01-03/SA_HPosition
y_pos: srdiag/bpm/c01-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-04
x_pos: srdiag/bpm/c01-04/SA_HPosition
y_pos: srdiag/bpm/c01-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-05
x_pos: srdiag/bpm/c01-05/SA_HPosition
y_pos: srdiag/bpm/c01-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-06
x_pos: srdiag/bpm/c01-06/SA_HPosition
y_pos: srdiag/bpm/c01-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-07
x_pos: srdiag/bpm/c01-07/SA_HPosition
y_pos: srdiag/bpm/c01-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-08
x_pos: srdiag/bpm/c01-08/SA_HPosition
y_pos: srdiag/bpm/c01-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-09
x_pos: srdiag/bpm/c01-09/SA_HPosition
y_pos: srdiag/bpm/c01-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-10
x_pos: srdiag/bpm/c01-10/SA_HPosition
y_pos: srdiag/bpm/c01-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-01
x_pos: srdiag/bpm/c02-01/SA_HPosition
y_pos: srdiag/bpm/c02-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-02
x_pos: srdiag/bpm/c02-02/SA_HPosition
y_pos: srdiag/bpm/c02-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-03
x_pos: srdiag/bpm/c02-03/SA_HPosition
y_pos: srdiag/bpm/c02-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-04
x_pos: srdiag/bpm/c02-04/SA_HPosition
y_pos: srdiag/bpm/c02-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-05
x_pos: srdiag/bpm/c02-05/SA_HPosition
y_pos: srdiag/bpm/c02-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-06
x_pos: srdiag/bpm/c02-06/SA_HPosition
y_pos: srdiag/bpm/c02-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-07
x_pos: srdiag/bpm/c02-07/SA_HPosition
y_pos: srdiag/bpm/c02-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-08
x_pos: srdiag/bpm/c02-08/SA_HPosition
y_pos: srdiag/bpm/c02-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-09
x_pos: srdiag/bpm/c02-09/SA_HPosition
y_pos: srdiag/bpm/c02-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-10
x_pos: srdiag/bpm/c02-10/SA_HPosition
y_pos: srdiag/bpm/c02-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-01
x_pos: srdiag/bpm/c03-01/SA_HPosition
y_pos: srdiag/bpm/c03-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-02
x_pos: srdiag/bpm/c03-02/SA_HPosition
y_pos: srdiag/bpm/c03-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-03
x_pos: srdiag/bpm/c03-03/SA_HPosition
y_pos: srdiag/bpm/c03-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-04
x_pos: srdiag/bpm/c03-04/SA_HPosition
y_pos: srdiag/bpm/c03-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-05
x_pos: srdiag/bpm/c03-05/SA_HPosition
y_pos: srdiag/bpm/c03-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-06
x_pos: srdiag/bpm/c03-06/SA_HPosition
y_pos: srdiag/bpm/c03-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-07
x_pos: srdiag/bpm/c03-07/SA_HPosition
y_pos: srdiag/bpm/c03-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-08
x_pos: srdiag/bpm/c03-08/SA_HPosition
y_pos: srdiag/bpm/c03-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-09
x_pos: srdiag/bpm/c03-09/SA_HPosition
y_pos: srdiag/bpm/c03-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-10
x_pos: srdiag/bpm/c03-10/SA_HPosition
y_pos: srdiag/bpm/c03-10/SA_VPosition
diff --git a/examples/use_cases/config/soleil_ii/devices.yaml b/examples/use_cases/config/soleil_ii/devices.yaml
index e75b0954a..c19b50ada 100644
--- a/examples/use_cases/config/soleil_ii/devices.yaml
+++ b/examples/use_cases/config/soleil_ii/devices.yaml
@@ -1,4 +1,4 @@
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_001
x_pos: AN01-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN01-SD/DG-EPOS/BPM.02/y_pos
@@ -54,7 +54,7 @@
physics:
- AN01-AR/EM-OCT/OH.02/strength
- AN01-AR/EM-COR/OH.02-CQLN.02/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_002
x_pos: AN01-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.03/y_pos
@@ -108,7 +108,7 @@
physics:
- AN01-AR/EM-SX/SCF.02/strength
- AN01-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_003
x_pos: AN01-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.04/y_pos
@@ -168,7 +168,7 @@
physics:
- AN01-AR/EM-SX/SCF.05/strength
- AN01-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_004
x_pos: AN01-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.05/y_pos
@@ -228,7 +228,7 @@
physics:
- AN01-AR/EM-SX/SCF.08/strength
- AN01-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_005
x_pos: AN01-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.06/y_pos
@@ -288,7 +288,7 @@
- AN01-AR/EM-OCT/OC.04/strength
- AN01-AR/EM-COR/OC.04-CQLN.13/strength
- AN01-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_006
x_pos: AN01-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.07/y_pos
@@ -348,7 +348,7 @@
- AN01-AR/EM-OCT/OC.05/strength
- AN01-AR/EM-COR/OC.05-CQLN.16/strength
- AN01-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_007
x_pos: AN01-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.08/y_pos
@@ -420,7 +420,7 @@
physics:
- AN01-AR/EM-SX/SCD.18/strength
- AN01-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_008
x_pos: AN01-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.09/y_pos
@@ -462,7 +462,7 @@
physics:
- AN01-AR/EM-OCT/OH.03/strength
- AN01-AR/EM-COR/OH.03-CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_009
x_pos: AN01-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN01-AR/DG-EPOS/BPM.10/y_pos
@@ -494,11 +494,11 @@
- AN01-AR/EM-OCT/OH.04/strength
- AN01-AR/EM-COR/OH.04-CQLN.22/strength
- AN01-AR/EM-COR/OH.04-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_010
x_pos: AN02-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN02-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_011
x_pos: AN02-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN02-SD/DG-EPOS/BPM.02/y_pos
@@ -530,7 +530,7 @@
- AN02-AR/EM-SX/SHF.01/strength
- AN02-AR/EM-COR/SHF.01-CDLH.01/strength
- AN02-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_012
x_pos: AN02-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN02-AR/DG-EPOS/BPM.03/y_pos
@@ -604,7 +604,7 @@
physics:
- AN02-AR/EM-SX/SCF.02/strength
- AN02-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_013
x_pos: AN02-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN02-AR/DG-EPOS/BPM.04/y_pos
@@ -664,7 +664,7 @@
physics:
- AN02-AR/EM-SX/SCF.05/strength
- AN02-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_014
x_pos: AN02-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN02-AR/DG-EPOS/BPM.05/y_pos
@@ -736,7 +736,7 @@
physics:
- AN02-AR/EM-SX/SCD.09/strength
- AN02-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_015
x_pos: AN02-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN02-AR/DG-EPOS/BPM.06/y_pos
@@ -772,7 +772,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN02-AR/EM-COR/CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_016
x_pos: AN02-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN02-AR/DG-EPOS/BPM.07/y_pos
@@ -804,11 +804,11 @@
- AN02-AR/EM-OCT/OH.03/strength
- AN02-AR/EM-COR/OH.03-CQLN.13/strength
- AN02-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_017
x_pos: AN03-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN03-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_018
x_pos: AN03-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN03-SD/DG-EPOS/BPM.02/y_pos
@@ -840,7 +840,7 @@
- AN03-AR/EM-SX/SHF.01/strength
- AN03-AR/EM-COR/SHF.01-CDLH.01/strength
- AN03-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_019
x_pos: AN03-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.03/y_pos
@@ -908,7 +908,7 @@
physics:
- AN03-AR/EM-SX/SCF.02/strength
- AN03-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_020
x_pos: AN03-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.04/y_pos
@@ -968,7 +968,7 @@
physics:
- AN03-AR/EM-SX/SCF.05/strength
- AN03-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_021
x_pos: AN03-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.05/y_pos
@@ -1028,7 +1028,7 @@
physics:
- AN03-AR/EM-SX/SCF.08/strength
- AN03-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_022
x_pos: AN03-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.06/y_pos
@@ -1088,7 +1088,7 @@
- AN03-AR/EM-OCT/OC.04/strength
- AN03-AR/EM-COR/OC.04-CQLN.13/strength
- AN03-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_023
x_pos: AN03-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.07/y_pos
@@ -1148,7 +1148,7 @@
- AN03-AR/EM-OCT/OC.05/strength
- AN03-AR/EM-COR/OC.05-CQLN.16/strength
- AN03-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_024
x_pos: AN03-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.08/y_pos
@@ -1220,7 +1220,7 @@
physics:
- AN03-AR/EM-SX/SCD.18/strength
- AN03-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_025
x_pos: AN03-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.09/y_pos
@@ -1256,7 +1256,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN03-AR/EM-COR/CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_026
x_pos: AN03-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN03-AR/DG-EPOS/BPM.10/y_pos
@@ -1288,11 +1288,11 @@
- AN03-AR/EM-OCT/OH.02/strength
- AN03-AR/EM-COR/OH.02-CQLN.22/strength
- AN03-AR/EM-COR/OH.02-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_027
x_pos: AN04-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN04-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_028
x_pos: AN04-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN04-SD/DG-EPOS/BPM.02/y_pos
@@ -1324,7 +1324,7 @@
- AN04-AR/EM-SX/SHF.01/strength
- AN04-AR/EM-COR/SHF.01-CDLH.01/strength
- AN04-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_029
x_pos: AN04-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN04-AR/DG-EPOS/BPM.03/y_pos
@@ -1392,7 +1392,7 @@
physics:
- AN04-AR/EM-SX/SCF.02/strength
- AN04-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_030
x_pos: AN04-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN04-AR/DG-EPOS/BPM.04/y_pos
@@ -1452,7 +1452,7 @@
- AN04-AR/EM-OCT/OC.02/strength
- AN04-AR/EM-COR/OC.02-CQLN.07/strength
- AN04-AR/EM-COR/OC.02-CQLT.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_031
x_pos: AN04-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN04-AR/DG-EPOS/BPM.05/y_pos
@@ -1524,7 +1524,7 @@
physics:
- AN04-AR/EM-SX/SCD.09/strength
- AN04-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_032
x_pos: AN04-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN04-AR/DG-EPOS/BPM.06/y_pos
@@ -1566,7 +1566,7 @@
physics:
- AN04-AR/EM-OCT/OH.02/strength
- AN04-AR/EM-COR/OH.02-CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_033
x_pos: AN04-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN04-AR/DG-EPOS/BPM.07/y_pos
@@ -1598,11 +1598,11 @@
- AN04-AR/EM-OCT/OH.03/strength
- AN04-AR/EM-COR/OH.03-CQLN.13/strength
- AN04-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_034
x_pos: AN05-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN05-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_035
x_pos: AN05-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN05-SD/DG-EPOS/BPM.02/y_pos
@@ -1634,7 +1634,7 @@
- AN05-AR/EM-SX/SHF.01/strength
- AN05-AR/EM-COR/SHF.01-CDLH.01/strength
- AN05-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_036
x_pos: AN05-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.03/y_pos
@@ -1708,7 +1708,7 @@
physics:
- AN05-AR/EM-SX/SCF.02/strength
- AN05-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_037
x_pos: AN05-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.04/y_pos
@@ -1768,7 +1768,7 @@
physics:
- AN05-AR/EM-SX/SCF.05/strength
- AN05-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_038
x_pos: AN05-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.05/y_pos
@@ -1828,7 +1828,7 @@
physics:
- AN05-AR/EM-SX/SCF.08/strength
- AN05-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_039
x_pos: AN05-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.06/y_pos
@@ -1888,7 +1888,7 @@
- AN05-AR/EM-OCT/OC.04/strength
- AN05-AR/EM-COR/OC.04-CQLN.13/strength
- AN05-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_040
x_pos: AN05-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.07/y_pos
@@ -1948,7 +1948,7 @@
- AN05-AR/EM-OCT/OC.05/strength
- AN05-AR/EM-COR/OC.05-CQLN.16/strength
- AN05-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_041
x_pos: AN05-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.08/y_pos
@@ -2020,7 +2020,7 @@
physics:
- AN05-AR/EM-SX/SCD.18/strength
- AN05-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_042
x_pos: AN05-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.09/y_pos
@@ -2042,7 +2042,7 @@
physics:
- AN05-AR/EM-SX/SHD.04/strength
- AN05-AR/EM-COR/SHD.04-CDLV.09/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_043
x_pos: AN05-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN05-AR/DG-EPOS/BPM.10/y_pos
@@ -2098,11 +2098,11 @@
- AN05-AR/EM-OCT/OH.04/strength
- AN05-AR/EM-COR/OH.04-CQLN.22/strength
- AN05-AR/EM-COR/OH.04-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_044
x_pos: AN06-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN06-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_045
x_pos: AN06-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN06-SD/DG-EPOS/BPM.02/y_pos
@@ -2158,11 +2158,11 @@
physics:
- AN06-SD/EM-OCT/OH.02/strength
- AN06-SD/EM-COR/OH.02-CQLN.02/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_046
x_pos: AN06-SD/DG-EPOS/BPM.03/x_pos
y_pos: AN06-SD/DG-EPOS/BPM.03/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_047
x_pos: AN06-SD/DG-EPOS/BPM.04/x_pos
y_pos: AN06-SD/DG-EPOS/BPM.04/y_pos
@@ -2218,7 +2218,7 @@
physics:
- AN06-AR/EM-SX/SHD.02/strength
- AN06-AR/EM-COR/SHD.02-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_048
x_pos: AN06-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.05/y_pos
@@ -2272,7 +2272,7 @@
physics:
- AN06-AR/EM-SX/SCF.02/strength
- AN06-AR/EM-COR/SCF.02-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_049
x_pos: AN06-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.06/y_pos
@@ -2332,7 +2332,7 @@
physics:
- AN06-AR/EM-SX/SCF.05/strength
- AN06-AR/EM-COR/SCF.05-CDLH.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_050
x_pos: AN06-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.07/y_pos
@@ -2392,7 +2392,7 @@
physics:
- AN06-AR/EM-SX/SCF.08/strength
- AN06-AR/EM-COR/SCF.08-CDLH.07/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_051
x_pos: AN06-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.08/y_pos
@@ -2452,7 +2452,7 @@
- AN06-AR/EM-OCT/OC.04/strength
- AN06-AR/EM-COR/OC.04-CQLN.13/strength
- AN06-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_052
x_pos: AN06-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.09/y_pos
@@ -2512,7 +2512,7 @@
- AN06-AR/EM-OCT/OC.05/strength
- AN06-AR/EM-COR/OC.05-CQLN.16/strength
- AN06-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_053
x_pos: AN06-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.10/y_pos
@@ -2584,7 +2584,7 @@
physics:
- AN06-AR/EM-SX/SCD.18/strength
- AN06-AR/EM-COR/SCD.18-CDLV.10/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_054
x_pos: AN06-AR/DG-EPOS/BPM.11/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.11/y_pos
@@ -2626,7 +2626,7 @@
physics:
- AN06-AR/EM-OCT/OH.03/strength
- AN06-AR/EM-COR/OH.03-CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_055
x_pos: AN06-AR/DG-EPOS/BPM.12/x_pos
y_pos: AN06-AR/DG-EPOS/BPM.12/y_pos
@@ -2658,11 +2658,11 @@
- AN06-AR/EM-OCT/OH.04/strength
- AN06-AR/EM-COR/OH.04-CQLN.22/strength
- AN06-AR/EM-COR/OH.04-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_056
x_pos: AN07-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN07-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_057
x_pos: AN07-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN07-SD/DG-EPOS/BPM.02/y_pos
@@ -2694,7 +2694,7 @@
- AN07-AR/EM-SX/SHF.01/strength
- AN07-AR/EM-COR/SHF.01-CDLH.01/strength
- AN07-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_058
x_pos: AN07-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN07-AR/DG-EPOS/BPM.03/y_pos
@@ -2768,7 +2768,7 @@
physics:
- AN07-AR/EM-SX/SCF.02/strength
- AN07-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_059
x_pos: AN07-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN07-AR/DG-EPOS/BPM.04/y_pos
@@ -2828,7 +2828,7 @@
physics:
- AN07-AR/EM-SX/SCF.05/strength
- AN07-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_060
x_pos: AN07-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN07-AR/DG-EPOS/BPM.05/y_pos
@@ -2900,7 +2900,7 @@
physics:
- AN07-AR/EM-SX/SCD.09/strength
- AN07-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_061
x_pos: AN07-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN07-AR/DG-EPOS/BPM.06/y_pos
@@ -2936,7 +2936,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN07-AR/EM-COR/CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_062
x_pos: AN07-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN07-AR/DG-EPOS/BPM.07/y_pos
@@ -2968,11 +2968,11 @@
- AN07-AR/EM-OCT/OH.03/strength
- AN07-AR/EM-COR/OH.03-CQLN.13/strength
- AN07-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_063
x_pos: AN08-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN08-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_064
x_pos: AN08-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN08-SD/DG-EPOS/BPM.02/y_pos
@@ -3004,7 +3004,7 @@
- AN08-AR/EM-SX/SHF.01/strength
- AN08-AR/EM-COR/SHF.01-CDLH.01/strength
- AN08-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_065
x_pos: AN08-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.03/y_pos
@@ -3072,7 +3072,7 @@
physics:
- AN08-AR/EM-SX/SCF.02/strength
- AN08-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_066
x_pos: AN08-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.04/y_pos
@@ -3132,7 +3132,7 @@
physics:
- AN08-AR/EM-SX/SCF.05/strength
- AN08-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_067
x_pos: AN08-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.05/y_pos
@@ -3192,7 +3192,7 @@
physics:
- AN08-AR/EM-SX/SCF.08/strength
- AN08-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_068
x_pos: AN08-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.06/y_pos
@@ -3252,7 +3252,7 @@
- AN08-AR/EM-OCT/OC.04/strength
- AN08-AR/EM-COR/OC.04-CQLN.13/strength
- AN08-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_069
x_pos: AN08-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.07/y_pos
@@ -3312,7 +3312,7 @@
- AN08-AR/EM-OCT/OC.05/strength
- AN08-AR/EM-COR/OC.05-CQLN.16/strength
- AN08-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_070
x_pos: AN08-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.08/y_pos
@@ -3384,7 +3384,7 @@
physics:
- AN08-AR/EM-SX/SCD.18/strength
- AN08-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_071
x_pos: AN08-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.09/y_pos
@@ -3420,7 +3420,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN08-AR/EM-COR/CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_072
x_pos: AN08-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN08-AR/DG-EPOS/BPM.10/y_pos
@@ -3452,11 +3452,11 @@
- AN08-AR/EM-OCT/OH.02/strength
- AN08-AR/EM-COR/OH.02-CQLN.22/strength
- AN08-AR/EM-COR/OH.02-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_073
x_pos: AN09-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN09-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_074
x_pos: AN09-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN09-SD/DG-EPOS/BPM.02/y_pos
@@ -3488,7 +3488,7 @@
- AN09-AR/EM-SX/SHF.01/strength
- AN09-AR/EM-COR/SHF.01-CDLH.01/strength
- AN09-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_075
x_pos: AN09-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN09-AR/DG-EPOS/BPM.03/y_pos
@@ -3556,7 +3556,7 @@
physics:
- AN09-AR/EM-SX/SCF.02/strength
- AN09-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_076
x_pos: AN09-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN09-AR/DG-EPOS/BPM.04/y_pos
@@ -3616,7 +3616,7 @@
- AN09-AR/EM-OCT/OC.02/strength
- AN09-AR/EM-COR/OC.02-CQLN.07/strength
- AN09-AR/EM-COR/OC.02-CQLT.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_077
x_pos: AN09-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN09-AR/DG-EPOS/BPM.05/y_pos
@@ -3688,7 +3688,7 @@
physics:
- AN09-AR/EM-SX/SCD.09/strength
- AN09-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_078
x_pos: AN09-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN09-AR/DG-EPOS/BPM.06/y_pos
@@ -3730,7 +3730,7 @@
physics:
- AN09-AR/EM-OCT/OH.02/strength
- AN09-AR/EM-COR/OH.02-CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_079
x_pos: AN09-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN09-AR/DG-EPOS/BPM.07/y_pos
@@ -3762,11 +3762,11 @@
- AN09-AR/EM-OCT/OH.03/strength
- AN09-AR/EM-COR/OH.03-CQLN.13/strength
- AN09-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_080
x_pos: AN10-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN10-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_081
x_pos: AN10-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN10-SD/DG-EPOS/BPM.02/y_pos
@@ -3798,7 +3798,7 @@
- AN10-AR/EM-SX/SHF.01/strength
- AN10-AR/EM-COR/SHF.01-CDLH.01/strength
- AN10-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_082
x_pos: AN10-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.03/y_pos
@@ -3872,7 +3872,7 @@
physics:
- AN10-AR/EM-SX/SCF.02/strength
- AN10-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_083
x_pos: AN10-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.04/y_pos
@@ -3932,7 +3932,7 @@
physics:
- AN10-AR/EM-SX/SCF.05/strength
- AN10-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_084
x_pos: AN10-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.05/y_pos
@@ -3992,7 +3992,7 @@
physics:
- AN10-AR/EM-SX/SCF.08/strength
- AN10-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_085
x_pos: AN10-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.06/y_pos
@@ -4052,7 +4052,7 @@
- AN10-AR/EM-OCT/OC.04/strength
- AN10-AR/EM-COR/OC.04-CQLN.13/strength
- AN10-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_086
x_pos: AN10-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.07/y_pos
@@ -4112,7 +4112,7 @@
- AN10-AR/EM-OCT/OC.05/strength
- AN10-AR/EM-COR/OC.05-CQLN.16/strength
- AN10-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_087
x_pos: AN10-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.08/y_pos
@@ -4184,7 +4184,7 @@
physics:
- AN10-AR/EM-SX/SCD.18/strength
- AN10-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_088
x_pos: AN10-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.09/y_pos
@@ -4206,7 +4206,7 @@
physics:
- AN10-AR/EM-SX/SHD.04/strength
- AN10-AR/EM-COR/SHD.04-CDLV.09/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_089
x_pos: AN10-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN10-AR/DG-EPOS/BPM.10/y_pos
@@ -4262,11 +4262,11 @@
- AN10-AR/EM-SX/SHF.06/strength
- AN10-AR/EM-COR/SHF.06-CDLH.10/strength
- AN10-AR/EM-COR/SHF.06-CDLV.10/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_090
x_pos: AN11-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN11-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_091
x_pos: AN11-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN11-SD/DG-EPOS/BPM.02/y_pos
@@ -4322,7 +4322,7 @@
physics:
- AN11-AR/EM-OCT/OH.02/strength
- AN11-AR/EM-COR/OH.02-CQLN.02/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_092
x_pos: AN11-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.03/y_pos
@@ -4376,7 +4376,7 @@
physics:
- AN11-AR/EM-SX/SCF.02/strength
- AN11-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_093
x_pos: AN11-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.04/y_pos
@@ -4436,7 +4436,7 @@
physics:
- AN11-AR/EM-SX/SCF.05/strength
- AN11-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_094
x_pos: AN11-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.05/y_pos
@@ -4496,7 +4496,7 @@
physics:
- AN11-AR/EM-SX/SCF.08/strength
- AN11-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_095
x_pos: AN11-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.06/y_pos
@@ -4556,7 +4556,7 @@
- AN11-AR/EM-OCT/OC.04/strength
- AN11-AR/EM-COR/OC.04-CQLN.13/strength
- AN11-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_096
x_pos: AN11-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.07/y_pos
@@ -4616,7 +4616,7 @@
- AN11-AR/EM-OCT/OC.05/strength
- AN11-AR/EM-COR/OC.05-CQLN.16/strength
- AN11-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_097
x_pos: AN11-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.08/y_pos
@@ -4688,7 +4688,7 @@
physics:
- AN11-AR/EM-SX/SCD.18/strength
- AN11-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_098
x_pos: AN11-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.09/y_pos
@@ -4730,7 +4730,7 @@
physics:
- AN11-AR/EM-OCT/OH.03/strength
- AN11-AR/EM-COR/OH.03-CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_099
x_pos: AN11-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN11-AR/DG-EPOS/BPM.10/y_pos
@@ -4762,11 +4762,11 @@
- AN11-AR/EM-OCT/OH.04/strength
- AN11-AR/EM-COR/OH.04-CQLN.22/strength
- AN11-AR/EM-COR/OH.04-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_100
x_pos: AN12-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN12-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_101
x_pos: AN12-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN12-SD/DG-EPOS/BPM.02/y_pos
@@ -4798,7 +4798,7 @@
- AN12-AR/EM-SX/SHF.01/strength
- AN12-AR/EM-COR/SHF.01-CDLH.01/strength
- AN12-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_102
x_pos: AN12-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN12-AR/DG-EPOS/BPM.03/y_pos
@@ -4872,7 +4872,7 @@
physics:
- AN12-AR/EM-SX/SCF.02/strength
- AN12-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_103
x_pos: AN12-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN12-AR/DG-EPOS/BPM.04/y_pos
@@ -4932,7 +4932,7 @@
physics:
- AN12-AR/EM-SX/SCF.05/strength
- AN12-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_104
x_pos: AN12-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN12-AR/DG-EPOS/BPM.05/y_pos
@@ -5004,7 +5004,7 @@
physics:
- AN12-AR/EM-SX/SCD.09/strength
- AN12-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_105
x_pos: AN12-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN12-AR/DG-EPOS/BPM.06/y_pos
@@ -5040,7 +5040,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN12-AR/EM-COR/CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_106
x_pos: AN12-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN12-AR/DG-EPOS/BPM.07/y_pos
@@ -5072,11 +5072,11 @@
- AN12-AR/EM-OCT/OH.03/strength
- AN12-AR/EM-COR/OH.03-CQLN.13/strength
- AN12-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_107
x_pos: AN13-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN13-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_108
x_pos: AN13-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN13-SD/DG-EPOS/BPM.02/y_pos
@@ -5108,7 +5108,7 @@
- AN13-AR/EM-SX/SHF.01/strength
- AN13-AR/EM-COR/SHF.01-CDLH.01/strength
- AN13-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_109
x_pos: AN13-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.03/y_pos
@@ -5176,7 +5176,7 @@
physics:
- AN13-AR/EM-SX/SCF.02/strength
- AN13-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_110
x_pos: AN13-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.04/y_pos
@@ -5236,7 +5236,7 @@
physics:
- AN13-AR/EM-SX/SCF.05/strength
- AN13-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_111
x_pos: AN13-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.05/y_pos
@@ -5296,7 +5296,7 @@
physics:
- AN13-AR/EM-SX/SCF.08/strength
- AN13-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_112
x_pos: AN13-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.06/y_pos
@@ -5356,7 +5356,7 @@
- AN13-AR/EM-OCT/OC.04/strength
- AN13-AR/EM-COR/OC.04-CQLN.13/strength
- AN13-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_113
x_pos: AN13-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.07/y_pos
@@ -5416,7 +5416,7 @@
- AN13-AR/EM-OCT/OC.05/strength
- AN13-AR/EM-COR/OC.05-CQLN.16/strength
- AN13-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_114
x_pos: AN13-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.08/y_pos
@@ -5488,7 +5488,7 @@
physics:
- AN13-AR/EM-SX/SCD.18/strength
- AN13-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_115
x_pos: AN13-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.09/y_pos
@@ -5524,7 +5524,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN13-AR/EM-COR/CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_116
x_pos: AN13-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN13-AR/DG-EPOS/BPM.10/y_pos
@@ -5556,11 +5556,11 @@
- AN13-AR/EM-OCT/OH.02/strength
- AN13-AR/EM-COR/OH.02-CQLN.22/strength
- AN13-AR/EM-COR/OH.02-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_117
x_pos: AN14-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN14-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_118
x_pos: AN14-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN14-SD/DG-EPOS/BPM.02/y_pos
@@ -5592,7 +5592,7 @@
- AN14-AR/EM-SX/SHF.01/strength
- AN14-AR/EM-COR/SHF.01-CDLH.01/strength
- AN14-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_119
x_pos: AN14-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN14-AR/DG-EPOS/BPM.03/y_pos
@@ -5660,7 +5660,7 @@
physics:
- AN14-AR/EM-SX/SCF.02/strength
- AN14-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_120
x_pos: AN14-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN14-AR/DG-EPOS/BPM.04/y_pos
@@ -5720,7 +5720,7 @@
- AN14-AR/EM-OCT/OC.02/strength
- AN14-AR/EM-COR/OC.02-CQLN.07/strength
- AN14-AR/EM-COR/OC.02-CQLT.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_121
x_pos: AN14-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN14-AR/DG-EPOS/BPM.05/y_pos
@@ -5792,7 +5792,7 @@
physics:
- AN14-AR/EM-SX/SCD.09/strength
- AN14-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_122
x_pos: AN14-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN14-AR/DG-EPOS/BPM.06/y_pos
@@ -5834,7 +5834,7 @@
physics:
- AN14-AR/EM-OCT/OH.02/strength
- AN14-AR/EM-COR/OH.02-CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_123
x_pos: AN14-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN14-AR/DG-EPOS/BPM.07/y_pos
@@ -5866,11 +5866,11 @@
- AN14-AR/EM-OCT/OH.03/strength
- AN14-AR/EM-COR/OH.03-CQLN.13/strength
- AN14-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_124
x_pos: AN15-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN15-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_125
x_pos: AN15-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN15-SD/DG-EPOS/BPM.02/y_pos
@@ -5902,7 +5902,7 @@
- AN15-AR/EM-SX/SHF.01/strength
- AN15-AR/EM-COR/SHF.01-CDLH.01/strength
- AN15-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_126
x_pos: AN15-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.03/y_pos
@@ -5976,7 +5976,7 @@
physics:
- AN15-AR/EM-SX/SCF.02/strength
- AN15-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_127
x_pos: AN15-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.04/y_pos
@@ -6036,7 +6036,7 @@
physics:
- AN15-AR/EM-SX/SCF.05/strength
- AN15-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_128
x_pos: AN15-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.05/y_pos
@@ -6096,7 +6096,7 @@
physics:
- AN15-AR/EM-SX/SCF.08/strength
- AN15-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_129
x_pos: AN15-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.06/y_pos
@@ -6156,7 +6156,7 @@
- AN15-AR/EM-OCT/OC.04/strength
- AN15-AR/EM-COR/OC.04-CQLN.13/strength
- AN15-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_130
x_pos: AN15-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.07/y_pos
@@ -6216,7 +6216,7 @@
- AN15-AR/EM-OCT/OC.05/strength
- AN15-AR/EM-COR/OC.05-CQLN.16/strength
- AN15-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_131
x_pos: AN15-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.08/y_pos
@@ -6288,7 +6288,7 @@
physics:
- AN15-AR/EM-SX/SCD.18/strength
- AN15-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_132
x_pos: AN15-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.09/y_pos
@@ -6310,7 +6310,7 @@
physics:
- AN15-AR/EM-SX/SHD.04/strength
- AN15-AR/EM-COR/SHD.04-CDLV.09/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_133
x_pos: AN15-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN15-AR/DG-EPOS/BPM.10/y_pos
@@ -6364,11 +6364,11 @@
physics:
- AN15-AR/EM-OCT/OH.04/strength
- AN15-AR/EM-COR/OH.04-CQLN.22/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_134
x_pos: AN16-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN16-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_135
x_pos: AN16-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN16-SD/DG-EPOS/BPM.02/y_pos
@@ -6424,11 +6424,11 @@
physics:
- AN16-SD/EM-OCT/OH.02/strength
- AN16-SD/EM-COR/OH.02-CQLN.02/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_136
x_pos: AN16-SD/DG-EPOS/BPM.03/x_pos
y_pos: AN16-SD/DG-EPOS/BPM.03/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_137
x_pos: AN16-SD/DG-EPOS/BPM.04/x_pos
y_pos: AN16-SD/DG-EPOS/BPM.04/y_pos
@@ -6482,7 +6482,7 @@
physics:
- AN16-AR/EM-SX/SHD.02/strength
- AN16-AR/EM-COR/SHD.02-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_138
x_pos: AN16-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.05/y_pos
@@ -6536,7 +6536,7 @@
physics:
- AN16-AR/EM-SX/SCF.02/strength
- AN16-AR/EM-COR/SCF.02-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_139
x_pos: AN16-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.06/y_pos
@@ -6596,7 +6596,7 @@
physics:
- AN16-AR/EM-SX/SCF.05/strength
- AN16-AR/EM-COR/SCF.05-CDLH.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_140
x_pos: AN16-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.07/y_pos
@@ -6656,7 +6656,7 @@
physics:
- AN16-AR/EM-SX/SCF.08/strength
- AN16-AR/EM-COR/SCF.08-CDLH.07/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_141
x_pos: AN16-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.08/y_pos
@@ -6716,7 +6716,7 @@
- AN16-AR/EM-OCT/OC.04/strength
- AN16-AR/EM-COR/OC.04-CQLN.13/strength
- AN16-AR/EM-COR/OC.04-CQLT.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_142
x_pos: AN16-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.09/y_pos
@@ -6776,7 +6776,7 @@
- AN16-AR/EM-OCT/OC.05/strength
- AN16-AR/EM-COR/OC.05-CQLN.16/strength
- AN16-AR/EM-COR/OC.05-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_143
x_pos: AN16-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.10/y_pos
@@ -6848,7 +6848,7 @@
physics:
- AN16-AR/EM-SX/SCD.18/strength
- AN16-AR/EM-COR/SCD.18-CDLV.10/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_144
x_pos: AN16-AR/DG-EPOS/BPM.11/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.11/y_pos
@@ -6890,7 +6890,7 @@
physics:
- AN16-AR/EM-OCT/OH.03/strength
- AN16-AR/EM-COR/OH.03-CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_145
x_pos: AN16-AR/DG-EPOS/BPM.12/x_pos
y_pos: AN16-AR/DG-EPOS/BPM.12/y_pos
@@ -6922,11 +6922,11 @@
- AN16-AR/EM-OCT/OH.04/strength
- AN16-AR/EM-COR/OH.04-CQLN.22/strength
- AN16-AR/EM-COR/OH.04-CQLT.07/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_146
x_pos: AN17-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN17-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_147
x_pos: AN17-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN17-SD/DG-EPOS/BPM.02/y_pos
@@ -6958,7 +6958,7 @@
- AN17-AR/EM-SX/SHF.01/strength
- AN17-AR/EM-COR/SHF.01-CDLH.01/strength
- AN17-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_148
x_pos: AN17-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN17-AR/DG-EPOS/BPM.03/y_pos
@@ -7032,7 +7032,7 @@
physics:
- AN17-AR/EM-SX/SCF.02/strength
- AN17-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_149
x_pos: AN17-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN17-AR/DG-EPOS/BPM.04/y_pos
@@ -7092,7 +7092,7 @@
physics:
- AN17-AR/EM-SX/SCF.05/strength
- AN17-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_150
x_pos: AN17-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN17-AR/DG-EPOS/BPM.05/y_pos
@@ -7164,7 +7164,7 @@
physics:
- AN17-AR/EM-SX/SCD.09/strength
- AN17-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_151
x_pos: AN17-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN17-AR/DG-EPOS/BPM.06/y_pos
@@ -7200,7 +7200,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN17-AR/EM-COR/CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_152
x_pos: AN17-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN17-AR/DG-EPOS/BPM.07/y_pos
@@ -7232,11 +7232,11 @@
- AN17-AR/EM-OCT/OH.03/strength
- AN17-AR/EM-COR/OH.03-CQLN.13/strength
- AN17-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_153
x_pos: AN18-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN18-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_154
x_pos: AN18-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN18-SD/DG-EPOS/BPM.02/y_pos
@@ -7268,7 +7268,7 @@
- AN18-AR/EM-SX/SHF.01/strength
- AN18-AR/EM-COR/SHF.01-CDLH.01/strength
- AN18-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_155
x_pos: AN18-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.03/y_pos
@@ -7336,7 +7336,7 @@
physics:
- AN18-AR/EM-SX/SCF.02/strength
- AN18-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_156
x_pos: AN18-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.04/y_pos
@@ -7396,7 +7396,7 @@
physics:
- AN18-AR/EM-SX/SCF.05/strength
- AN18-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_157
x_pos: AN18-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.05/y_pos
@@ -7456,7 +7456,7 @@
physics:
- AN18-AR/EM-SX/SCF.08/strength
- AN18-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_158
x_pos: AN18-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.06/y_pos
@@ -7516,7 +7516,7 @@
- AN18-AR/EM-OCT/OC.04/strength
- AN18-AR/EM-COR/OC.04-CQLN.13/strength
- AN18-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_159
x_pos: AN18-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.07/y_pos
@@ -7576,7 +7576,7 @@
- AN18-AR/EM-OCT/OC.05/strength
- AN18-AR/EM-COR/OC.05-CQLN.16/strength
- AN18-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_160
x_pos: AN18-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.08/y_pos
@@ -7648,7 +7648,7 @@
physics:
- AN18-AR/EM-SX/SCD.18/strength
- AN18-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_161
x_pos: AN18-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.09/y_pos
@@ -7684,7 +7684,7 @@
type: pyaml.magnet.identity_model
unit: 1/m
physics: AN18-AR/EM-COR/CQLN.21/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_162
x_pos: AN18-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN18-AR/DG-EPOS/BPM.10/y_pos
@@ -7716,11 +7716,11 @@
- AN18-AR/EM-OCT/OH.02/strength
- AN18-AR/EM-COR/OH.02-CQLN.22/strength
- AN18-AR/EM-COR/OH.02-CQLT.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_163
x_pos: AN19-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN19-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_164
x_pos: AN19-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN19-SD/DG-EPOS/BPM.02/y_pos
@@ -7752,7 +7752,7 @@
- AN19-AR/EM-SX/SHF.01/strength
- AN19-AR/EM-COR/SHF.01-CDLH.01/strength
- AN19-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_165
x_pos: AN19-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN19-AR/DG-EPOS/BPM.03/y_pos
@@ -7820,7 +7820,7 @@
physics:
- AN19-AR/EM-SX/SCF.02/strength
- AN19-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_166
x_pos: AN19-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN19-AR/DG-EPOS/BPM.04/y_pos
@@ -7880,7 +7880,7 @@
- AN19-AR/EM-OCT/OC.02/strength
- AN19-AR/EM-COR/OC.02-CQLN.07/strength
- AN19-AR/EM-COR/OC.02-CQLT.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_167
x_pos: AN19-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN19-AR/DG-EPOS/BPM.05/y_pos
@@ -7952,7 +7952,7 @@
physics:
- AN19-AR/EM-SX/SCD.09/strength
- AN19-AR/EM-COR/SCD.09-CDLV.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_168
x_pos: AN19-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN19-AR/DG-EPOS/BPM.06/y_pos
@@ -7994,7 +7994,7 @@
physics:
- AN19-AR/EM-OCT/OH.02/strength
- AN19-AR/EM-COR/OH.02-CQLN.12/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_169
x_pos: AN19-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN19-AR/DG-EPOS/BPM.07/y_pos
@@ -8026,11 +8026,11 @@
- AN19-AR/EM-OCT/OH.03/strength
- AN19-AR/EM-COR/OH.03-CQLN.13/strength
- AN19-AR/EM-COR/OH.03-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_170
x_pos: AN20-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN20-SD/DG-EPOS/BPM.01/y_pos
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_171
x_pos: AN20-SD/DG-EPOS/BPM.02/x_pos
y_pos: AN20-SD/DG-EPOS/BPM.02/y_pos
@@ -8062,7 +8062,7 @@
- AN20-AR/EM-SX/SHF.01/strength
- AN20-AR/EM-COR/SHF.01-CDLH.01/strength
- AN20-AR/EM-COR/SHF.01-CDLV.01/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_172
x_pos: AN20-AR/DG-EPOS/BPM.03/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.03/y_pos
@@ -8136,7 +8136,7 @@
physics:
- AN20-AR/EM-SX/SCF.02/strength
- AN20-AR/EM-COR/SCF.02-CDLH.03/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_173
x_pos: AN20-AR/DG-EPOS/BPM.04/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.04/y_pos
@@ -8196,7 +8196,7 @@
physics:
- AN20-AR/EM-SX/SCF.05/strength
- AN20-AR/EM-COR/SCF.05-CDLH.04/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_174
x_pos: AN20-AR/DG-EPOS/BPM.05/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.05/y_pos
@@ -8256,7 +8256,7 @@
physics:
- AN20-AR/EM-SX/SCF.08/strength
- AN20-AR/EM-COR/SCF.08-CDLH.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_175
x_pos: AN20-AR/DG-EPOS/BPM.06/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.06/y_pos
@@ -8316,7 +8316,7 @@
- AN20-AR/EM-OCT/OC.04/strength
- AN20-AR/EM-COR/OC.04-CQLN.13/strength
- AN20-AR/EM-COR/OC.04-CQLT.05/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_176
x_pos: AN20-AR/DG-EPOS/BPM.07/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.07/y_pos
@@ -8376,7 +8376,7 @@
- AN20-AR/EM-OCT/OC.05/strength
- AN20-AR/EM-COR/OC.05-CQLN.16/strength
- AN20-AR/EM-COR/OC.05-CQLT.06/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_177
x_pos: AN20-AR/DG-EPOS/BPM.08/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.08/y_pos
@@ -8448,7 +8448,7 @@
physics:
- AN20-AR/EM-SX/SCD.18/strength
- AN20-AR/EM-COR/SCD.18-CDLV.08/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_178
x_pos: AN20-AR/DG-EPOS/BPM.09/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.09/y_pos
@@ -8470,7 +8470,7 @@
physics:
- AN20-AR/EM-SX/SHD.04/strength
- AN20-AR/EM-COR/SHD.04-CDLV.09/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_179
x_pos: AN20-AR/DG-EPOS/BPM.10/x_pos
y_pos: AN20-AR/DG-EPOS/BPM.10/y_pos
@@ -8526,7 +8526,7 @@
- AN20-AR/EM-SX/SHF.06/strength
- AN20-AR/EM-COR/SHF.06-CDLH.10/strength
- AN20-AR/EM-COR/SHF.06-CDLV.10/strength
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_180
x_pos: AN01-SD/DG-EPOS/BPM.01/x_pos
y_pos: AN01-SD/DG-EPOS/BPM.01/y_pos
diff --git a/examples/use_cases/config/soleil_ii/p.yaml b/examples/use_cases/config/soleil_ii/p.yaml
index d8829096d..3eab94047 100644
--- a/examples/use_cases/config/soleil_ii/p.yaml
+++ b/examples/use_cases/config/soleil_ii/p.yaml
@@ -14,8 +14,8 @@ controls:
- type: tango.pyaml.controlsystem
name: live
tango_host: localhost:11000
- catalog: catalogs.yaml
-arrays: arrays.yaml
+ catalog: ${include:catalogs.yaml}
+arrays: ${include:arrays.yaml}
devices:
-- devices.yaml
-- tuning_tools.yaml
+- ${include:devices.yaml}
+- ${include:tuning_tools.yaml}
diff --git a/pyaml/apidoc/gen_api.py b/pyaml/apidoc/gen_api.py
index e2b05a8ae..4439e85e2 100644
--- a/pyaml/apidoc/gen_api.py
+++ b/pyaml/apidoc/gen_api.py
@@ -20,7 +20,6 @@
"pyaml.arrays.magnet_array",
"pyaml.arrays.serialized_magnet",
"pyaml.arrays.serialized_magnet_array",
- "pyaml.bpm.bpm",
"pyaml.common.abstract",
"pyaml.common.abstract_aggregator",
"pyaml.common.constants",
@@ -40,6 +39,7 @@
"pyaml.control.deviceaccesslist",
"pyaml.control.readback_value",
"pyaml.diagnostics.atune_monitor",
+ "pyaml.diagnostics.bpm.bpm",
"pyaml.diagnostics.tune_monitor",
"pyaml.external.pySC_interface",
"pyaml.lattice.abstract_impl",
diff --git a/pyaml/arrays/bpm.py b/pyaml/arrays/bpm.py
index 4ea849271..dd9d29969 100644
--- a/pyaml/arrays/bpm.py
+++ b/pyaml/arrays/bpm.py
@@ -88,4 +88,4 @@ def fill_array(self, holder: ElementHolder):
holder : ElementHolder
The element holder to populate the :py:class:`.BPMArray` with.
"""
- holder.bpms.add(self._name, self._elements)
+ holder.diagnostic.bpms.add(self._name, self._elements)
diff --git a/pyaml/arrays/bpm_array.py b/pyaml/arrays/bpm_array.py
index 9006af38c..f3751226e 100644
--- a/pyaml/arrays/bpm_array.py
+++ b/pyaml/arrays/bpm_array.py
@@ -6,7 +6,8 @@
import numpy as np
-from ..bpm.bpm import BPM
+from pyaml.diagnostics.bpm import BPM
+
from ..common.abstract import ReadFloatArray
from ..control.deviceaccesslist import DeviceAccessList
from .element_array import ElementArray
@@ -24,7 +25,7 @@ class RWBPMPosition(ReadFloatArray):
----------
name : str
Name of the position accessor
- bpms : list[pyaml.bpm.bpm.BPM]
+ bpms : list[pyaml.diagnostics.bpm.bpm.BPM]
List of BPM objects to access
Methods
@@ -98,7 +99,7 @@ class RWBPMSinglePosition(ReadFloatArray):
----------
name : str
Name of the position accessor
- bpms : list[pyaml.bpm.bpm.BPM]
+ bpms : list[pyaml.diagnostics.bpm.bpm.BPM]
List of BPM objects to access
idx : int
Index for the position axis (0 for horizontal, 1 for vertical)
@@ -170,7 +171,7 @@ class BPMArray(ElementArray):
----------
arrayName : str
Array name
- bpms : list[pyaml.bpm.bpm.BPM]
+ bpms : list[pyaml.diagnostics.bpm.bpm.BPM]
BPM list, all elements must be attached to the same instance of
either a (:py:class:`~pyaml.lattice.simulator.Simulator`
or a :py:class:`~pyaml.control.controlsystem.ControlSystem`).
diff --git a/pyaml/arrays/element.py b/pyaml/arrays/element.py
index 6483f03de..4b93276a0 100644
--- a/pyaml/arrays/element.py
+++ b/pyaml/arrays/element.py
@@ -65,7 +65,7 @@ def fill_array(self, holder: ElementHolder):
.. code-block:: python
>>> elt_cfg.fill_array(sr.design)
- >>> names = sr.design.get_elements("MyArray").names()
+ >>> names = sr.design.get("MyArray").names()
>>> print(names)
['BPM_C04-01', 'SH1A-C04-H']
diff --git a/pyaml/arrays/element_array.py b/pyaml/arrays/element_array.py
index 26b7ce260..d39d7cbbf 100644
--- a/pyaml/arrays/element_array.py
+++ b/pyaml/arrays/element_array.py
@@ -10,9 +10,11 @@
import numpy as np
-from ..bpm.bpm import BPM
+from pyaml.diagnostics.bpm import BPM
+
from ..common.element import Element, __pyaml_repr__
from ..common.exception import PyAMLException
+from ..common.name_matching import resolve_names
from ..magnet.cfm_magnet import CombinedFunctionMagnet
from ..magnet.magnet import Magnet
from ..magnet.serialized_magnet import SerializedMagnets
@@ -60,7 +62,7 @@ class ElementArray(list[Element]):
.. code-block:: python
>>> sr = Accelerator.load("acc.yaml")
- >>> elements = sr.design.get_elements("QuadForTune")
+ >>> elements = sr.design.get("QuadForTune")
"""
def __init__(self, array_name: str, elements: list[Element], use_aggregator=True):
@@ -136,13 +138,17 @@ def __create_array(self, array_name: str, element_type: type, elements: list):
array_class = getattr(m, "BPMArray", None)
return array_class(array_name, elements, self.__use_aggregator)
elif issubclass(element_type, CombinedFunctionMagnet):
+ # CombinedFunctionMagnetArray has no aggregator support, unlike the
+ # array type this selection was derived from.
m = importlib.import_module("pyaml.arrays.cfm_magnet_array")
array_class = getattr(m, "CombinedFunctionMagnetArray", None)
- return array_class(array_name, elements, self.__use_aggregator)
+ return array_class(array_name, elements, False)
elif issubclass(element_type, SerializedMagnets):
+ # SerializedMagnetsArray has no aggregator support, unlike the
+ # array type this selection was derived from.
m = importlib.import_module("pyaml.arrays.serialized_magnet_array")
array_class = getattr(m, "SerializedMagnetsArray", None)
- return array_class(array_name, elements, self.__use_aggregator)
+ return array_class(array_name, elements, False)
elif issubclass(element_type, Element):
return ElementArray(array_name, elements, self.__use_aggregator)
else:
@@ -240,22 +246,6 @@ def mro_as_list(cls: type) -> list[type]:
return self.__create_array("", chosen, elements)
- def _select_names(self, pattern: str) -> "ElementArray":
- """Select names without interpreting field selectors.
-
- Parameters
- ----------
- pattern : str
- A fnmatch pattern applied to each element name.
-
- Returns
- -------
- ElementArray
- Typed selection in the original order, including an empty array
- when no names match.
- """
- return self._typed_array([element for element in self if fnmatch.fnmatch(element.get_name(), pattern)])
-
def __is_bool_mask(self, other: object) -> bool:
"""Return True if 'other' looks like a boolean mask (list or numpy array)."""
# --- numpy boolean array ---
@@ -293,7 +283,7 @@ def __and__(self, other: object):
.. code-block:: python
- >>> cell1 = sr.live.get_elements("C01")
+ >>> cell1 = sr.live.get("C01")
>>> sexts = sr.live.get_magnets("SEXT")
>>> cell1_sext = cell1 & sexts
@@ -576,8 +566,15 @@ def __getitem__(self, key):
Parameters
----------
- key : int, slice or str
- Element index, slice, name pattern, or existing field selector.
+ key : int, slice, str, list[str] or tuple[str, ...]
+ Element index, slice, name pattern (or ``field:pattern`` field
+ selector), or a list/tuple of name patterns. A name pattern is a
+ literal name (must match an element in this array), an fnmatch
+ wildcard (``*``, ``?`` or ``[``), or a ``re:``-prefixed regular
+ expression. A list or tuple resolves each entry independently
+ and unions the results. Prefix a name pattern with ``~`` to
+ exclude its matches instead; a lone ``~pattern`` means every
+ element except those matches.
Returns
-------
@@ -585,33 +582,47 @@ def __getitem__(self, key):
Indexed element or an array inferred from all selected elements.
Different Magnet subclasses produce a MagnetArray; mixed element
families produce an ElementArray. Empty selections return an
- empty ElementArray.
+ empty ElementArray, except a literal name pattern (or literal
+ entry within a list/tuple) matching nothing, which raises.
+
+ Raises
+ ------
+ PyAMLException
+ If a literal name pattern, or a literal entry within a list or
+ tuple, matches no element in this array, or a ``re:`` pattern is
+ not a valid regular expression.
Examples
--------
>>> magnets = sr.design.magnets.get()
>>> subset = magnets[:] # MagnetArray, including mixed magnet classes
>>> correctors = magnets["SH*"] # MagnetArray
+ >>> correctors = magnets["re:^SH1A-C0[12]-H$"] # MagnetArray
+ >>> selection = magnets[["SH1A-C01-H", "SH*-V"]] # Union of patterns
+ >>> all_but_one = magnets["~SH1A-C01-H"] # Every magnet except one
"""
if isinstance(key, slice):
# Slicing
r = super().__getitem__(key)
+ elif isinstance(key, (list, tuple)):
+ # Selection by a list/tuple of name patterns
+ matched = set(resolve_names([e.get_name() for e in self], key))
+ r = [e for e in self if e.get_name() in matched]
+
elif isinstance(key, str):
- fields = key.split(":")
+ fields = [] if key.lstrip("~").startswith("re:") else key.split(":")
if len(fields) <= 1:
- # Selection by name
- r = []
- for e in self:
- if fnmatch.fnmatch(e.get_name(), key):
- r.append(e)
+ # Selection by name pattern
+ matched = set(resolve_names([e.get_name() for e in self], key))
+ r = [e for e in self if e.get_name() in matched]
else:
# Selection by fields
r = []
for e in self:
txt = self.__eval_field(fields[0], e)
- if fnmatch.fnmatch(txt, fields[1]):
+ if fnmatch.fnmatchcase(txt, fields[1]):
r.append(e)
else:
diff --git a/pyaml/bpm/__init__.py b/pyaml/bpm/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/pyaml/common/constants.py b/pyaml/common/constants.py
index 4f8703a25..4d4ee5aca 100644
--- a/pyaml/common/constants.py
+++ b/pyaml/common/constants.py
@@ -20,15 +20,17 @@ class Action(Enum):
Attributes
----------
APPLY : int
- Callback triggered immediately after an actuator excitation.
+ Callback triggered after an actuator excitation completes (including the waiting time).
RESTORE : int
Callback triggered immediately after restoring the actuator.
MEASURE : int
Callback triggered immediately after taking a measurement.
+ INIT : int
+ Triggered once before the measurement starts
"""
APPLY = 0
- "Triggered immediately after actuator excitation."
+ "Triggered after an actuator excitation completes (including the waiting time)."
RESTORE = 1
"Triggered immediately after restoring the actuator to its initial value."
MEASURE = 2
diff --git a/pyaml/common/element.py b/pyaml/common/element.py
index 7314c8d13..cdf83239a 100644
--- a/pyaml/common/element.py
+++ b/pyaml/common/element.py
@@ -232,7 +232,9 @@ class ElementConfigModel(BaseModel):
- [name]@idx[,idx] : Element indices in the subset formed by name.
- [name]#start_idx..end_idx : Element range in the subset formed by name.
In the above syntax, if the name is not specficied, the whole set
- of lattice element is used for indexing.
+ of lattice element is used for indexing. ``name`` refers to the
+ ``FamName`` of the lattice elements, or to the attribute configured
+ in the simulator linker when one is used.
"""
model_config = ConfigDict(arbitrary_types_allowed=True, extra="forbid")
@@ -260,7 +262,9 @@ class Element:
| ``[name]#start_idx..end_idx`` : Lattice element range in the subset formed by name.
In the above syntax, if the name is not specficied, the whole set
- of lattice element is used for indexing.
+ of lattice element is used for indexing. ``name`` refers to the
+ ``FamName`` of the lattice elements, or to the attribute configured
+ in the simulator linker when one is used.
description : str or None, optional
Human-readable element description.
diff --git a/pyaml/common/holders/diagnostic_holder.py b/pyaml/common/holders/diagnostic_holder.py
new file mode 100644
index 000000000..fa156c684
--- /dev/null
+++ b/pyaml/common/holders/diagnostic_holder.py
@@ -0,0 +1,146 @@
+"""Holder interface for diagnostics."""
+
+from typing import TYPE_CHECKING
+
+from ...arrays.element_array import ElementArray
+from ...diagnostics.tune_monitor import BetatronTuneMonitor
+from ..element import Element, __pyaml_repr__
+from ..exception import PyAMLException
+from ..name_matching import is_wildcard, resolve_names
+from .sub_holders import BPMHolder, BPMsHolder
+
+if TYPE_CHECKING:
+ from .element_holder import ElementHolder
+
+
+class DiagnosticHolder:
+ """
+ Provide access to diagnostics.
+
+ Parameters
+ ----------
+ peer : 'ElementHolder'
+ Parent holder containing the diagnostic store.
+
+ Attributes
+ ----------
+ bpm, bpms
+ Single BPM by name, or a named BPM array.
+ betatron_tune
+ Betatron tune monitor configured as ``BETATRON_TUNE``, the default, validated
+ against its expected class.
+
+ Methods
+ -------
+ get(name=None)
+ Return a named diagnostic, or all configured diagnostics when no name is given.
+
+ Examples
+ --------
+ >>> default_tune_monitor = sr.live.diagnostic.betatron_tune
+ >>> measured_tune = default_tune_monitor.tune.get()
+ >>> spare_tune_monitor = sr.live.diagnostic.get("SPARE_BETATRON_TUNE_MONITOR")
+ >>> all_diagnostics = sr.live.diagnostic.get()
+ >>> bpm = sr.live.diagnostic.bpm.get("BPM01")
+ >>> bpms = sr.live.diagnostic.bpms.get("BPMS")
+ """
+
+ def __init__(self, peer: "ElementHolder"):
+ """
+ Initialize a diagnostic holder for an element holder.
+ """
+ self._peer = peer
+ self._bpm_holder = BPMHolder(peer)
+ self._bpms_holder = BPMsHolder(peer)
+
+ @property
+ def bpm(self) -> BPMHolder:
+ """Return the bpm."""
+ return self._bpm_holder
+
+ @property
+ def bpms(self) -> BPMsHolder:
+ """Return the bpms."""
+ return self._bpms_holder
+
+ def get(self, name: str = None) -> "Element | ElementArray":
+ """
+ Return a named diagnostic, or all configured diagnostics when no name is given.
+
+ Parameters
+ ----------
+ name : str, optional
+ Name of the diagnostic to look up, as declared in the configuration. When
+ omitted, every configured diagnostic is returned instead.
+
+ Returns
+ -------
+ Element or ElementArray
+ The diagnostic registered under ``name``, or an
+ :class:`~pyaml.arrays.element_array.ElementArray` holding every configured
+ diagnostic, in insertion order, when ``name`` is omitted.
+
+ Raises
+ ------
+ PyAMLException
+ If ``name`` is given and no diagnostic is registered under it.
+ """
+ if name is None:
+ return ElementArray("", list(self._peer._DIAG.values()))
+ return self._peer._get_diagnostic(name)
+
+ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | ElementArray":
+ """
+ Return a diagnostic, or a selection typed as a generic ElementArray.
+
+ Parameters
+ ----------
+ key : str, list[str] or tuple[str, ...]
+ An exact literal name returns the stored diagnostic. An fnmatch
+ wildcard, a ``re:``-prefixed regular expression, or a list/tuple
+ of such patterns returns an ElementArray of matches (possibly
+ empty).
+
+ Returns
+ -------
+ Element or ElementArray
+ The stored diagnostic for an exact literal name, otherwise an
+ ElementArray of matches.
+
+ Raises
+ ------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any diagnostic, or a ``re:`` pattern is
+ not a valid regular expression.
+ """
+ store = self._peer._DIAG
+ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key):
+ return self._peer._get_diagnostic(key)
+ matched = set(resolve_names(store.keys(), key, what="Diagnostic"))
+ return ElementArray("", [v for n, v in store.items() if n in matched])
+
+ @property
+ def betatron_tune(self) -> BetatronTuneMonitor:
+ """
+ Return the betatron tune monitor configured as ``BETATRON_TUNE``.
+
+ Returns
+ -------
+ BetatronTuneMonitor
+ Betatron tune monitor registered under ``BETATRON_TUNE``.
+
+ Raises
+ ------
+ PyAMLException
+ If no diagnostic is registered under ``BETATRON_TUNE``, or if it is not a
+ :class:`~pyaml.diagnostics.tune_monitor.BetatronTuneMonitor`.
+ """
+ name = "BETATRON_TUNE"
+ obj = self.get(name)
+ if not isinstance(obj, BetatronTuneMonitor):
+ raise PyAMLException(f"{name}: BetatronTuneMonitor expected but got {type(obj).__name__}")
+ return obj
+
+ def __repr__(self):
+ return __pyaml_repr__(self)
diff --git a/pyaml/common/holders/element_holder.py b/pyaml/common/holders/element_holder.py
index aa2b16dc0..1cf63dfb1 100644
--- a/pyaml/common/holders/element_holder.py
+++ b/pyaml/common/holders/element_holder.py
@@ -1,26 +1,24 @@
"""Store, resolve, and group elements shared by runtime backends."""
-import fnmatch
-import re
from abc import ABCMeta, abstractmethod
from typing import TYPE_CHECKING, overload
+from pyaml.diagnostics.bpm import BPM
+
from ...arrays.element_array import ElementArray
-from ...bpm.bpm import BPM
from ...diagnostics.tune_monitor import BetatronTuneMonitor
from ...magnet.cfm_magnet import CombinedFunctionMagnet
from ...magnet.magnet import Magnet
from ...magnet.serialized_magnet import SerializedMagnets
from ...rf.rf_plant import RFPlant
from ...rf.rf_transmitter import RFTransmitter
-from ...tuning_tools.chromaticity_monitor import ChromaticityMonitor
from ..abstract_aggregator import ScalarAggregator
from ..element import Element
from ..exception import PyAMLException
+from ..name_matching import is_wildcard, resolve_names
+from .diagnostic_holder import DiagnosticHolder
from .rf_holder import RFHolder
from .sub_holders import (
- BPMHolder,
- BPMsHolder,
CombinedFunctionMagnetHolder,
CombinedFunctionMagnetsHolder,
MagnetHolder,
@@ -28,19 +26,12 @@
SerializedMagnetHolder,
SerializedMagnetsHolder,
)
+from .tool_holder import ToolHolder
if TYPE_CHECKING:
from ...accelerator import Accelerator
from ...configuration.unbound_element import UnboundElement
- from ...tuning_tools.bba import BBA
- from ...tuning_tools.chromaticity import Chromaticity
- from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix
- from ...tuning_tools.dispersion import Dispersion
from ...tuning_tools.measurement_tool import MeasurementTool
- from ...tuning_tools.orbit import Orbit
- from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix
- from ...tuning_tools.tune import Tune
- from ...tuning_tools.tune_response_matrix import TuneResponseMatrix
from ...tuning_tools.tuning_tool import TuningTool
@@ -57,18 +48,16 @@ class ElementHolder(metaclass=ABCMeta):
----------
magnet, magnets
Single magnet by name, or a named magnet array.
- bpm, bpms
- Single BPM by name, or a named BPM array.
combined_function_magnet, combined_function_magnets
Single combined-function magnet by name, or a named array.
serialized_magnet, serialized_magnets
Single serialized magnet group by name, or a named array.
rf
RF plant and transmitters of this mode.
- tune, chromaticity, orbit, dispersion
- Tuning tools attached to this mode, looked up by name.
- trm, crm, orm
- Response-matrix measurement tools, looked up by name.
+ diagnostic
+ Diagnostics of this mode, with typed default-name access.
+ tool
+ Tuning and measurement tools of this mode, with typed default-name access.
Methods
-------
@@ -88,36 +77,12 @@ class ElementHolder(metaclass=ABCMeta):
Create and register a generic element array.
add_element(element)
Add an element to the global element store.
- get_element(name)
- Return a named element from the global store.
- get_elements(name)
- Return a named generic element array.
- get_all_elements()
- Return all registered elements in insertion order.
- get_betatron_tune_monitor(name)
- Return a named betatron tune monitor.
+ get(name=None)
+ Return a named element array, or every registered element when no name is given.
add_betatron_tune_monitor(tune_monitor)
Add a betatron tune monitor to the diagnostics store.
add_tool(tool)
Add a tuning or measurement tool to the tool store.
- get_chromaticity_monitor(name)
- Return a named chromaticity monitor.
- get_chromaticity_tuning(name)
- Return a named chromaticity tuning tool.
- get_crm_tuning(name)
- Return a named chromaticity response-matrix tool.
- get_tune_tuning(name)
- Return a named tune correction tool.
- get_trm_tuning(name)
- Return a named tune response-matrix tool.
- get_orbit_tuning(name)
- Return a named orbit correction tool.
- get_orm_tuning(name)
- Return a named orbit response-matrix tool.
- get_bba(name)
- Return a named beam-based alignment tool.
- get_dispersion_tuning(name)
- Return a named dispersion tuning tool.
"""
def __init__(self):
@@ -156,9 +121,9 @@ def __init__(self):
self._serialized_magnets_holder = SerializedMagnetsHolder(self)
self._combined_function_magnet_holder = CombinedFunctionMagnetHolder(self)
self._combined_function_magnets_holder = CombinedFunctionMagnetsHolder(self)
- self._bpm_holder = BPMHolder(self)
- self._bpms_holder = BPMsHolder(self)
self._rf_holder = RFHolder(self)
+ self._diagnostic_holder = DiagnosticHolder(self)
+ self._tool_holder = ToolHolder(self)
@property
def peer(self) -> "Accelerator":
@@ -198,23 +163,23 @@ def combined_function_magnets(self) -> CombinedFunctionMagnetsHolder:
return self._combined_function_magnets_holder
@property
- def bpm(self) -> BPMHolder:
- """Return the bpm."""
- return self._bpm_holder
+ def rf(self) -> RFHolder:
+ """Return the rf."""
+ return self._rf_holder
@property
- def bpms(self) -> BPMsHolder:
- """Return the bpms."""
- return self._bpms_holder
+ def diagnostic(self) -> DiagnosticHolder:
+ """Return the diagnostic."""
+ return self._diagnostic_holder
@property
- def rf(self) -> RFHolder:
- """Return the rf."""
- return self._rf_holder
+ def tool(self) -> ToolHolder:
+ """Return the tool."""
+ return self._tool_holder
def post_init(self):
"""Run post-initialization hooks for every stored element."""
- for e in self.get_all_elements():
+ for e in self._ALL.values():
e.post_init()
def fill_device(self, elements: list[Element]):
@@ -308,29 +273,34 @@ def create_bpm_aggregators(self, bpms: list[BPM]) -> list[ScalarAggregator | Non
# Elements
- def find_elements(self, filter: str) -> list[str]:
+ def find_elements(self, filter: str | list[str] | tuple[str, ...]) -> list[str]:
"""
- Find element names matching a literal, wildcard, or regular expression.
+ Find element names matching one or several literal, wildcard, or regex patterns.
Parameters
----------
- filter : str
- Pattern to match. Prefix with ``re:`` for a regular expression.
+ filter : str, list[str] or tuple[str, ...]
+ Pattern, or patterns, to match. A pattern is a literal name, an
+ fnmatch wildcard (``*``, ``?`` or ``[`` anywhere in the string),
+ or a regular expression prefixed with ``re:``. Prefix any of
+ those with ``~`` to exclude its matches instead, as in the
+ ``elements:`` selector list of a YAML array declaration, e.g.
+ ``["QD2*", "QF1*", "~QF1E-C05"]``. A lone ``~pattern`` (or a list
+ made only of ``~`` entries) means "every element except those".
Returns
-------
list[str]
Matching element names.
- """
- if filter.startswith("re:"):
- pattern = re.compile(rf"{filter[3:]}")
- elements = [k for k in self._ALL.keys() if pattern.fullmatch(k)]
- elif "*" in filter or "?" in filter:
- elements = [k for k in self._ALL.keys() if fnmatch.fnmatch(k, filter)]
- else:
- elements = [filter]
- return elements
+ Raises
+ ------
+ PyAMLException
+ If a literal pattern (or a ``~``-prefixed literal) matches no
+ element, or a ``re:`` pattern is not a valid regular expression.
+ """
+ matched = set(resolve_names(self._ALL.keys(), filter, what="Element"))
+ return [n for n in self._ALL if n in matched]
def _fill_array(
self,
@@ -340,7 +310,6 @@ def _fill_array(
constructor,
ARR: dict,
):
- # Handle wildcard, regexp and exclusion pattern
"""
Resolve selectors and store a constructed element array.
@@ -358,16 +327,14 @@ def _fill_array(
Destination array store.
"""
all_names: list[str] = []
- excluded_names: list[str] = []
+ excluded_names: set[str] = set()
for name in element_names:
if name.startswith("~"):
- names = self.find_elements(name[1:])
- excluded_names.extend(names)
+ excluded_names.update(self.find_elements(name[1:]))
else:
- names = self.find_elements(name)
- all_names.extend(names)
+ all_names.extend(self.find_elements(name))
- [all_names.remove(name) for name in excluded_names]
+ all_names = [n for n in all_names if n not in excluded_names]
a = []
for n in all_names:
@@ -376,7 +343,7 @@ def _fill_array(
except Exception as err:
raise PyAMLException(f"{constructor.__name__} {array_name} : {err} @index {len(a)}") from None
if m in a:
- raise PyAMLException(f"{constructor.__name__} {array_name} : duplicate name {name} @index {len(a)}") from None
+ raise PyAMLException(f"{constructor.__name__} {array_name} : duplicate name {n} @index {len(a)}") from None
a.append(m)
ARR[array_name] = constructor(array_name, a)
@@ -419,13 +386,27 @@ def _get(self, what, name, array) -> Element:
return array[name]
# Generic elements
- def get(self) -> ElementArray:
- """Return all registered elements in insertion order.
+ def get(self, name: str | None = None) -> ElementArray:
+ """Return a named element array, or every registered element when no name is given.
+
+ Parameters
+ ----------
+ name : str, optional
+ Name of the element array to look up, as declared in the configuration.
+ When omitted, every registered element is returned instead.
Returns
-------
ElementArray
- New unnamed container sharing the registered element references.
+ The element array registered under ``name``, regardless of its concrete
+ family (magnet, BPM, combined-function magnet, serialized-magnet, or
+ generic element array), or a new unnamed container of every registered
+ element, in insertion order, when ``name`` is omitted.
+
+ Raises
+ ------
+ PyAMLException
+ If ``name`` is given and no array is registered under it.
Notes
-----
@@ -437,8 +418,11 @@ def get(self) -> ElementArray:
--------
>>> elements = sr.live.get()
>>> names = elements.names()
+ >>> cell08 = sr.live.get("CELL08")
"""
- return ElementArray("", list(self._ALL.values()))
+ if name is None:
+ return ElementArray("", list(self._ALL.values()))
+ return self._get_array(name)
@overload
def __getitem__(self, key: int) -> Element: ...
@@ -447,32 +431,46 @@ def __getitem__(self, key: int) -> Element: ...
def __getitem__(self, key: slice) -> ElementArray: ...
@overload
- def __getitem__(self, key: str) -> Element | ElementArray | None: ...
+ def __getitem__(self, key: str) -> Element: ...
- def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None:
+ @overload
+ def __getitem__(self, key: list[str] | tuple[str, ...]) -> ElementArray: ...
+
+ def __getitem__(self, key: int | slice | str | list[str] | tuple[str, ...]) -> Element | ElementArray:
"""Retrieve an element or select a collection.
Parameters
----------
- key : int, slice or str
- Index in registration order, slice, exact name, or name pattern.
- Strings containing ``*``, ``?`` or ``[`` use fnmatch matching.
- Other strings are exact registry keys. Colons are literal.
+ key : int, slice, str, list[str] or tuple[str, ...]
+ Index in registration order, slice, exact name, name pattern, or
+ a list/tuple of patterns. Strings containing ``*``, ``?`` or
+ ``[`` use fnmatch matching; a ``re:`` prefix uses a regular
+ expression instead. Any other string is an exact registry key.
+ Colons are literal. A list or tuple resolves each entry
+ independently and unions the results. Prefix any pattern with
+ ``~`` to exclude its matches instead, as in a YAML array's
+ ``elements:`` list; a lone ``~pattern`` means every element
+ except those matches.
Returns
-------
- Element or ElementArray or None
- An index returns an element. An exact name returns its element
- or None. Patterns and slices return the most specific compatible
- array, or an empty ElementArray when nothing matches.
+ Element or ElementArray
+ An index or an exact literal name returns its element. Patterns,
+ lists/tuples of patterns, and slices return the most specific
+ compatible array, or an empty ElementArray when nothing matches.
The full slice ``[:]`` returns a generic ElementArray, like get().
Raises
------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any registered element, or if a ``re:``
+ pattern is not a valid regular expression.
IndexError
If the index is out of bounds.
TypeError
- If the key is neither an integer, a slice, nor a string.
+ If the key is neither an integer, a slice, a string, nor a
+ list/tuple of strings.
ValueError
If a slice has a zero step.
@@ -480,25 +478,35 @@ def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None:
-----
Indices follow insertion order, not necessarily lattice order.
Collections share element references but do not modify the registry.
- Field filters and regular expressions are not interpreted here.
+ Field filters are not interpreted here.
Examples
--------
>>> bpm = sr.live["BPM01"]
- >>> missing = sr.live["UNKNOWN"] # None
+ >>> missing = sr.live["UNKNOWN"] # raises PyAMLException
>>> bpms = sr.live["BPM*"]
>>> bpms = sr.live["BPM0[123]"] # BPM01, BPM02 or BPM03
>>> bpms = sr.live["BPM0[1-3]"] # Same selection using a range
>>> quads = sr.live["Q[FD]*"] # Names starting with QF or QD
>>> bpms = sr.live["BPM0[!3]"] # One character after BPM0, except 3
+ >>> bpms = sr.live["re:^BPM0[12]$"] # Regular expression
+ >>> mixed = sr.live[["BPM01", "QF1*"]] # Union of several patterns
+ >>> all_but_one = sr.live["~BPM01"] # Every element except BPM01
+ >>> most_quads = sr.live[["QF1*", "~QF1A-C01"]] # QF1* minus one name
>>> first = sr.live[0]
>>> subset = sr.live[1:10]
>>> all_elements = sr.live[:]
"""
if isinstance(key, str):
- if any(marker in key for marker in "*?["):
- return self.get()._select_names(key)
- return self._ALL.get(key)
+ if key.startswith("re:") or key.startswith("~") or is_wildcard(key):
+ matched = set(resolve_names(self._ALL.keys(), key))
+ return self.get()._typed_array([v for n, v in self._ALL.items() if n in matched])
+ if key not in self._ALL:
+ raise PyAMLException(f"Element {key} not defined")
+ return self._ALL[key]
+ if isinstance(key, (list, tuple)):
+ matched = set(resolve_names(self._ALL.keys(), key))
+ return self.get()._typed_array([v for n, v in self._ALL.items() if n in matched])
if isinstance(key, int):
return list(self._ALL.values())[key]
if isinstance(key, slice):
@@ -506,7 +514,7 @@ def __getitem__(self, key: int | slice | str) -> Element | ElementArray | None:
if key == slice(None):
return elements
return elements._typed_array(list(elements)[key])
- raise TypeError("ElementHolder keys must be integers, slices or strings")
+ raise TypeError("ElementHolder keys must be integers, slices, strings, or lists/tuples of strings")
def fill_element_array(self, arrayName: str, elementNames: list[str]):
"""
@@ -522,7 +530,7 @@ def fill_element_array(self, arrayName: str, elementNames: list[str]):
self._fill_array(
arrayName,
elementNames,
- self.get_element,
+ self._get_element,
ElementArray,
self._ELEMENT_ARRAYS,
)
@@ -538,60 +546,14 @@ def add_element(self, element: Element):
"""
self._ALL[element.get_name()] = element
- def get_element(self, name: str) -> Element:
+ def _get_element(self, name: str) -> Element:
"""
- Return a named element from the global store.
-
- Parameters
- ----------
- name : str
- Name of the element to look up, as declared in the configuration.
-
- Returns
- -------
- Element
- The element registered under ``name``.
+ Generic single-element resolver used internally to build element arrays.
"""
return self._get("Element", name, self._ALL)
- def get_elements(self, name: str) -> ElementArray:
- """
- Return a named generic element array.
-
- Parameters
- ----------
- name : str
- Name of the element array to look up, as declared in the configuration.
-
- Returns
- -------
- ElementArray
- The element array registered under ``name``.
- """
- return self._get("Element array", name, self._ELEMENT_ARRAYS)
-
- def get_all_elements(self) -> list[Element]:
- """Return all registered elements in insertion order."""
- return [value for key, value in self._ALL.items()]
-
# Tune monitor
- def get_betatron_tune_monitor(self, name: str) -> BetatronTuneMonitor:
- """
- Return a named betatron tune monitor.
-
- Parameters
- ----------
- name : str
- Name of the betatron tune monitor to look up, as declared in the configuration.
-
- Returns
- -------
- BetatronTuneMonitor
- The betatron tune monitor registered under ``name``.
- """
- return self._get("Diagnostic", name, self._DIAG)
-
def add_betatron_tune_monitor(self, tune_monitor: Element):
"""
Add a betatron tune monitor to the diagnostics store.
@@ -616,196 +578,6 @@ def add_tool(self, tool: Element):
"""
self._add(self._TOOLS, tool)
- # ---- Chromaticity -------------------------------------------------
-
- def get_chromaticity_monitor(self, name: str) -> ChromaticityMonitor:
- """
- Return a named chromaticity monitor.
-
- Parameters
- ----------
- name : str
- Name of the chromaticity monitor to look up, as declared in the configuration.
-
- Returns
- -------
- ChromaticityMonitor
- The chromaticity monitor registered under ``name``.
- """
- obj = self._get("Chromaticity monitor", name, self._TOOLS)
- return obj
-
- def get_chromaticity_tuning(self, name: str) -> "Chromaticity":
- """
- Return a named chromaticity tuning tool.
-
- Parameters
- ----------
- name : str
- Name of the chromaticity tuning tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'Chromaticity'
- The chromaticity tuning tool registered under ``name``.
- """
- return self._get("Chromaticity tool", name, self._TOOLS)
-
- def get_crm_tuning(self, name: str) -> "ChromaticityResponseMatrix":
- """
- Return a named chromaticity response-matrix tool.
-
- Parameters
- ----------
- name : str
- Name of the chromaticity response-matrix tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'ChromaticityResponseMatrix'
- The chromaticity response-matrix tool registered under ``name``.
- """
- return self._get("ChromaticityResponseMatrix tool", name, self._TOOLS)
-
- @property
- def chromaticity(self) -> "Chromaticity":
- """Return the chromaticity."""
- return self.get_chromaticity_tuning("DEFAULT_CHROMATICITY_CORRECTION")
-
- @property
- def crm(self) -> "ChromaticityResponseMatrix":
- """Return the crm."""
- return self.get_crm_tuning("DEFAULT_CHROMATICITY_RESPONSE_MATRIX")
-
- # ---- Tune ---------------------------------------------------------
-
- def get_tune_tuning(self, name: str) -> "Tune":
- """
- Return a named tune correction tool.
-
- Parameters
- ----------
- name : str
- Name of the tune correction tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'Tune'
- The tune correction tool registered under ``name``.
- """
- return self._get("Tune tuning tool", name, self._TOOLS)
-
- @property
- def tune(self) -> "Tune":
- """Return the tune."""
- return self.get_tune_tuning("DEFAULT_TUNE_CORRECTION")
-
- def get_trm_tuning(self, name: str) -> "TuneResponseMatrix":
- """
- Return a named tune response-matrix tool.
-
- Parameters
- ----------
- name : str
- Name of the tune response-matrix tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'TuneResponseMatrix'
- The tune response-matrix tool registered under ``name``.
- """
- return self._get("TuneResponseMatrix tool", name, self._TOOLS)
-
- @property
- def trm(self) -> "TuneResponseMatrix":
- """Return the default tune response-matrix tool."""
- return self.get_trm_tuning("DEFAULT_TUNE_RESPONSE_MATRIX")
-
- # ---- Orbit --------------------------------------------------------
-
- def get_orbit_tuning(self, name: str) -> "Orbit":
- """
- Return a named orbit correction tool.
-
- Parameters
- ----------
- name : str
- Name of the orbit correction tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'Orbit'
- The orbit correction tool registered under ``name``.
- """
- return self._get("Orbit tuning tool", name, self._TOOLS)
-
- @property
- def orbit(self) -> "Orbit":
- """Return the orbit."""
- return self.get_orbit_tuning("DEFAULT_ORBIT_CORRECTION")
-
- def get_orm_tuning(self, name: str) -> "OrbitResponseMatrix":
- """
- Return a named orbit response-matrix tool.
-
- Parameters
- ----------
- name : str
- Name of the orbit response-matrix tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'OrbitResponseMatrix'
- The orbit response-matrix tool registered under ``name``.
- """
- return self._get("OrbitResponseMatrix tool", name, self._TOOLS)
-
- @property
- def orm(self) -> "OrbitResponseMatrix":
- """Return the default orbit response-matrix tool."""
- return self.get_orm_tuning("DEFAULT_ORBIT_RESPONSE_MATRIX")
-
- # ---- BBA --------------------------------------------------------
-
- def get_bba(self, name: str) -> "BBA":
- """
- Return a named beam-based alignment tool.
-
- Parameters
- ----------
- name : str
- Name of the beam-based alignment tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'BBA'
- The beam-based alignment tool registered under ``name``.
- """
- return self._get("BBA tool", name, self._TOOLS)
-
- # ---- Dispersive orbit --------------------------------------------
-
- def get_dispersion_tuning(self, name: str) -> "Dispersion":
- """
- Return a named dispersion tuning tool.
-
- Parameters
- ----------
- name : str
- Name of the dispersion tuning tool to look up, as declared in the configuration.
-
- Returns
- -------
- 'Dispersion'
- The dispersion tuning tool registered under ``name``.
- """
- return self._get("Dispersion tool", name, self._TOOLS)
-
- @property
- def dispersion(self) -> "Dispersion":
- """Return the dispersion."""
- return self.get_dispersion_tuning("DEFAULT_DISPERSION")
-
def _get_array(self, name: str):
"""
Generic array resolver used by YellowPages.
@@ -876,7 +648,7 @@ def _set_energy(self, E: float):
Energy in eV
"""
# Needed by energy dependant element (i.e. magnet coil current calculation)
- for m in self.get_all_elements():
+ for m in self._ALL.values():
m.set_energy(E)
def _set_mcf(self, alphac: float):
@@ -889,7 +661,7 @@ def _set_mcf(self, alphac: float):
Moment compaction factor
"""
# Needed by some off energy dependant element (i.e. chromaticty tools)
- for m in self.get_all_elements():
+ for m in self._ALL.values():
m.set_mcf(alphac)
def _set_harmonic(self, h: int):
@@ -901,5 +673,5 @@ def _set_harmonic(self, h: int):
h : int
Harmonic number
"""
- for m in self.get_all_elements():
+ for m in self._ALL.values():
m.set_harmonic(h)
diff --git a/pyaml/common/holders/generic_array_holder.py b/pyaml/common/holders/generic_array_holder.py
index 0ce624410..50fec2c19 100644
--- a/pyaml/common/holders/generic_array_holder.py
+++ b/pyaml/common/holders/generic_array_holder.py
@@ -42,6 +42,13 @@ class GenericArrayHolder(Generic[T, A]):
Return a named array or a transient array of all elements.
add(arrayName, elementNames)
Create and register a named array from element selectors.
+
+ Notes
+ -----
+ A configured array is also reachable as an attribute when its name is a
+ valid Python identifier, e.g. ``holder.QuadForTune`` is equivalent to
+ ``holder.get("QuadForTune")``. Array names appear in ``dir(holder)`` so
+ interactive completion (IPython, Jupyter) discovers them.
"""
def __init__(
@@ -103,19 +110,87 @@ def add(self, arrayName: str, elementNames: list[str]):
def __getitem__(self, key):
"""
- Return an element from the aggregate array by index.
+ Select from the aggregate array of every individual element.
+
+ Delegates to :meth:`ElementArray.__getitem__
+ ` on ``self.get()``
+ (the array of every individual element of this type), so ``key``
+ matches against **individual element names**, not against the
+ registered array/family names that :meth:`get` searches. These are
+ deliberately two different, non-overlapping namespaces: ``get(name)``
+ looks up a configured family (e.g. ``"QForTune"``), while ``[key]``
+ looks up the elements themselves (e.g. ``"QF1A-C01"`` or ``"QF1*"``).
Parameters
----------
- key : int or slice
- Index or slice passed to the aggregate array.
+ key : int, slice, str, list[str] or tuple[str, ...]
+ Index or slice into the aggregate array, an individual element's
+ exact name, an fnmatch wildcard or ``re:`` regular expression
+ over element names, or a list/tuple of such patterns.
Returns
-------
object
Element or sub-array selected by ``key``.
+
+ Raises
+ ------
+ PyAMLException
+ If ``key`` is an exact literal element name (or a literal entry
+ within a list or tuple) that matches no individual element, or a
+ ``re:`` pattern is not a valid regular expression.
+
+ Examples
+ --------
+ >>> family = sr.live.magnets.get("QForTune") # array-name namespace
+ >>> one_magnet = sr.live.magnets["QF1A-C01"] # element-name namespace
+ >>> some_magnets = sr.live.magnets["QF1*"] # element-name namespace
"""
return self.get().__getitem__(key)
+ def __getattr__(self, name: str) -> A:
+ """
+ Return a configured array through attribute access.
+
+ Only called when normal attribute lookup fails, so it never shadows
+ :meth:`get`, :meth:`add`, or any other existing attribute.
+
+ Parameters
+ ----------
+ name : str
+ Configured array name. Must be a valid Python identifier.
+
+ Returns
+ -------
+ A
+ The array registered under ``name``.
+
+ Raises
+ ------
+ AttributeError
+ If ``name`` starts with an underscore, is not a valid Python
+ identifier, or does not match a configured array.
+
+ Examples
+ --------
+ >>> quad_family = sr.live.magnets.get("QuadForTune")
+ >>> same_quad_family = sr.live.magnets.QuadForTune
+ """
+ if name.startswith("_") or not name.isidentifier() or name not in self._array_store:
+ raise AttributeError(f"'{type(self).__name__}' object has no array named '{name}'")
+ return self._array_store[name]
+
+ def __dir__(self) -> list[str]:
+ """
+ List attributes, including configured array names.
+
+ Returns
+ -------
+ list of str
+ Default attributes plus configured array names that are valid
+ Python identifiers, for interactive completion (IPython, Jupyter).
+ """
+ return sorted(set(super().__dir__()) | {name for name in self._array_store if name.isidentifier()})
+
def __repr__(self):
return __pyaml_repr__(self)
diff --git a/pyaml/common/holders/generic_element_holder.py b/pyaml/common/holders/generic_element_holder.py
index a23dec8b0..d5c404ffe 100644
--- a/pyaml/common/holders/generic_element_holder.py
+++ b/pyaml/common/holders/generic_element_holder.py
@@ -2,7 +2,9 @@
from typing import TYPE_CHECKING, Generic, TypeVar
+from ...arrays.element_array import ElementArray
from ..element import Element, __pyaml_repr__
+from ..name_matching import is_wildcard, resolve_names
if TYPE_CHECKING:
from .element_holder import ElementHolder
@@ -73,6 +75,38 @@ def get(self, name: str) -> T:
"""
return self._peer._get(self._what, name, self._store)
+ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "T | ElementArray":
+ """
+ Return an element, or a selection typed as the most specific compatible array.
+
+ Parameters
+ ----------
+ key : str, list[str] or tuple[str, ...]
+ An exact literal name returns the stored element. An fnmatch
+ wildcard (``*``, ``?`` or ``[``), a ``re:``-prefixed regular
+ expression, or a list/tuple of such patterns returns the most
+ specific compatible array of matches (possibly empty), like
+ :meth:`.ElementHolder.__getitem__`.
+
+ Returns
+ -------
+ T or ElementArray
+ The stored element for an exact literal name, otherwise a
+ typed array of matches.
+
+ Raises
+ ------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any element in this holder, or a ``re:``
+ pattern is not a valid regular expression.
+ """
+ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key):
+ return self._peer._get(self._what, key, self._store)
+ matched = set(resolve_names(self._store.keys(), key, what=self._what))
+ elements = [v for n, v in self._store.items() if n in matched]
+ return ElementArray("", elements)._typed_array(elements)
+
def add(self, m: T):
"""
Add an element to the holder's name-indexed store.
diff --git a/pyaml/common/holders/rf_holder.py b/pyaml/common/holders/rf_holder.py
index 257c396a4..43c070284 100644
--- a/pyaml/common/holders/rf_holder.py
+++ b/pyaml/common/holders/rf_holder.py
@@ -2,10 +2,12 @@
from typing import TYPE_CHECKING
+from ...arrays.element_array import ElementArray
from ...rf.rf_plant import RFPlant
from ...rf.rf_transmitter import RFTransmitter
from ..abstract import ReadWriteFloatScalar
from ..element import __pyaml_repr__
+from ..name_matching import is_wildcard, resolve_names
if TYPE_CHECKING:
from .element_holder import ElementHolder
@@ -50,6 +52,37 @@ def get(self, name: str) -> RFTransmitter:
"""
return self._peer._get("RFTransmitter", name, self._peer._RFTRANSMITTER)
+ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFTransmitter | ElementArray":
+ """
+ Return a transmitter, or a selection typed as a generic ElementArray.
+
+ Parameters
+ ----------
+ key : str, list[str] or tuple[str, ...]
+ An exact literal name returns the stored transmitter. An fnmatch
+ wildcard, a ``re:``-prefixed regular expression, or a list/tuple
+ of such patterns returns an ElementArray of matches (possibly
+ empty).
+
+ Returns
+ -------
+ RFTransmitter or ElementArray
+ The stored transmitter for an exact literal name, otherwise an
+ ElementArray of matches.
+
+ Raises
+ ------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any transmitter, or a ``re:`` pattern is
+ not a valid regular expression.
+ """
+ store = self._peer._RFTRANSMITTER
+ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key):
+ return self._peer._get("RFTransmitter", key, store)
+ matched = set(resolve_names(store.keys(), key, what="RFTransmitter"))
+ return ElementArray("", [v for n, v in store.items() if n in matched])
+
def add(self, rf: RFTransmitter):
"""
Add an RF transmitter to the holder.
@@ -134,6 +167,37 @@ def get(self, name: str) -> RFPlant:
"""
return self._peer._get("RFPlant", name, self._peer._RFPLANT)
+ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "RFPlant | ElementArray":
+ """
+ Return an RF plant, or a selection typed as a generic ElementArray.
+
+ Parameters
+ ----------
+ key : str, list[str] or tuple[str, ...]
+ An exact literal name returns the stored RF plant. An fnmatch
+ wildcard, a ``re:``-prefixed regular expression, or a list/tuple
+ of such patterns returns an ElementArray of matches (possibly
+ empty).
+
+ Returns
+ -------
+ RFPlant or ElementArray
+ The stored RF plant for an exact literal name, otherwise an
+ ElementArray of matches.
+
+ Raises
+ ------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any RF plant, or a ``re:`` pattern is not
+ a valid regular expression.
+ """
+ store = self._peer._RFPLANT
+ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key):
+ return self._peer._get("RFPlant", key, store)
+ matched = set(resolve_names(store.keys(), key, what="RFPlant"))
+ return ElementArray("", [v for n, v in store.items() if n in matched])
+
def add(self, rf: RFPlant):
"""
Add an RF plant to the holder.
diff --git a/pyaml/common/holders/sub_holders.py b/pyaml/common/holders/sub_holders.py
index 399485eb0..7d2bdc0ac 100644
--- a/pyaml/common/holders/sub_holders.py
+++ b/pyaml/common/holders/sub_holders.py
@@ -2,11 +2,12 @@
from typing import TYPE_CHECKING
+from pyaml.diagnostics.bpm import BPM
+
from ...arrays.bpm_array import BPMArray
from ...arrays.cfm_magnet_array import CombinedFunctionMagnetArray
from ...arrays.magnet_array import MagnetArray
from ...arrays.serialized_magnet_array import SerializedMagnetsArray
-from ...bpm.bpm import BPM
from ...magnet.cfm_magnet import CombinedFunctionMagnet
from ...magnet.magnet import Magnet
from ...magnet.serialized_magnet import SerializedMagnets
@@ -42,6 +43,19 @@ class MagnetsHolder(GenericArrayHolder[Magnet, MagnetArray]):
----------
peer : 'ElementHolder'
Parent element holder that owns this specialized holder.
+
+ Notes
+ -----
+ A configured magnet family is also reachable as an attribute when its
+ name is a valid Python identifier, e.g. ``magnets.QuadForTune`` is
+ equivalent to ``magnets.get("QuadForTune")``. Family names appear in
+ ``dir(magnets)`` for interactive completion.
+
+ Examples
+ --------
+ >>> quad_family = sr.live.magnets.get("QuadForTune")
+ >>> same_quad_family = sr.live.magnets.QuadForTune
+ >>> combined_function_magnets = sr.live.magnets.get_cfm()
"""
def __init__(self, peer: "ElementHolder"):
@@ -57,6 +71,22 @@ def __init__(self, peer: "ElementHolder"):
"Magnet array",
)
+ def get_cfm(self) -> CombinedFunctionMagnetArray:
+ """
+ Return all combined-function magnets.
+
+ Returns
+ -------
+ CombinedFunctionMagnetArray
+ New unnamed container with every registered combined-function
+ magnet.
+
+ Examples
+ --------
+ >>> combined_function_magnets = sr.live.magnets.get_cfm()
+ """
+ return self._peer.combined_function_magnets.get()
+
class CombinedFunctionMagnetHolder(GenericElementHolder[CombinedFunctionMagnet]):
"""
@@ -83,6 +113,13 @@ class CombinedFunctionMagnetsHolder(GenericArrayHolder[CombinedFunctionMagnet, C
----------
peer : 'ElementHolder'
Parent element holder that owns this specialized holder.
+
+ Notes
+ -----
+ A configured array is also reachable as an attribute when its name is a
+ valid Python identifier, e.g. ``combined_function_magnets.CFM`` is
+ equivalent to ``combined_function_magnets.get("CFM")``. Array names
+ appear in ``dir(combined_function_magnets)`` for interactive completion.
"""
def __init__(self, peer: "ElementHolder"):
@@ -124,6 +161,13 @@ class SerializedMagnetsHolder(GenericArrayHolder[SerializedMagnets, SerializedMa
----------
peer : 'ElementHolder'
Parent element holder that owns this specialized holder.
+
+ Notes
+ -----
+ A configured array is also reachable as an attribute when its name is a
+ valid Python identifier, e.g. ``serialized_magnets.QForTune`` is
+ equivalent to ``serialized_magnets.get("QForTune")``. Array names appear
+ in ``dir(serialized_magnets)`` for interactive completion.
"""
def __init__(self, peer: "ElementHolder"):
@@ -165,17 +209,25 @@ class BPMsHolder(GenericArrayHolder[BPM, BPMArray]):
----------
peer : 'ElementHolder'
Parent element holder that owns this specialized holder.
+
+ Notes
+ -----
+ A configured array is also reachable as an attribute when its name is a
+ valid Python identifier, e.g. ``bpms.BPMS`` is equivalent to
+ ``bpms.get("BPMS")``. Array names appear in ``dir(bpms)`` for interactive
+ completion.
"""
def __init__(self, peer: "ElementHolder"):
"""
Initialize the BPMsHolder.
"""
+ bpm_holder = BPMHolder(peer)
super().__init__(
peer,
peer._BPM_ARRAYS,
- peer.bpm.all,
- peer.bpm.get,
+ bpm_holder.all,
+ bpm_holder.get,
BPMArray,
"BPM array",
)
diff --git a/pyaml/common/holders/tool_holder.py b/pyaml/common/holders/tool_holder.py
new file mode 100644
index 000000000..9f8619593
--- /dev/null
+++ b/pyaml/common/holders/tool_holder.py
@@ -0,0 +1,185 @@
+"""Holder interface for tuning and measurement tools."""
+
+from typing import TYPE_CHECKING
+
+from ...arrays.element_array import ElementArray
+from ..element import Element, __pyaml_repr__
+from ..exception import PyAMLException
+from ..name_matching import is_wildcard, resolve_names
+
+if TYPE_CHECKING:
+ from ...tuning_tools.chromaticity import Chromaticity
+ from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix
+ from ...tuning_tools.dispersion import Dispersion
+ from ...tuning_tools.orbit import Orbit
+ from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix
+ from ...tuning_tools.tune import Tune
+ from ...tuning_tools.tune_response_matrix import TuneResponseMatrix
+ from .element_holder import ElementHolder
+
+
+class ToolHolder:
+ """
+ Provide access to tuning and measurement tools.
+
+ Parameters
+ ----------
+ peer : 'ElementHolder'
+ Parent holder containing the tool store.
+
+ Attributes
+ ----------
+ tune, chromaticity, orbit, dispersion
+ Default tuning tool for each kind, resolved from its ``DEFAULT_...`` name and
+ validated against the expected class.
+ trm, crm, orm
+ Default response-matrix measurement tool for each kind, resolved the same way.
+
+ Methods
+ -------
+ get(name=None)
+ Return a named tool, or all configured tools when no name is given.
+
+ Examples
+ --------
+ >>> tune_correction = sr.live.tool.tune
+ >>> tune_correction.set([0.31, 0.22])
+ >>> tune_response = sr.live.tool.trm
+ >>> tune_response.measure()
+ >>> other_tool = sr.live.tool.get("OTHER_TUNE_CORRECTION")
+ >>> all_tools = sr.live.tool.get()
+ """
+
+ def __init__(self, peer: "ElementHolder"):
+ """
+ Initialize a tool holder for an element holder.
+ """
+ self._peer = peer
+
+ def get(self, name: str = None) -> "Element | ElementArray":
+ """
+ Return a named tool, or all configured tools when no name is given.
+
+ Parameters
+ ----------
+ name : str, optional
+ Name of the tuning or measurement tool to look up, as declared in the
+ configuration. When omitted, every configured tool is returned instead.
+
+ Returns
+ -------
+ Element or ElementArray
+ The tool registered under ``name``, or an :class:`~pyaml.arrays.element_array.ElementArray`
+ holding every configured tool, in insertion order, when ``name`` is omitted.
+
+ Raises
+ ------
+ PyAMLException
+ If ``name`` is given and no tool is registered under it.
+ """
+ if name is None:
+ return ElementArray("", list(self._peer._TOOLS.values()))
+ return self._peer._get_tool(name)
+
+ def __getitem__(self, key: str | list[str] | tuple[str, ...]) -> "Element | ElementArray":
+ """
+ Return a tool, or a selection typed as a generic ElementArray.
+
+ Parameters
+ ----------
+ key : str, list[str] or tuple[str, ...]
+ An exact literal name returns the stored tool. An fnmatch
+ wildcard, a ``re:``-prefixed regular expression, or a list/tuple
+ of such patterns returns an ElementArray of matches (possibly
+ empty).
+
+ Returns
+ -------
+ Element or ElementArray
+ The stored tool for an exact literal name, otherwise an
+ ElementArray of matches.
+
+ Raises
+ ------
+ PyAMLException
+ If an exact literal name, or a literal entry within a list or
+ tuple, does not match any tool, or a ``re:`` pattern is not a
+ valid regular expression.
+ """
+ store = self._peer._TOOLS
+ if isinstance(key, str) and not key.startswith(("re:", "~")) and not is_wildcard(key):
+ return self._peer._get_tool(key)
+ matched = set(resolve_names(store.keys(), key, what="Tool"))
+ return ElementArray("", [v for n, v in store.items() if n in matched])
+
+ def _validate_type(self, name: str, obj: Element, expected_type: type) -> Element:
+ """
+ Ensure a resolved default tool matches the type its accessor expects.
+
+ Raises
+ ------
+ PyAMLException
+ If ``obj`` is not an instance of ``expected_type``.
+ """
+ if not isinstance(obj, expected_type):
+ raise PyAMLException(f"{name}: {expected_type.__name__} expected but got {type(obj).__name__}")
+ return obj
+
+ @property
+ def chromaticity(self) -> "Chromaticity":
+ """Return the chromaticity tuning tool configured as ``DEFAULT_CHROMATICITY_CORRECTION``."""
+ from ...tuning_tools.chromaticity import Chromaticity
+
+ name = "DEFAULT_CHROMATICITY_CORRECTION"
+ return self._validate_type(name, self.get(name), Chromaticity)
+
+ @property
+ def crm(self) -> "ChromaticityResponseMatrix":
+ """Return the chromaticity response-matrix tool configured as ``DEFAULT_CHROMATICITY_RESPONSE_MATRIX``."""
+ from ...tuning_tools.chromaticity_response_matrix import ChromaticityResponseMatrix
+
+ name = "DEFAULT_CHROMATICITY_RESPONSE_MATRIX"
+ return self._validate_type(name, self.get(name), ChromaticityResponseMatrix)
+
+ @property
+ def tune(self) -> "Tune":
+ """Return the tune correction tool configured as ``DEFAULT_TUNE_CORRECTION``."""
+ from ...tuning_tools.tune import Tune
+
+ name = "DEFAULT_TUNE_CORRECTION"
+ return self._validate_type(name, self.get(name), Tune)
+
+ @property
+ def trm(self) -> "TuneResponseMatrix":
+ """Return the tune response-matrix tool configured as ``DEFAULT_TUNE_RESPONSE_MATRIX``."""
+ from ...tuning_tools.tune_response_matrix import TuneResponseMatrix
+
+ name = "DEFAULT_TUNE_RESPONSE_MATRIX"
+ return self._validate_type(name, self.get(name), TuneResponseMatrix)
+
+ @property
+ def orbit(self) -> "Orbit":
+ """Return the orbit correction tool configured as ``DEFAULT_ORBIT_CORRECTION``."""
+ from ...tuning_tools.orbit import Orbit
+
+ name = "DEFAULT_ORBIT_CORRECTION"
+ return self._validate_type(name, self.get(name), Orbit)
+
+ @property
+ def orm(self) -> "OrbitResponseMatrix":
+ """Return the orbit response-matrix tool configured as ``DEFAULT_ORBIT_RESPONSE_MATRIX``."""
+ from ...tuning_tools.orbit_response_matrix import OrbitResponseMatrix
+
+ name = "DEFAULT_ORBIT_RESPONSE_MATRIX"
+ return self._validate_type(name, self.get(name), OrbitResponseMatrix)
+
+ @property
+ def dispersion(self) -> "Dispersion":
+ """Return the dispersion tool configured as ``DEFAULT_DISPERSION``."""
+ from ...tuning_tools.dispersion import Dispersion
+
+ name = "DEFAULT_DISPERSION"
+ return self._validate_type(name, self.get(name), Dispersion)
+
+ def __repr__(self):
+ return __pyaml_repr__(self)
diff --git a/pyaml/common/name_matching.py b/pyaml/common/name_matching.py
new file mode 100644
index 000000000..9125cd3af
--- /dev/null
+++ b/pyaml/common/name_matching.py
@@ -0,0 +1,84 @@
+"""Shared name and wildcard resolution convention used by every holder and array."""
+
+import fnmatch
+import re
+from typing import Iterable
+
+from .exception import PyAMLException
+
+WILDCARD_CHARS = frozenset("*?[")
+
+
+def is_wildcard(pattern: str) -> bool:
+ """Return True if `pattern` contains an fnmatch wildcard character."""
+ return any(c in pattern for c in WILDCARD_CHARS)
+
+
+def resolve_names(pool: Iterable[str], pattern: str | list[str] | tuple[str, ...], what: str = "Element") -> list[str]:
+ """
+ Resolve one pattern, or several, against a pool of names.
+
+ Parameters
+ ----------
+ pool : Iterable[str]
+ Names to match against.
+ pattern : str, list[str] or tuple[str, ...]
+ A literal name, an fnmatch wildcard (triggered by ``*``, ``?`` or
+ ``[`` anywhere in the string), or a regular expression prefixed with
+ ``re:``. Prefix any of those with ``~`` to exclude its matches
+ instead of including them, mirroring the ``elements:`` selector list
+ convention used in YAML configuration. A sequence of patterns is
+ resolved entry by entry: non-``~`` entries are unioned,
+ de-duplicated, in first-encounter order, then anything matched by a
+ ``~`` entry is removed from that union. If every entry is
+ ``~``-prefixed (including a single lone ``~pattern``, treated as a
+ one-entry sequence), there is no explicit inclusion, so the base set
+ defaults to the full pool: ``~pattern`` alone means "everything
+ except pattern".
+
+ Returns
+ -------
+ list[str]
+ Matching names.
+
+ Raises
+ ------
+ PyAMLException
+ If a literal pattern (or the remainder of a ``~``-prefixed one) does
+ not match any name in `pool`, or if a `re:`-prefixed pattern is not
+ a valid regular expression.
+ """
+ names = list(pool)
+ patterns = pattern if isinstance(pattern, (list, tuple)) else [pattern]
+
+ included: list[str] = []
+ seen: set[str] = set()
+ excluded: set[str] = set()
+ has_inclusion = False
+ for p in patterns:
+ if p.startswith("~"):
+ excluded.update(_resolve_one(names, p[1:], what))
+ continue
+ has_inclusion = True
+ for name in _resolve_one(names, p, what):
+ if name not in seen:
+ seen.add(name)
+ included.append(name)
+
+ base = included if has_inclusion else names
+ return [n for n in base if n not in excluded]
+
+
+def _resolve_one(names: list[str], pattern: str, what: str) -> list[str]:
+ if pattern.startswith("re:"):
+ source = pattern[3:]
+ try:
+ compiled = re.compile(source)
+ except re.error as exc:
+ raise PyAMLException(f"Invalid regex '{source}': {exc}") from exc
+ return [n for n in names if compiled.fullmatch(n)]
+ if is_wildcard(pattern):
+ return [n for n in names if fnmatch.fnmatchcase(n, pattern)]
+ if pattern not in names:
+ raise PyAMLException(f"{what} {pattern} not defined")
+ return [pattern]
diff --git a/pyaml/configuration/fileloader.py b/pyaml/configuration/fileloader.py
index ef5f9f0eb..c8b09aa96 100644
--- a/pyaml/configuration/fileloader.py
+++ b/pyaml/configuration/fileloader.py
@@ -29,7 +29,6 @@
LOCATION_KEY = "__location__"
FIELD_LOCATIONS_KEY = "__fieldlocations__"
-ACCEPTED_SUFFIXES = (".yaml", ".yml", ".json")
RESOLVER_PATTERN = re.compile(r"\$\{([^{}]+)\}")
@@ -189,7 +188,7 @@ def resolver(name: str):
Args:
name: Prefix used to invoke the resolver (for example ``"env"``
- or ``"file"``).
+ or ``"include"``).
Returns:
A decorator that registers the decorated function in the global
@@ -266,10 +265,10 @@ def resolve_path(value: str, _context: LoadContext | None = None) -> str:
return str(ROOT.expand_path(value))
-@resolver("file")
-def resolve_file(value: str, context: LoadContext | None = None) -> Any:
+@resolver("include")
+def resolve_include(value: str, context: LoadContext | None = None) -> Any:
"""
- Load and return the contents of a configuration file.
+ Load and include the contents of a configuration file.
Parameters
----------
@@ -289,7 +288,7 @@ def resolve_file(value: str, context: LoadContext | None = None) -> Any:
If no loading context is provided.
"""
if context is None:
- raise RuntimeError("File resolver requires LoadContext")
+ raise RuntimeError("Include resolver requires LoadContext")
return _load(value, context)
@@ -323,11 +322,6 @@ def _load(filename: str, context: LoadContext) -> Union[dict, list]:
return loader.load()
-def _is_supported_file(value: Any) -> bool:
- """Return True if the value looks like a supported configuration file name."""
- return isinstance(value, str) and value.endswith(ACCEPTED_SUFFIXES)
-
-
class ConfigLoader(ABC):
"""
Base class for parsers that expand nested configuration references.
@@ -375,7 +369,7 @@ def _expand_string(self, value: str) -> Any:
Expand resolver expressions and file references in a string.
If the entire string is a resolver expression (for example
- ``"${env:HOME}"`` or ``"${file:config.yaml}"``), the resolved value is
+ ``"${env:HOME}"`` or ``"${include:config.yaml}"``), the resolved value is
returned directly and may be of any type.
Resolver expressions embedded inside a larger string are interpolated
@@ -424,9 +418,6 @@ def replace(match: re.Match[str]) -> str:
value = RESOLVER_PATTERN.sub(replace, value)
- if _is_supported_file(value):
- return RESOLVERS["file"](value, self.context)
-
return value
def _resolve_resolver_expression(self, expr: str) -> Any:
@@ -434,7 +425,7 @@ def _resolve_resolver_expression(self, expr: str) -> Any:
Resolve a single resolver expression.
The expression must have the form ``":"``, for
- example ``"env:HOME"`` or ``"file:config.yaml"``. The resolver is
+ example ``"env:HOME"`` or ``"include:config.yaml"``. The resolver is
looked up in the global resolver registry and invoked with the
supplied payload.
@@ -487,31 +478,24 @@ def _expand_list(self, items: list) -> list:
"""
Recursively expand the elements of a list.
- Plain string values that refer to supported configuration files are
- treated as list includes. If the referenced file loads to a list, its
- elements are spliced into the current list. Otherwise, the loaded
- object is appended as a single element.
-
- All other items are expanded recursively using :meth:`expand`.
-
- Args:
- items: The list to expand.
-
- Returns:
- The expanded list.
+ Lists returned by an explicit include resolver are spliced into the
+ current list. Other nested lists are preserved.
"""
expanded: list[Any] = []
for item in items:
- if isinstance(item, str) and _is_supported_file(item):
- loaded = RESOLVERS["file"](item, self.context)
- if isinstance(loaded, list):
- expanded.extend(loaded)
- else:
- expanded.append(loaded)
- continue
-
- expanded.append(self.expand(item))
+ is_include = (
+ isinstance(item, str)
+ and (match := RESOLVER_PATTERN.fullmatch(item)) is not None
+ and match.group(1).strip().startswith("include:")
+ )
+
+ value = self.expand(item)
+
+ if is_include and isinstance(value, list):
+ expanded.extend(value)
+ else:
+ expanded.append(value)
return expanded
diff --git a/pyaml/configuration/restfetcher.py b/pyaml/configuration/restfetcher.py
index 96a754502..0ae0612f6 100644
--- a/pyaml/configuration/restfetcher.py
+++ b/pyaml/configuration/restfetcher.py
@@ -18,12 +18,12 @@
from yaml import CLoader
from ..common.exception import PyAMLConfigException
-from .fileloader import ACCEPTED_SUFFIXES, SafeLineLoader
+from .fileloader import SafeLineLoader
REMOTE_BASE_URL_KEY = "__baseurl__"
SourceRoot = Path | str | None
_REMOTE_SCHEMES = {"http", "https"}
-
+INCLUDE_PREFIX = "${include:"
FILE_PREFIX = "${path:"
@@ -285,9 +285,10 @@ def _expand_remote_dict(
"""
values.setdefault(REMOTE_BASE_URL_KEY, base_url)
for key, value in list(values.items()):
- if _is_config_reference(value):
+ if _is_include(value):
+ reference = _include_reference(value)
values[key] = _load_remote_document(
- _resolve_remote_config_reference(value, base_url),
+ _resolve_remote_config_reference(reference, base_url),
include_locations=include_locations,
stack=stack,
)
@@ -324,9 +325,10 @@ def _expand_remote_list(values: list[Any], base_url: str, stack: list[str], *, i
index = 0
while index < len(values):
value = values[index]
- if _is_config_reference(value):
+ if _is_include(value):
+ reference = _include_reference(value)
expanded = _load_remote_document(
- _resolve_remote_config_reference(value, base_url),
+ _resolve_remote_config_reference(reference, base_url),
include_locations=include_locations,
stack=stack,
)
@@ -348,29 +350,14 @@ def _expand_remote_list(values: list[Any], base_url: str, stack: list[str], *, i
return values
-def _is_config_reference(value: Any) -> bool:
- """
- Return whether a value names a supported configuration document.
-
- Parameters
- ----------
- value : Any
- Value to inspect.
-
- Returns
- -------
- bool
- ``True`` for a YAML, JSON, or supported remote document reference.
- """
- if not isinstance(value, str):
- return False
+def _is_include(value: Any) -> bool:
+ """Return whether a value is an explicit include expression."""
+ return isinstance(value, str) and value.startswith(INCLUDE_PREFIX) and value.endswith("}")
- if value.startswith(FILE_PREFIX):
- return False
- parsed = urlparse(value)
- path = parsed.path if parsed.scheme in _REMOTE_SCHEMES else value
- return any(path.endswith(suffix) for suffix in ACCEPTED_SUFFIXES)
+def _include_reference(value: str) -> str:
+ """Return the reference contained in an include expression."""
+ return value[len(INCLUDE_PREFIX) : -1].strip()
def _resolve_remote_config_reference(reference: str, base_url: str) -> str:
diff --git a/pyaml/control/abstract_impl.py b/pyaml/control/abstract_impl.py
index 077a819dd..5b1105628 100644
--- a/pyaml/control/abstract_impl.py
+++ b/pyaml/control/abstract_impl.py
@@ -294,6 +294,89 @@ def nb_device(self) -> int:
# ------------------------------------------------------------------------------
+class CSSparseScalarAggregator(CSScalarAggregator):
+ """
+ Scalar aggregator whose slots may have no device.
+
+ Only existing devices are added to the backend aggregator, so they are
+ still read in one grouped call. Values are scattered back to their slots
+ and missing slots read NaN.
+
+ Parameters
+ ----------
+ devs : DeviceAccessList
+ Backend aggregator holding the existing devices.
+
+ Methods
+ -------
+ add_devices(devices)
+ Add one or more slots, ``None`` for a slot without device.
+ set(value)
+ Write the values of the slots that have a device.
+ set_and_wait(value)
+ Write the values of the slots that have a device and wait.
+ get()
+ Read all slots, NaN for slots without device.
+ readback()
+ Read all slot readbacks, NaN for slots without device.
+ nb_device()
+ Return the number of slots.
+ """
+
+ def __init__(self, devs: DeviceAccessList):
+ """
+ Initialize the CSSparseScalarAggregator.
+ """
+ super().__init__(devs)
+ self._nb_slots = 0
+ self._slots: list[int] = []
+
+ def add_devices(self, devices: DeviceAccess | None | list[DeviceAccess | None]):
+ """
+ Add one or more slots, ``None`` for a slot without device.
+
+ Parameters
+ ----------
+ devices : DeviceAccess | None | list[DeviceAccess | None]
+ Control-system device or devices to manage.
+ """
+ for d in devices if isinstance(devices, list) else [devices]:
+ if d is not None:
+ self._devs.add_devices(d)
+ self._slots.append(self._nb_slots)
+ self._nb_slots += 1
+
+ def _scatter(self, values: NDArray[np.float64]) -> NDArray[np.float64]:
+ out = np.full(self._nb_slots, np.nan)
+ out[self._slots] = values
+ return out
+
+ def set(self, value: NDArray[np.float64]):
+ """Write the values of the slots that have a device."""
+ if self._slots:
+ self._devs.set(np.asarray(value)[self._slots])
+
+ def set_and_wait(self, value: NDArray[np.float64]):
+ """Write the values of the slots that have a device and wait."""
+ if self._slots:
+ self._devs.set_and_wait(np.asarray(value)[self._slots])
+
+ def get(self) -> NDArray[np.float64]:
+ """Read all slots, NaN for slots without device."""
+ return self._scatter(self._devs.get() if self._slots else [])
+
+ def readback(self) -> np.array:
+ """Read all slot readbacks, NaN for slots without device."""
+ return self._scatter(self._devs.readback() if self._slots else [])
+
+ def nb_device(self) -> int:
+ """Return the number of slots."""
+ return self._nb_slots
+
+
+# ------------------------------------------------------------------------------
+
+
class CSStrengthScalarAggregator(CSScalarAggregator):
"""
Aggregate magnet strengths while avoiding duplicate hardware writes.
@@ -347,7 +430,10 @@ def add_magnet(self, magnet: Magnet, devs: list[DeviceAccess]):
devs : list[DeviceAccess]
Hardware devices associated with the magnet model.
"""
- strengthIndex = magnet.strength.index() if isinstance(magnet.strength, abstract.RWMapper) else 0
+ # Magnets of a serialized group share the serialized model (one power supply for N strengths):
+ # the power-supply current is computed by the model from the N strengths (mean of the implied currents).
+ is_indexed = isinstance(magnet.strength, (abstract.RWMapper, RWSerializedStrengthScalar))
+ strengthIndex = magnet.strength.index() if is_indexed else 0
if magnet.model not in self.__models:
index = len(self.__models)
self.__models.append(magnet.model)
@@ -628,6 +714,42 @@ def set_magnet_rigidity(self, brho: np.double):
self.__model.set_magnet_rigidity(brho)
+class RWSerializedStrengthScalar(RWStrengthScalar):
+ """
+ Expose the strength of one magnet of a serialized group.
+
+ All magnets of a serialized group share one power supply. This accessor
+ converts with the magnet's own sub-model and remembers the magnet position
+ in the group so that aggregators can map it to the right strength of the
+ serialized model.
+
+ Parameters
+ ----------
+ model : MagnetModel
+ Sub-model of the magnet, used for strength conversion and units.
+ dev : DeviceAccess
+ Power-supply device shared by the serialized group.
+ idx : int
+ Zero-based position of the magnet in the serialized group.
+
+ Methods
+ -------
+ index()
+ Return the position of the magnet in the serialized group.
+ """
+
+ def __init__(self, model: MagnetModel, dev: DeviceAccess, idx: int):
+ """
+ Initialize the RWSerializedStrengthScalar.
+ """
+ super().__init__(model, dev)
+ self.__idx = idx
+
+ def index(self) -> int:
+ """Return the position of the magnet in the serialized group."""
+ return self.__idx
+
+
# ------------------------------------------------------------------------------
@@ -801,20 +923,22 @@ class RBpmArray(abstract.ReadFloatArray):
Parameters
----------
- hDev : DeviceAccess
- Device providing the horizontal BPM position.
- vDev : DeviceAccess
- Device providing the vertical BPM position.
+ hDev : DeviceAccess | None
+ Device providing the horizontal BPM position, ``None`` for a BPM
+ without horizontal plane.
+ vDev : DeviceAccess | None
+ Device providing the vertical BPM position, ``None`` for a BPM
+ without vertical plane.
Methods
-------
get()
- Return horizontal and vertical BPM positions.
+ Return horizontal and vertical BPM positions (NaN for a missing plane).
unit()
Return the unit reported by the BPM device.
"""
- def __init__(self, hDev: DeviceAccess, vDev: DeviceAccess):
+ def __init__(self, hDev: DeviceAccess | None, vDev: DeviceAccess | None):
"""
Initialize the RBpmArray.
"""
@@ -822,14 +946,14 @@ def __init__(self, hDev: DeviceAccess, vDev: DeviceAccess):
self._vDev = vDev
def get(self) -> np.array:
- """Return horizontal and vertical BPM positions."""
- return np.array([self._hDev.get(), self._vDev.get()])
+ """Return horizontal and vertical BPM positions (NaN for a missing plane)."""
+ return np.array([d.get() if d is not None else np.nan for d in (self._hDev, self._vDev)], dtype=float)
# Gets the unit of the value Assume that x and y, offsets and positions
# have the same unit
def unit(self) -> str:
"""Return the unit reported by the BPM device."""
- return self._hDev.unit()
+ return (self._hDev if self._hDev is not None else self._vDev).unit()
# ------------------------------------------------------------------------------
diff --git a/pyaml/control/controlsystem.py b/pyaml/control/controlsystem.py
index 9199f98de..4800f7967 100644
--- a/pyaml/control/controlsystem.py
+++ b/pyaml/control/controlsystem.py
@@ -10,7 +10,8 @@
from pydantic import BaseModel
-from ..bpm.bpm import BPM
+from pyaml.diagnostics.bpm import BPM
+
from ..common.abstract import RWMapper
from ..common.abstract_aggregator import ScalarAggregator
from ..common.exception import PyAMLException
@@ -18,6 +19,7 @@
from ..configuration.unbound_element import UnboundElement
from ..control.abstract_impl import (
CSScalarAggregator,
+ CSSparseScalarAggregator,
CSStrengthScalarAggregator,
RBetatronTuneArray,
RBpmArray,
@@ -28,6 +30,7 @@
RWRFFrequencyScalar,
RWRFPhaseScalar,
RWRFVoltageScalar,
+ RWSerializedStrengthScalar,
RWStrengthArray,
RWStrengthScalar,
)
@@ -197,12 +200,14 @@ def create_bpm_aggregators(self, bpms: list[BPM]) -> list[ScalarAggregator | Non
-------
list[ScalarAggregator | None]
Aggregators for combined, horizontal, and vertical positions.
+ A plane without device (e.g. the horizontal plane of a
+ vertical-only XBPM) reads NaN, the other devices are still read
+ in one grouped call.
"""
- agg = self._create_scalar_aggregator()
- aggh = self._create_scalar_aggregator()
- aggv = self._create_scalar_aggregator()
- if agg is None or aggh is None or aggv is None:
+ aggs = [self.get_aggregator() for _ in range(3)]
+ if any(a is None for a in aggs):
return [None, None, None]
+ agg, aggh, aggv = (CSSparseScalarAggregator(a) for a in aggs)
for b in bpms:
devs = self.get_devices_access(b.get_pos_devices())
agg.add_devices(devs)
@@ -226,16 +231,14 @@ def _fill_combined_function_magnet(self, magnet: CombinedFunctionMagnet) -> None
self.magnet.add(virtual_magnet)
def _fill_serialized_magnets(self, magnets: SerializedMagnets) -> None:
- devices = self.get_devices_access(magnets.model.get_device_names())
+ # All magnets of the group share the same power supply
+ device = self.get_device_access(magnets.model.get_device_names()[0])
currents = []
strengths = []
for index in range(magnets.get_nb_magnets()):
- currents.append(
- RWHardwareScalar(magnets.model.get_sub_model(index), devices[index]) if magnets.model.has_hardware() else None
- )
- strengths.append(
- RWStrengthScalar(magnets.model.get_sub_model(index), devices[index]) if magnets.model.has_physics() else None
- )
+ sub_model = magnets.model.get_sub_model(index)
+ currents.append(RWHardwareScalar(sub_model, device) if magnets.model.has_hardware() else None)
+ strengths.append(RWSerializedStrengthScalar(sub_model, device, index) if magnets.model.has_physics() else None)
attached_magnets = magnets.attach(self, strengths, currents)
self.serialized_magnet.add(attached_magnets[0])
for magnet in attached_magnets[1:]:
@@ -248,7 +251,7 @@ def _fill_bpm(self, bpm: BPM) -> None:
positions = RBpmArray(position_devices[0], position_devices[1])
tilt = RWBpmTiltScalar(tilt_devices[0])
offsets = RWBpmOffsetArray(offset_devices[0], offset_devices[1])
- self.bpm.add(bpm.attach(self, positions, offsets, tilt))
+ self.diagnostic.bpm.add(bpm.attach(self, positions, offsets, tilt))
def _fill_rf_plant(self, rf_plant: RFPlant) -> None:
attached_transmitters: list[RFTransmitter] = []
diff --git a/pyaml/diagnostics/bpm/__init__.py b/pyaml/diagnostics/bpm/__init__.py
new file mode 100644
index 000000000..84915bda0
--- /dev/null
+++ b/pyaml/diagnostics/bpm/__init__.py
@@ -0,0 +1,3 @@
+from pyaml.diagnostics.bpm.bpm import BPM
+
+__all__ = ["BPM"]
diff --git a/pyaml/bpm/bpm.py b/pyaml/diagnostics/bpm/bpm.py
similarity index 90%
rename from pyaml/bpm/bpm.py
rename to pyaml/diagnostics/bpm/bpm.py
index dd7015c2e..c63f662aa 100644
--- a/pyaml/bpm/bpm.py
+++ b/pyaml/diagnostics/bpm/bpm.py
@@ -3,13 +3,13 @@
import copy
from typing import TYPE_CHECKING, Self
-from ..common.abstract import ReadFloatArray, ReadWriteFloatArray, ReadWriteFloatScalar
-from ..common.element import Element, __pyaml_repr__
-from ..common.exception import PyAMLException
-from ..validation import DynamicValidation, register_schema
+from pyaml.common.abstract import ReadFloatArray, ReadWriteFloatArray, ReadWriteFloatScalar
+from pyaml.common.element import Element, __pyaml_repr__
+from pyaml.common.exception import PyAMLException
+from pyaml.validation import DynamicValidation, register_schema
if TYPE_CHECKING:
- from ..common.holders.element_holder import ElementHolder
+ from pyaml.common.holders.element_holder import ElementHolder
PYAMLCLASS = "BPM"
@@ -61,6 +61,19 @@ class BPM(Element, DynamicValidation):
Return the configured device key used for tilt access.
get_offset_devices()
Return configured device keys used for offset control.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.diagnostics.bpm.bpm
+ name: BPM_NAME
+ lattice_names: LATTICE_BPM_NAME
+ x_pos: DEVICE/X_POSITION
+ y_pos: DEVICE/Y_POSITION
+ x_offset: DEVICE/X_OFFSET
+ y_offset: DEVICE/Y_OFFSET
+ tilt: DEVICE/TILT
"""
def __init__(
diff --git a/pyaml/diagnostics/tune_monitor.py b/pyaml/diagnostics/tune_monitor.py
index 3b5206d77..3a771cb6a 100644
--- a/pyaml/diagnostics/tune_monitor.py
+++ b/pyaml/diagnostics/tune_monitor.py
@@ -61,6 +61,16 @@ class BetatronTuneMonitor(Element, DynamicValidation, ABetatronTuneMonitor):
Set the harmonic number used for tune-frequency conversion.
attach(peer, betatron_tune)
Attach the tune monitor to a peer with betatron tune data.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.diagnostics.tune_monitor
+ name: BETATRON_TUNE
+ tune_h: DEVICE/HORIZONTAL_TUNE
+ tune_v: DEVICE/VERTICAL_TUNE
+ rf_plant_name: RF
"""
def __init__(
diff --git a/pyaml/external/pySC_interface.py b/pyaml/external/pySC_interface.py
index 3be5196ea..b9e604932 100644
--- a/pyaml/external/pySC_interface.py
+++ b/pyaml/external/pySC_interface.py
@@ -56,7 +56,7 @@ def __init__(
"""
self.element_holder = element_holder
- self.bpm_array = element_holder.bpms.get(bpm_array_name)
+ self.bpm_array = element_holder.diagnostic.bpms.get(bpm_array_name)
self.rf_plant_name = rf_plant_name
if rf_plant_name is not None:
diff --git a/pyaml/lattice/abstract_impl.py b/pyaml/lattice/abstract_impl.py
index 91c07975e..a734a5871 100644
--- a/pyaml/lattice/abstract_impl.py
+++ b/pyaml/lattice/abstract_impl.py
@@ -12,6 +12,7 @@
from ..common import abstract
from ..common.abstract_aggregator import ScalarAggregator
+from ..common.exception import PyAMLException
from ..magnet.model import MagnetModel
from .polynom_info import PolynomInfo
@@ -20,6 +21,21 @@
# ------------------------------------------------------------------------------
+def _effective_lengths(elements: list[at.Element]) -> list[float]:
+ """
+ Return the lengths used to convert between integrated strengths and polynom coefficients.
+
+ AT convention is followed: a zero-length (thin) element stores the *integrated* strength in
+ ``PolynomA``/``PolynomB``, so it behaves as a unit-length element for the conversion. When every element of the
+ group is thin, each one is given a unit length, so that the integrated strength is shared equally between the
+ slices. Otherwise the real lengths are used and any thin slice of the group is left untouched.
+ """
+ lengths = [float(e.Length) for e in elements]
+ if all(L == 0.0 for L in lengths):
+ return [1.0] * len(lengths)
+ return lengths
+
+
class RWHardwareScalar(abstract.ReadWriteFloatScalar):
"""
Provide read/write access to a simulated magnet in hardware units.
@@ -62,19 +78,23 @@ def __init__(self, elements: list[at.Element], poly: PolynomInfo, model: MagnetM
self._poly = [e.__getattribute__(poly.attName) for e in elements]
self._sign = poly.sign
self._polyIdx = poly.index
- self._length: float = 0.0
- for e in elements:
- self._length += e.Length
+ self._is_thin = all(e.Length == 0 for e in elements)
+ self._lengths = _effective_lengths(elements)
+ self._length: float = sum(self._lengths)
def get_length(self) -> float:
- """Return the total length of the lattice elements."""
+ """Return the total effective length of the lattice elements (1.0 per element when they are all thin)."""
return self._length
+ def is_thin(self) -> bool:
+ """Return True when every lattice element of this magnet has zero length."""
+ return self._is_thin
+
def get(self) -> float:
"""Return the current value."""
s = 0
- for idx, e in enumerate(self._elements):
- s += self._poly[idx][self._polyIdx] * self._sign * e.Length
+ for idx, _ in enumerate(self._elements):
+ s += self._poly[idx][self._polyIdx] * self._sign * self._lengths[idx]
return self._model.compute_hardware_values([s])[0]
def set(self, value: float):
@@ -160,9 +180,8 @@ def __init__(self, elements: list[at.Element], poly: PolynomInfo, model: MagnetM
self._poly = [e.__getattribute__(poly.attName) for e in elements]
self._sign = poly.sign
self._polyIdx = poly.index
- self._length = 0
- for e in elements:
- self._length += e.Length
+ self._lengths = _effective_lengths(elements)
+ self._length: float = sum(self._lengths)
def get_element_length(self) -> float:
"""Return the total length of the represented element."""
@@ -195,8 +214,8 @@ def get(self, polynom: str = None, polyidx: int = None) -> float:
poly = [e.__getattribute__(polynom) for e in self._elements]
s = 0
- for idx, e in enumerate(self._elements):
- s += poly[idx][pIdx] * self._sign * e.Length
+ for idx, _ in enumerate(self._elements):
+ s += poly[idx][pIdx] * self._sign * self._lengths[idx]
return s
# Sets the value
@@ -398,6 +417,14 @@ def __init__(
self.__elements_strength = elements_strength
self.__elements_hardware = elements_hardware
self.__element_index = element_index
+ # The strength is shared between the serialized magnets in proportion to their (effective) length: thick
+ # magnets share by length, thin magnets share equally. Mixing both has no meaningful share rule.
+ thin_flags = [e.is_thin() for e in elements_hardware]
+ if any(thin_flags) and not all(thin_flags):
+ raise PyAMLException(
+ "Serialized magnets must be either all thin (zero length) or all thick; "
+ f"got {sum(thin_flags)} thin out of {len(thin_flags)} magnets"
+ )
self.__total_length = 0
for e in self.__elements_hardware:
self.__total_length += e.get_length()
@@ -509,6 +536,7 @@ def __init__(self, elements: list[at.Element], poly: list[PolynomInfo], model: M
self.__polyIdx = []
self.__sign = []
self.__model = model
+ self.__length = _effective_lengths(elements[:1])[0]
for p in poly:
self.__poly.append(elements[0].__getattribute__(p.attName))
self.__polyIdx.append(p.index)
@@ -520,7 +548,7 @@ def get(self) -> np.array:
nbStrength = len(self.__poly)
s = np.zeros(nbStrength)
for i in range(nbStrength):
- s[i] = self.__poly[i][self.__polyIdx[i]] * self.__sign[i] * self.__elements[0].Length
+ s[i] = self.__poly[i][self.__polyIdx[i]] * self.__sign[i] * self.__length
return self.__model.compute_hardware_values(s)
# Sets the value
@@ -536,7 +564,7 @@ def set(self, value: np.array):
nbStrength = len(self.__poly)
s = self.__model.compute_strengths(value)
for i in range(nbStrength):
- self.__poly[i][self.__polyIdx[i]] = s[i] / (self.__elements[0].Length * self.__sign[i])
+ self.__poly[i][self.__polyIdx[i]] = s[i] / (self.__length * self.__sign[i])
# Sets the value and wait that the read value reach the setpoint
def set_and_wait(self, value: np.array):
@@ -599,6 +627,7 @@ def __init__(self, elements: list[at.Element], poly: list[PolynomInfo], model: M
self.__polyIdx = []
self.__sign = []
self.__model = model
+ self.__length = _effective_lengths(elements[:1])[0]
for p in poly:
self.__poly.append(elements[0].__getattribute__(p.attName))
self.__polyIdx.append(p.index)
@@ -610,7 +639,7 @@ def get(self) -> np.array:
nbStrength = len(self.__poly)
s = np.zeros(nbStrength)
for i in range(nbStrength):
- s[i] = self.__poly[i][self.__polyIdx[i]] * self.__sign[i] * self.__elements[0].Length
+ s[i] = self.__poly[i][self.__polyIdx[i]] * self.__sign[i] * self.__length
return s
# Sets the value
@@ -626,7 +655,7 @@ def set(self, value: np.array):
nbStrength = len(self.__poly)
s = np.zeros(nbStrength)
for i in range(nbStrength):
- self.__poly[i][self.__polyIdx[i]] = value[i] / (self.__elements[0].Length * self.__sign[i])
+ self.__poly[i][self.__polyIdx[i]] = value[i] / (self.__length * self.__sign[i])
# Sets the value and wait that the read value reach the setpoint
def set_and_wait(self, value: np.array):
@@ -679,13 +708,14 @@ class BPMScalarAggregator(ScalarAggregator):
Return the value unit.
"""
- def __init__(self, ring: at.Lattice):
+ def __init__(self, ring: at.Lattice, twiss_in: dict):
"""
Initialize the BPMScalarAggregator.
"""
self._lattice = ring
self._refpts = []
self._matrices = []
+ self._twiss_in = twiss_in
def add_elem(self, elem: at.Element):
"""
@@ -735,9 +765,15 @@ def unit(self) -> str:
def _transform(self) -> np.array:
"""Transform the configured value for the lattice interface."""
- _, orbit = at.find_orbit(self._lattice, refpts=self._refpts)
+ if self._twiss_in is None:
+ _, orbit = at.find_orbit(self._lattice, refpts=self._refpts)
+ pts = orbit[:, [0, 2]] # Extract x,y
+ else:
+ _, _, elemdata = at.get_optics(self._lattice, refpts=self._refpts, twiss_in=self._twiss_in)
+ pts = [e.closed_orbit[[0, 2]] for e in elemdata]
+
ones = np.ones(len(self._refpts))
- pts = orbit[:, [0, 2]] # Extract x,y
+ # Transfom BPM coordinates (offset and tilt)
# Batch matrices multiplication (homogeneous coordinates)
return np.matmul(self._matrices, np.column_stack([pts, ones])[:, :, None]).squeeze(-1)
@@ -827,19 +863,25 @@ class RBpmArray(abstract.ReadFloatArray):
Return the value unit.
"""
- def __init__(self, element: at.Element, lattice: at.Lattice):
+ def __init__(self, element: at.Element, lattice: at.Lattice, twiss_in: dict):
"""
Initialize the RBpmArray.
"""
self._element = element
self._lattice = lattice
+ self._twiss_in = twiss_in
# Gets the value
def get(self) -> np.array:
"""Return the current value."""
index = self._lattice.index(self._element)
- _, orbit = at.find_orbit(self._lattice, refpts=index)
- pts = orbit[0, [0, 2]]
+ if self._twiss_in is None:
+ _, orbit = at.find_orbit(self._lattice, refpts=index)
+ pts = orbit[0, [0, 2]]
+ else:
+ _, _, elemdata = at.get_optics(self._lattice, refpts=index, twiss_in=self._twiss_in)
+ pts = elemdata[0].closed_orbit[[0, 2]]
+ # Transfom BPM coordinates (offset and tilt)
return np.dot(self._element._transform, np.hstack([pts, 1])) # Use homogeneous coordinates
# Gets the unit of the value
diff --git a/pyaml/lattice/attribute_linker.py b/pyaml/lattice/attribute_linker.py
index affa5bcf3..053ef10ee 100644
--- a/pyaml/lattice/attribute_linker.py
+++ b/pyaml/lattice/attribute_linker.py
@@ -109,7 +109,23 @@ def get_element_identifier(self, element: Element) -> LinkerIdentifier:
LinkerIdentifier
The identifier for linking the element
"""
- return PyAtAttributeIdentifier(self.linker_config_model.attribute_name, element.get_name())
+ return self.get_identifier_for_name(element.get_name())
+
+ def get_identifier_for_name(self, name: str) -> LinkerIdentifier:
+ """
+ Get the identifier for a name used in an element ``lattice_names`` selector.
+
+ Parameters
+ ----------
+ name : str
+ Expected value of the configured attribute.
+
+ Returns
+ -------
+ LinkerIdentifier
+ The identifier matching the lattice elements whose attribute equals ``name``
+ """
+ return PyAtAttributeIdentifier(self.linker_config_model.attribute_name, name)
def _test_at_element(self, identifier: PyAtAttributeIdentifier, element: at.Element) -> bool:
"""
diff --git a/pyaml/lattice/lattice_elements_linker.py b/pyaml/lattice/lattice_elements_linker.py
index ef11e559b..87703667c 100644
--- a/pyaml/lattice/lattice_elements_linker.py
+++ b/pyaml/lattice/lattice_elements_linker.py
@@ -70,6 +70,8 @@ class LatticeElementsLinker(ABC):
Set the lattice for element linking.
get_element_identifier(element)
Get the identifier for linking an element.
+ get_identifier_for_name(name)
+ Get the identifier for a name given in an element ``lattice_names`` selector.
get_at_elements(element_id)
Return a list of PyAT elements matching the given identifiers.
get_at_element(element_id)
@@ -130,6 +132,31 @@ def get_element_identifier(self, element: Element) -> LinkerIdentifier:
"""
pass
+ def get_identifier_for_name(self, name: str) -> LinkerIdentifier:
+ """
+ Get the identifier for a name used in an element ``lattice_names`` selector.
+
+ Called when a PyAML element selects its lattice elements explicitly
+ (``lattice_names: list(a,b)``, ``a@0,1`` or ``a#0..2``): each ``name`` of the
+ selector is resolved through the linker instead of the element name.
+
+ Parameters
+ ----------
+ name : str
+ Name given in the ``lattice_names`` selector.
+
+ Returns
+ -------
+ LinkerIdentifier
+ The identifier matching the lattice element(s) designated by ``name``.
+
+ Raises
+ ------
+ NotImplementedError
+ If the linker does not support ``lattice_names`` selectors.
+ """
+ raise NotImplementedError(f"{self.__class__.__name__} does not support 'lattice_names' selectors")
+
def _iter_matches(self, identifier: LinkerIdentifier) -> Iterable[at.Element]:
"""
Yield all lattice elements matching ``identifier``.
diff --git a/pyaml/lattice/simulator.py b/pyaml/lattice/simulator.py
index 071d66a8e..e0922ae38 100644
--- a/pyaml/lattice/simulator.py
+++ b/pyaml/lattice/simulator.py
@@ -10,7 +10,8 @@
import at
-from ..bpm.bpm import BPM
+from pyaml.diagnostics.bpm import BPM
+
from ..common.abstract_aggregator import ScalarAggregator
from ..common.element import Element, __pyaml_repr__
from ..common.exception import PyAMLException
@@ -47,6 +48,7 @@
from ..tuning_tools.tuning_tool import TuningTool
from ..validation import DynamicValidation, register_schema
from .lattice_elements_linker import LatticeElementsLinker
+from .twiss_in import TwissIn
if TYPE_CHECKING:
from ..configuration.unbound_element import UnboundElement
@@ -78,6 +80,8 @@ class Simulator(ElementHolder, DynamicValidation):
mat_key : str, optional
Variable name of the lattice when loading a MATLAB ``.mat``
lattice file.
+ twiss_in : TwissIn, optional
+ Describe input beam parameters of a tranfer line, when not specified the lattice is considered as a ring
linker : LatticeElementsLinker, optional
Custom linker used to associate PyAML elements with PyAT
lattice elements. If omitted, elements are matched by name.
@@ -122,6 +126,7 @@ def __init__(
name: str,
lattice: str,
mat_key: str | None = None,
+ twiss_in: TwissIn | None = None,
linker: LatticeElementsLinker | None = None,
description: str | None = None,
):
@@ -134,6 +139,11 @@ def __init__(
self._lattice = lattice
self._mat_key = mat_key
self.description = description
+ self.twiss_in = twiss_in
+ if twiss_in is None:
+ self._at_twiss_in = None
+ else:
+ self._at_twiss_in = self.twiss_in._to_at()
path: Path = ROOT.get() / self._lattice
@@ -225,9 +235,9 @@ def create_bpm_aggregators(self, bpms: list[BPM]) -> list[ScalarAggregator]:
list[ScalarAggregator]
Aggregators for combined, horizontal, and vertical BPM positions.
"""
- agg = BPMScalarAggregator(self.get_lattice())
- aggh = BPMHScalarAggregator(self.get_lattice())
- aggv = BPMVScalarAggregator(self.get_lattice())
+ agg = BPMScalarAggregator(self.get_lattice(), self._at_twiss_in)
+ aggh = BPMHScalarAggregator(self.get_lattice(), self._at_twiss_in)
+ aggv = BPMVScalarAggregator(self.get_lattice(), self._at_twiss_in)
for b in bpms:
e = self.get_at_elems(b)[0]
agg.add_elem(e)
@@ -291,7 +301,11 @@ def _fill_bpm(self, bpm: BPM) -> None:
if len(bpm_elt.Offset) != 2:
raise PyAMLException(f"BPM {bpm.get_name()} offset must be a 2-element array.")
update_bpm_transform_matrix(bpm_elt)
- self.bpm.add(bpm.attach(self, RBpmArray(bpm_elt, self.ring), RWBpmOffsetArray(bpm_elt), RWBpmTiltScalar(bpm_elt)))
+ self.diagnostic.bpm.add(
+ bpm.attach(
+ self, RBpmArray(bpm_elt, self.ring, self._at_twiss_in), RWBpmOffsetArray(bpm_elt), RWBpmTiltScalar(bpm_elt)
+ )
+ )
def _fill_rf_plant(self, rf_plant: RFPlant) -> None:
if rf_plant.transmitters:
@@ -387,6 +401,12 @@ def get_at_elems(self, element: Element) -> list[at.Element]:
"""
Resolve a PyAML element to matching PyAT lattice elements.
+ The ``lattice_names`` selector of the element is honoured with or without a
+ linker. With a linker, the names of the selector are resolved through
+ ``linker.get_identifier_for_name`` (e.g. the configured attribute for
+ ``pyaml.lattice.attribute_linker``) instead of ``FamName``; without a
+ selector the linker uses the element name.
+
Parameters
----------
element : Element
@@ -398,11 +418,28 @@ def get_at_elems(self, element: Element) -> list[at.Element]:
Matching Accelerator Toolbox lattice elements.
"""
if self._linker:
- identifier = self._linker.get_element_identifier(element)
- element_list = self._linker.get_at_elements(identifier)
- if not element_list:
- raise PyAMLException(f"{identifier} not found in lattice:{self._lattice}")
- return element_list
+ if element.get_lattice_names() is None:
+ # By name
+ return self._linker.get_at_elements(self._linker.get_element_identifier(element))
+ # By list
+ nameList = self.get_names(element)
+ if nameList is not None:
+ identifiers = [self._linker.get_identifier_for_name(name) for name in nameList]
+ return self._linker.get_at_elements(identifiers)
+ # By name or indices
+ name, indices = self.get_indices(element)
+ if name is None:
+ # Direct indexing in the ring
+ return [self.ring[idx] for idx in indices]
+ elts = self._linker.get_at_elements(self._linker.get_identifier_for_name(name))
+ if indices is None:
+ return elts
+ try:
+ return [elts[idx] for idx in indices]
+ except IndexError as err:
+ strErr = f"{element.get_name()}: Invalid lattice_names index "
+ strErr += f"for {element.get_lattice_names()}, {len(elts)} element(s) found for {name}"
+ raise PyAMLException(strErr) from err
else:
# By list
nameList = self.get_names(element)
diff --git a/pyaml/lattice/twiss_in.py b/pyaml/lattice/twiss_in.py
new file mode 100644
index 000000000..c42ee6c7e
--- /dev/null
+++ b/pyaml/lattice/twiss_in.py
@@ -0,0 +1,52 @@
+"""
+Initial input beam parameters for a transfer line
+"""
+
+import numpy
+
+from ..validation import DynamicValidation, register_schema
+
+# Define the main class name for this module
+PYAMLCLASS = "TwissIn"
+
+
+@register_schema
+class TwissIn(DynamicValidation):
+ """
+ Class that describes input beam parameters of a transfer line
+
+ Attributes
+ ----------
+ alpha : list[float]
+ Initial alpha parameters (x,y)
+ beta : list[float] | None
+ Initial beta parameters (x,y), default [0,0]
+ position : list[float] | None
+ Initial position (6D), default [0,0,0,0,0,0]
+ dispersion : list[float] | None
+ Initial dispersion (4D), default [0,0,0,0]
+ """
+
+ def __init__(
+ self,
+ alpha: list[float],
+ beta: list[float] | None = None,
+ position: list[float] | None = None,
+ dispersion: list[float] | None = None,
+ ):
+ """
+ Create TwissIn object
+ """
+ super().__init__()
+ self.alpha = alpha
+ self.beta = beta if beta is not None else [0.0, 0.0]
+ self.position = position if position is not None else [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
+ self.dispersion = dispersion if dispersion is not None else [0.0, 0.0, 0.0, 0.0]
+
+ def _to_at(self) -> dict:
+ return {
+ "beta": numpy.array(self.alpha, dtype=float),
+ "alpha": numpy.array(self.beta, dtype=float),
+ "closed_orbit": numpy.array(self.position, dtype=float),
+ "dispersion": numpy.array(self.dispersion, dtype=float),
+ }
diff --git a/pyaml/magnet/cfm_magnet.py b/pyaml/magnet/cfm_magnet.py
index eb7db64e8..83c5578fd 100644
--- a/pyaml/magnet/cfm_magnet.py
+++ b/pyaml/magnet/cfm_magnet.py
@@ -93,6 +93,21 @@ class CombinedFunctionMagnet(Element, DynamicValidation):
PyAMLException
If the mapping is invalid, if an unsupported multipole is requested, or
if the model does not provide the required multipole information.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.cfm_magnet
+ name: COMBINED_FUNCTION_MAGNET_NAME
+ mapping:
+ - [B2, SEXTUPOLE_NAME]
+ - [B0, HORIZONTAL_CORRECTOR_NAME]
+ - [A0, VERTICAL_CORRECTOR_NAME]
+ model: path/to/combined_function_magnet_model.yaml
"""
def __init__(
diff --git a/pyaml/magnet/hcorrector.py b/pyaml/magnet/hcorrector.py
index 84bfbfb2e..968c4c330 100644
--- a/pyaml/magnet/hcorrector.py
+++ b/pyaml/magnet/hcorrector.py
@@ -44,6 +44,18 @@ class HCorrector(Magnet, DynamicValidation):
-------
attach(peer, strength, hardware)
Return an attached copy with a bound horizontal-angle handle.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.hcorrector
+ name: HORIZONTAL_CORRECTOR_NAME
+ lattice_names: LATTICE_CORRECTOR_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomB", 0, HORIZONTAL_KICK_SIGN)
diff --git a/pyaml/magnet/identity_cfm_model.py b/pyaml/magnet/identity_cfm_model.py
index 0f578f2cc..497afb6eb 100644
--- a/pyaml/magnet/identity_cfm_model.py
+++ b/pyaml/magnet/identity_cfm_model.py
@@ -71,6 +71,18 @@ class IdentityCFMagnetModel(MagnetModel, DynamicValidation):
Return whether the model provides physics strengths.
has_hardware()
Return whether the model provides hardware values.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.identity_cfm_model
+ multipoles: [B2, B0, A0]
+ units: [1/m**2, rad, rad]
+ physics:
+ - DEVICE/SEXTUPOLE_STRENGTH
+ - DEVICE/HORIZONTAL_KICK
+ - DEVICE/VERTICAL_KICK
"""
def __init__(
diff --git a/pyaml/magnet/identity_model.py b/pyaml/magnet/identity_model.py
index 9d5f94f6a..744321d3d 100644
--- a/pyaml/magnet/identity_model.py
+++ b/pyaml/magnet/identity_model.py
@@ -64,6 +64,14 @@ class IdentityMagnetModel(MagnetModel, DynamicValidation):
-----
The model does not perform any numerical conversion: strengths are returned
as hardware values and hardware values are returned as strengths.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.identity_model
+ unit: 1/m
+ physics: DEVICE/MAGNET_STRENGTH
"""
def __init__(
diff --git a/pyaml/magnet/linear_cfm_model.py b/pyaml/magnet/linear_cfm_model.py
index 75489526b..2288df68d 100644
--- a/pyaml/magnet/linear_cfm_model.py
+++ b/pyaml/magnet/linear_cfm_model.py
@@ -101,6 +101,23 @@ class LinearCFMagnetModel(MagnetModel, DynamicValidation):
Set the magnetic rigidity used for conversion.
has_hardware()
Return whether the model provides hardware values.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.linear_cfm_model
+ multipoles: [B0, A0]
+ units: [rad, rad]
+ hardware_units: [A, A]
+ curves:
+ - type: pyaml.magnet.csvcurve
+ file: path/to/horizontal_excitation_curve.csv
+ - type: pyaml.magnet.csvcurve
+ file: path/to/vertical_excitation_curve.csv
+ powerconverters:
+ - DEVICE/HORIZONTAL_POWER_CONVERTER_CURRENT
+ - DEVICE/VERTICAL_POWER_CONVERTER_CURRENT
"""
def __init__(
diff --git a/pyaml/magnet/linear_model.py b/pyaml/magnet/linear_model.py
index 148629bf5..6ffa0608d 100644
--- a/pyaml/magnet/linear_model.py
+++ b/pyaml/magnet/linear_model.py
@@ -66,6 +66,20 @@ class LinearMagnetModel(MagnetModel, DynamicValidation):
If a curve is provided, the model interpolates between strength and current
values using the curve and its inverse. If no curve is provided, the model
uses a simple linear relation with the stored scaling factor and offset.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.linear_model
+ unit: 1/m
+ hardware_unit: A
+ calibration_factor: 1.0
+ calibration_offset: 0.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: path/to/excitation_curve.csv
+ powerconverter: DEVICE/POWER_CONVERTER_CURRENT
"""
def __init__(
diff --git a/pyaml/magnet/linear_serialized_model.py b/pyaml/magnet/linear_serialized_model.py
index 7b30c2ea5..1e912c113 100644
--- a/pyaml/magnet/linear_serialized_model.py
+++ b/pyaml/magnet/linear_serialized_model.py
@@ -177,6 +177,20 @@ class LinearSerializedMagnetModel(MagnetModel, DynamicValidation):
-----
The number of magnets is inferred from the longest list among the supplied
configuration values. Scalars are expanded to match that length.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.linear_serialized_model
+ unit: 1/m
+ hardware_unit: A
+ calibration_factors: 1.0
+ calibration_offsets: 0.0
+ curves:
+ type: pyaml.magnet.csvcurve
+ file: path/to/excitation_curve.csv
+ powerconverter: DEVICE/POWER_CONVERTER_CURRENT
"""
def __init__(
diff --git a/pyaml/magnet/octupole.py b/pyaml/magnet/octupole.py
index 2247c1afd..41749abf7 100644
--- a/pyaml/magnet/octupole.py
+++ b/pyaml/magnet/octupole.py
@@ -38,6 +38,18 @@ class Octupole(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.octupole
+ name: OCTUPOLE_NAME
+ lattice_names: LATTICE_OCTUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomB", 3)
diff --git a/pyaml/magnet/quadrupole.py b/pyaml/magnet/quadrupole.py
index c3b749a12..90afac558 100644
--- a/pyaml/magnet/quadrupole.py
+++ b/pyaml/magnet/quadrupole.py
@@ -38,6 +38,18 @@ class Quadrupole(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.quadrupole
+ name: QUADRUPOLE_NAME
+ lattice_names: LATTICE_QUADRUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomB", 1)
diff --git a/pyaml/magnet/serialized_magnet.py b/pyaml/magnet/serialized_magnet.py
index 58ef44222..ddfe1733d 100644
--- a/pyaml/magnet/serialized_magnet.py
+++ b/pyaml/magnet/serialized_magnet.py
@@ -221,6 +221,21 @@ class SerializedMagnets(Element, DynamicValidation):
The serialized group stores a virtual magnet for each underlying element. When
attached, each virtual magnet is bound to the same peer and the group exposes
aggregate strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.serialized_magnet
+ name: SERIALIZED_QUADRUPOLES
+ function: B1
+ elements:
+ - QUADRUPOLE_1
+ - QUADRUPOLE_2
+ model: path/to/serialized_magnet_model.yaml
"""
def __init__(
diff --git a/pyaml/magnet/sextupole.py b/pyaml/magnet/sextupole.py
index 7928c6395..7380ab9eb 100644
--- a/pyaml/magnet/sextupole.py
+++ b/pyaml/magnet/sextupole.py
@@ -38,6 +38,18 @@ class Sextupole(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.sextupole
+ name: SEXTUPOLE_NAME
+ lattice_names: LATTICE_SEXTUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomB", 2)
diff --git a/pyaml/magnet/skewoctu.py b/pyaml/magnet/skewoctu.py
index b76bf3ccc..7fb69abcd 100644
--- a/pyaml/magnet/skewoctu.py
+++ b/pyaml/magnet/skewoctu.py
@@ -38,6 +38,18 @@ class SkewOctu(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.skewoctu
+ name: SKEW_OCTUPOLE_NAME
+ lattice_names: LATTICE_SKEW_OCTUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomA", 3)
diff --git a/pyaml/magnet/skewquad.py b/pyaml/magnet/skewquad.py
index abf6bab9b..40a7b054f 100644
--- a/pyaml/magnet/skewquad.py
+++ b/pyaml/magnet/skewquad.py
@@ -38,6 +38,18 @@ class SkewQuad(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.skewquad
+ name: SKEW_QUADRUPOLE_NAME
+ lattice_names: LATTICE_SKEW_QUADRUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomA", 1)
diff --git a/pyaml/magnet/skewsext.py b/pyaml/magnet/skewsext.py
index 5d82c1d16..cc483684c 100644
--- a/pyaml/magnet/skewsext.py
+++ b/pyaml/magnet/skewsext.py
@@ -38,6 +38,18 @@ class SkewSext(Magnet, DynamicValidation):
See Also
--------
Magnet : Base class listing the strength and hardware accessors.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.skewsext
+ name: SKEW_SEXTUPOLE_NAME
+ lattice_names: LATTICE_SKEW_SEXTUPOLE_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomA", 2)
diff --git a/pyaml/magnet/spline_model.py b/pyaml/magnet/spline_model.py
index e38734451..cdda528cb 100644
--- a/pyaml/magnet/spline_model.py
+++ b/pyaml/magnet/spline_model.py
@@ -70,6 +70,19 @@ class SplineMagnetModel(MagnetModel, DynamicValidation):
-----
The magnet rigidity ``brho`` must be set with :meth:`set_magnet_rigidity`
before using the conversion methods.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ type: pyaml.magnet.spline_model
+ unit: 1/m
+ hardware_unit: A
+ alpha: 0.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: path/to/excitation_curve.csv
+ powerconverter: DEVICE/POWER_CONVERTER_CURRENT
"""
def __init__(
diff --git a/pyaml/magnet/vcorrector.py b/pyaml/magnet/vcorrector.py
index f9614754f..80a379904 100644
--- a/pyaml/magnet/vcorrector.py
+++ b/pyaml/magnet/vcorrector.py
@@ -43,6 +43,18 @@ class VCorrector(Magnet, DynamicValidation):
-------
attach(peer, strength, hardware)
Return an attached copy with a bound vertical-angle handle.
+
+ Configuration
+ -------------
+ The model can be defined inline or in a separate file. See
+ :mod:`pyaml.magnet.model` and its subclasses for model configuration.
+
+ .. code-block:: yaml
+
+ - type: pyaml.magnet.vcorrector
+ name: VERTICAL_CORRECTOR_NAME
+ lattice_names: LATTICE_CORRECTOR_NAME
+ model: path/to/magnet_model.yaml
"""
polynom = PolynomInfo("PolynomA", 0)
diff --git a/pyaml/rf/rf_plant.py b/pyaml/rf/rf_plant.py
index 4a0055370..62e5954b6 100644
--- a/pyaml/rf/rf_plant.py
+++ b/pyaml/rf/rf_plant.py
@@ -54,6 +54,19 @@ class RFPlant(Element, DynamicValidation):
-------
attach(peer, frequency, voltage)
Return a copy attached to RF read/write handles.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.rf.rf_plant
+ name: RF
+ masterclock: DEVICE/RF_FREQUENCY
+ transmitters:
+ - type: pyaml.rf.rf_transmitter
+ name: RF_TRANSMITTER
+ cavities: [CAVITY_1, CAVITY_2]
+ voltage: DEVICE/RF_VOLTAGE
"""
def __init__(
diff --git a/pyaml/rf/rf_transmitter.py b/pyaml/rf/rf_transmitter.py
index 69abe2296..7b1677fda 100644
--- a/pyaml/rf/rf_transmitter.py
+++ b/pyaml/rf/rf_transmitter.py
@@ -55,6 +55,21 @@ class RFTransmitter(Element, DynamicValidation):
-------
attach(peer, voltage, phase)
Return a copy with voltage and phase handles attached.
+
+ Configuration
+ -------------
+ RF transmitters are normally nested under an
+ :class:`~pyaml.rf.rf_plant.RFPlant`.
+
+ .. code-block:: yaml
+
+ - type: pyaml.rf.rf_transmitter
+ name: RF_TRANSMITTER
+ cavities: [CAVITY_1, CAVITY_2]
+ voltage: DEVICE/RF_VOLTAGE
+ phase: DEVICE/RF_PHASE
+ harmonic: 1
+ distribution: 1
"""
def __init__(
diff --git a/pyaml/tuning_tools/bba.py b/pyaml/tuning_tools/bba.py
index ed0b8cc27..feb8bccd3 100644
--- a/pyaml/tuning_tools/bba.py
+++ b/pyaml/tuning_tools/bba.py
@@ -23,8 +23,9 @@
from .measurement_tool import MeasurementTool
if TYPE_CHECKING:
+ from pyaml.diagnostics.bpm import BPM
+
from ..arrays.bpm_array import BPMArray
- from ..bpm.bpm import BPM
from ..magnet.magnet import Magnet
logger = logging.getLogger(__name__)
@@ -106,6 +107,22 @@ class BBA(MeasurementTool, DynamicValidation):
Vertical corrector used for the alignment.
quadrupole : Magnet
Quadrupole being aligned.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.bba
+ name: BBA
+ bpm_array_name: BPM
+ bpm_name: BPM_NAME
+ hcorr_name: HORIZONTAL_CORRECTOR_NAME
+ vcorr_name: VERTICAL_CORRECTOR_NAME
+ quad_name: QUADRUPOLE_NAME
+ hcorr_delta: 1e-5
+ vcorr_delta: 1e-5
+ hquad_delta: 5e-3
+ vquad_delta: 5e-3
"""
def __init__(
@@ -147,13 +164,13 @@ def __init__(
def bpms(self) -> "BPMArray":
"""Return the BPM array used for the measurement."""
self.check_peer()
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def bpm(self) -> "BPM":
"""Return the reference BPM used for the alignment."""
self.check_peer()
- return self.peer.bpm.get(self.bpm_name)
+ return self.peer.diagnostic.bpm.get(self.bpm_name)
@property
def hcorrector(self) -> "Magnet":
@@ -190,7 +207,7 @@ def measure(
sr = Accelerator.load("tests/config/EBSOrbit.yaml")
SR = sr.design
- bba = SR.get_bba("BBA-BPM_C04-04")
+ bba = SR.tool.get("BBA-BPM_C04-04")
# Add a misalignement
SR.get_bpm("BPM_C04-04").offset.set([20e-6,-15e-6])
diff --git a/pyaml/tuning_tools/bba2.py b/pyaml/tuning_tools/bba2.py
index b1b7bb071..adaa9224d 100644
--- a/pyaml/tuning_tools/bba2.py
+++ b/pyaml/tuning_tools/bba2.py
@@ -18,8 +18,9 @@
from .measurement_tool import MeasurementTool
if TYPE_CHECKING:
+ from pyaml.diagnostics.bpm import BPM
+
from ..arrays.bpm_array import BPMArray
- from ..bpm.bpm import BPM
from ..magnet.magnet import Magnet
from .tune import Tune
@@ -183,6 +184,22 @@ class BBA2(MeasurementTool, DynamicValidation):
Return the quadrupole being aligned.
tune_correction
Return the tune-correction tool used during alignment.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.bba2
+ name: BBA_WITH_TUNE_CORRECTION
+ bpm_array_name: BPM
+ bpm_name: BPM_NAME
+ hcorr_name: HORIZONTAL_CORRECTOR_NAME
+ vcorr_name: VERTICAL_CORRECTOR_NAME
+ quad_name: QUADRUPOLE_NAME
+ tune_correction_name: TUNE_CORRECTION
+ hcorr_delta: 1e-5
+ vcorr_delta: 1e-5
+ quad_delta: 5e-3
"""
def __init__(
@@ -228,13 +245,13 @@ def __init__(
def bpms(self) -> "BPMArray":
"""Return the BPM array used for the measurement."""
self.check_peer()
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def bpm(self) -> "BPM":
"""Return the reference BPM used for the alignment."""
self.check_peer()
- return self.peer.bpm.get(self.bpm_name)
+ return self.peer.diagnostic.bpm.get(self.bpm_name)
@property
def hcorrector(self) -> "Magnet":
@@ -258,7 +275,7 @@ def quadrupole(self) -> "Magnet":
def tune_correction(self) -> "Tune":
"""Return the tune-correction tool used during alignment."""
self.check_peer()
- return self.peer.get_tune_tuning(self.tune_correction_name)
+ return self.peer.tool.get(self.tune_correction_name)
@staticmethod
def _x_intercept(x, k, n):
@@ -343,9 +360,9 @@ def _init_responses(
quad = design.magnet.get(quadname)
sth = design.magnet.get(steererhname)
stv = design.magnet.get(steerervname)
- orbit = design.bpms.get(bpmname).positions
- tune_design = design.get_tune_tuning(tunename)
- tune_live = self._peer.get_tune_tuning(tunename)
+ orbit = design.diagnostic.bpms.get(bpmname).positions
+ tune_design = design.tool.get(tunename)
+ tune_live = self._peer.tool.get(tunename)
# Get tune from live and adjust the model to improve quad response phase
tune0 = tune_design.readback()
@@ -569,7 +586,7 @@ def measure(
sr = Accelerator.load("tests/config/EBSOrbit.yaml")
SR = sr.live
- bba = SR.get_bba("BBA2-BPM_C04-04")
+ bba = SR.tool.get("BBA2-BPM_C04-04")
# Add a misalignement
SR.get_bpm("BPM_C04-04").offset.set([200e-6,-150e-6])
diff --git a/pyaml/tuning_tools/chromaticity.py b/pyaml/tuning_tools/chromaticity.py
index e1aed2640..d43c46726 100644
--- a/pyaml/tuning_tools/chromaticity.py
+++ b/pyaml/tuning_tools/chromaticity.py
@@ -72,6 +72,16 @@ class Chromaticity(TuningTool, DynamicValidation):
Calculate sextupole-strength changes for a chromaticity change.
add(dchroma, wait_time=0.0)
Apply a chromaticity correction relative to the current setpoint.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.chromaticity
+ name: CHROMATICITY_CORRECTION
+ sextu_array_name: SEXTUPOLES
+ chromaticity_monitor_name: CHROMATICITY_MONITOR
+ response_matrix: path/to/chromaticity_response.json
"""
def __init__(
@@ -125,7 +135,7 @@ def load(self, load_path: Path):
def chromaticity_monitor(self) -> "ChromaticityMonitor":
"""Return the chromaticity monitor used for readback."""
self.check_peer()
- return self.peer.get_chromaticity_monitor(self._chromaticity_monitor_name)
+ return self.peer.tool.get(self._chromaticity_monitor_name)
@property
def sextupoles(self) -> "MagnetArray":
diff --git a/pyaml/tuning_tools/chromaticity_monitor.py b/pyaml/tuning_tools/chromaticity_monitor.py
index c1da25079..c03e284f0 100644
--- a/pyaml/tuning_tools/chromaticity_monitor.py
+++ b/pyaml/tuning_tools/chromaticity_monitor.py
@@ -140,6 +140,18 @@ class ChromaticityMonitor(MeasurementTool, DynamicValidation):
fit(deltas, Q, order, orbit=None, fit_disp_order=None, do_plot=False)
Compute chromaticity (and dispersion) from input data and update
:py:attr:`~pyaml.tuning_tools.measurement_tool.MeasurementTool.latest_measurement`.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.chromaticity_monitor
+ name: CHROMATICITY_MONITOR
+ betatron_tune_name: BETATRON_TUNE
+ rf_plant_name: RF
+ bpm_array_name: BPM
+ fit_dispersion: true
+ n_step: 5
"""
def __init__(
@@ -189,7 +201,7 @@ def __init__(
def tune_monitor(self) -> "BetatronTuneMonitor":
"""Return the betatron tune monitor used for measurements."""
self.check_peer()
- return self.peer.get_betatron_tune_monitor(self.betatron_tune_name)
+ return self.peer.diagnostic.get(self.betatron_tune_name)
@property
def rf_plant(self) -> "RFPlant":
@@ -203,7 +215,7 @@ def bpms(self) -> "BPMArray | None":
self.check_peer()
if self.bpm_array_name is None:
return None
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def chromaticity(self) -> ReadFloatArray:
diff --git a/pyaml/tuning_tools/chromaticity_response_matrix.py b/pyaml/tuning_tools/chromaticity_response_matrix.py
index 6746f4034..23d712ed4 100644
--- a/pyaml/tuning_tools/chromaticity_response_matrix.py
+++ b/pyaml/tuning_tools/chromaticity_response_matrix.py
@@ -68,6 +68,16 @@ class ChromaticityResponseMatrix(MeasurementTool, DynamicValidation):
Sextupole array used for the measurement.
chromaticity_monitor : ChromaticityMonitor
Chromaticity monitor used for the measurement.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.chromaticity_response_matrix
+ name: CHROMATICITY_RESPONSE_MATRIX
+ sextu_array_name: SEXTUPOLES
+ chromaticity_name: CHROMATICITY_MONITOR
+ sextu_delta: 1e-6
"""
def __init__(
@@ -105,7 +115,7 @@ def sextupoles(self) -> "MagnetArray":
def chromaticity_monitor(self) -> "ChromaticityMonitor":
"""Return the chromaticity monitor used for the measurement."""
self.check_peer()
- return self.peer.get_chromaticity_monitor(self.chromaticity_name)
+ return self.peer.tool.get(self.chromaticity_name)
def measure(
self,
@@ -141,10 +151,10 @@ def callback(action: Action, data:dict):
sr = Accelerator.load("tests/config/EBSOrbit.yaml")
acc = sr.design
- if acc.crm.measure(callback=callback):
- acc.crm.save("ideal_crm.json")
- acc.crm.save("ideal_crm.yaml", with_type="yaml")
- acc.crm.save("ideal_crm.npz", with_type="npz")
+ if acc.tool.crm.measure(callback=callback):
+ acc.tool.crm.save("ideal_crm.json")
+ acc.tool.crm.save("ideal_crm.yaml", with_type="yaml")
+ acc.tool.crm.save("ideal_crm.npz", with_type="npz")
Parameters
----------
diff --git a/pyaml/tuning_tools/dispersion.py b/pyaml/tuning_tools/dispersion.py
index 6bbc3844b..81fccb11a 100644
--- a/pyaml/tuning_tools/dispersion.py
+++ b/pyaml/tuning_tools/dispersion.py
@@ -65,6 +65,16 @@ class Dispersion(MeasurementTool, DynamicValidation):
Measure beam dispersion by varying the RF frequency.
get()
Return the most recently measured dispersion data.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.dispersion
+ name: DISPERSION
+ bpm_array_name: BPM
+ rf_plant_name: RF
+ frequency_delta: 100
"""
def __init__(self, name: str, bpm_array_name: str, rf_plant_name: str, frequency_delta: float):
@@ -81,7 +91,7 @@ def __init__(self, name: str, bpm_array_name: str, rf_plant_name: str, frequency
def bpms(self) -> "BPMArray":
"""Return the BPM array used for orbit readback."""
self.check_peer()
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def rf_plant(self) -> "RFPlant":
diff --git a/pyaml/tuning_tools/measurement_tool.py b/pyaml/tuning_tools/measurement_tool.py
index 646d38ed9..acdc57892 100644
--- a/pyaml/tuning_tools/measurement_tool.py
+++ b/pyaml/tuning_tools/measurement_tool.py
@@ -182,7 +182,7 @@ def callback(action: Action, data: dict):
return True
# Measure a tune response matrix using the above callback
- sr.design.trm.measure(callback=callback)
+ sr.design.tool.trm.measure(callback=callback)
Parameters
----------
diff --git a/pyaml/tuning_tools/orbit.py b/pyaml/tuning_tools/orbit.py
index 3f2c8b397..61468323f 100644
--- a/pyaml/tuning_tools/orbit.py
+++ b/pyaml/tuning_tools/orbit.py
@@ -94,6 +94,19 @@ class Orbit(TuningTool, DynamicValidation):
Return the configured RF-frequency correction weight.
post_init()
Bind orbit corrector and RF handles after attachment.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.orbit
+ name: ORBIT_CORRECTION
+ bpm_array_name: BPM
+ hcorr_array_name: HORIZONTAL_CORRECTORS
+ vcorr_array_name: VERTICAL_CORRECTORS
+ rf_plant_name: RF
+ singular_values: 16
+ response_matrix: path/to/orbit_response.json
"""
def __init__(
@@ -199,7 +212,7 @@ def response_matrix(self) -> OrbitResponseMatrixData | None:
def bpms(self) -> BPMArray:
"""Return the BPM array used for orbit readback."""
self.check_peer()
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def hcorrectors(self) -> MagnetArray:
diff --git a/pyaml/tuning_tools/orbit_response_matrix.py b/pyaml/tuning_tools/orbit_response_matrix.py
index 7b065b49c..14bd96d2a 100644
--- a/pyaml/tuning_tools/orbit_response_matrix.py
+++ b/pyaml/tuning_tools/orbit_response_matrix.py
@@ -98,6 +98,17 @@ class OrbitResponseMatrix(MeasurementTool, DynamicValidation):
-------
measure(...)
Measure orbit response matrix.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.orbit_response_matrix
+ name: ORBIT_RESPONSE_MATRIX
+ bpm_array_name: BPM
+ hcorr_array_name: HORIZONTAL_CORRECTORS
+ vcorr_array_name: VERTICAL_CORRECTORS
+ corrector_delta: 1e-6
"""
def __init__(
@@ -130,7 +141,7 @@ def __init__(
def bpms(self) -> "BPMArray":
"""Return the BPM array used for orbit readback."""
self.check_peer()
- return self.peer.bpms.get(self.bpm_array_name)
+ return self.peer.diagnostic.bpms.get(self.bpm_array_name)
@property
def hcorrectors(self) -> "MagnetArray":
@@ -162,10 +173,10 @@ def measure(
sr = Accelerator.load("MyAccelerator.yaml")
acc = sr.design
- if acc.orm.measure():
- acc.orm.save("ideal_orm.json")
- acc.orm.save("ideal_orm.yaml", with_type="yaml")
- acc.orm.save("ideal_orm.npz", with_type="npz")
+ if acc.tool.orm.measure():
+ acc.tool.orm.save("ideal_orm.json")
+ acc.tool.orm.save("ideal_orm.yaml", with_type="yaml")
+ acc.tool.orm.save("ideal_orm.npz", with_type="npz")
Parameters
----------
diff --git a/pyaml/tuning_tools/tune.py b/pyaml/tuning_tools/tune.py
index 068caf137..18811bba3 100644
--- a/pyaml/tuning_tools/tune.py
+++ b/pyaml/tuning_tools/tune.py
@@ -86,6 +86,16 @@ class Tune(TuningTool, DynamicValidation):
Calculate quadrupole-strength changes for a tune change.
add(dtune, wait_time=0.0)
Apply a tune correction relative to the current setpoint.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.tune
+ name: TUNE_CORRECTION
+ quad_array_name: QUADRUPOLES
+ betatron_tune_name: BETATRON_TUNE
+ response_matrix: path/to/tune_response.json
"""
def __init__(
@@ -143,7 +153,7 @@ def response_matrix(self) -> ResponseMatrixData | None:
def tune_monitor(self) -> "BetatronTuneMonitor":
"""Return the betatron tune monitor used by the correction."""
self.check_peer()
- return self.peer.get_betatron_tune_monitor(self.betatron_tune_name)
+ return self.peer.diagnostic.get(self.betatron_tune_name)
@property
def quadrupoles(self) -> "MagnetArray":
diff --git a/pyaml/tuning_tools/tune_response_matrix.py b/pyaml/tuning_tools/tune_response_matrix.py
index 023b86cad..fe65e0d14 100644
--- a/pyaml/tuning_tools/tune_response_matrix.py
+++ b/pyaml/tuning_tools/tune_response_matrix.py
@@ -109,6 +109,16 @@ class TuneResponseMatrix(MeasurementTool, DynamicValidation):
Quadrupole strengths are restored after each individual scan and again when
the measurement exits because of an error or interruption.
+
+ Configuration
+ -------------
+ .. code-block:: yaml
+
+ - type: pyaml.tuning_tools.tune_response_matrix
+ name: TUNE_RESPONSE_MATRIX
+ quad_array_name: QUADRUPOLES
+ betatron_tune_name: BETATRON_TUNE
+ quad_delta: 1e-4
"""
def __init__(
@@ -144,7 +154,7 @@ def quadrupoles(self) -> "MagnetArray":
def tune_monitor(self) -> "BetatronTuneMonitor":
"""Return the betatron tune monitor used for the measurement."""
self.check_peer()
- return self.peer.get_betatron_tune_monitor(self.betatron_tune_name)
+ return self.peer.diagnostic.get(self.betatron_tune_name)
def measure(
self,
@@ -180,10 +190,10 @@ def callback(action: Action, data:dict):
sr = Accelerator.load("tests/config/EBSTune.yaml")
acc = sr.design
- if acc.trm.measure(n_avg_meas=3,sleep_between_meas=5,callback=callback):
- acc.trm.save("ideal_trm.json")
- acc.trm.save("ideal_trm.yaml", with_type="yaml")
- acc.trm.save("ideal_trm.npz", with_type="npz")
+ if acc.tool.trm.measure(n_avg_meas=3,sleep_between_meas=5,callback=callback):
+ acc.tool.trm.save("ideal_trm.json")
+ acc.tool.trm.save("ideal_trm.yaml", with_type="yaml")
+ acc.tool.trm.save("ideal_trm.npz", with_type="npz")
Parameters
----------
diff --git a/tests/arrays/test_array_selection_types.py b/tests/arrays/test_array_selection_types.py
index d5cc782bf..8dce804ef 100644
--- a/tests/arrays/test_array_selection_types.py
+++ b/tests/arrays/test_array_selection_types.py
@@ -2,6 +2,7 @@
from pyaml.arrays.element_array import ElementArray
from pyaml.arrays.magnet_array import MagnetArray
+from pyaml.common.exception import PyAMLException
@pytest.fixture
@@ -43,7 +44,7 @@ def test_magnet_holder_selection_uses_the_same_typing(design):
def test_mixed_array_stays_generic_until_only_magnets_are_selected(design):
- mixed = design.get_elements("ElArray")
+ mixed = design.get("ElArray")
assert type(mixed[:]) is ElementArray
assert mixed[:].names() == mixed.names()
@@ -60,3 +61,41 @@ def test_empty_selections_and_integer_indexing_keep_their_behavior(design):
assert magnets["UNKNOWN*"] == []
assert magnets[0] is design.magnet.get(magnets.names()[0])
assert type(magnets - magnets) is list
+
+
+def test_literal_name_miss_raises(design):
+ magnets = design.magnets.get()
+
+ with pytest.raises(PyAMLException):
+ magnets["UNKNOWN"]
+ with pytest.raises(PyAMLException):
+ design.magnets["UNKNOWN"]
+
+
+def test_literal_name_hit_still_returns_a_single_element_array(design):
+ magnets = design.magnets.get()
+
+ selected = magnets["SH1A-C01-H"]
+ assert type(selected) is MagnetArray
+ assert selected.names() == ["SH1A-C01-H"]
+
+
+def test_bracket_only_pattern_is_a_wildcard(design):
+ magnets = design.magnets.get()
+ assert sorted(magnets["SH1A-C0[12]-H"].names()) == ["SH1A-C01-H", "SH1A-C02-H"]
+
+
+def test_regex_pattern_is_supported(design):
+ magnets = design.magnets.get()
+ assert sorted(magnets["re:^SH1A-C0[12]-H$"].names()) == ["SH1A-C01-H", "SH1A-C02-H"]
+
+
+def test_list_of_patterns_is_supported(design):
+ magnets = design.magnets.get()
+ selected = magnets[["SH1A-C01-H", "SH1A-C02-H"]]
+ assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H"]
+
+
+def test_wildcard_matching_is_case_sensitive(design):
+ magnets = design.magnets.get()
+ assert magnets["sh1a*"] == []
diff --git a/tests/arrays/test_arrays.py b/tests/arrays/test_arrays.py
index 7ae9b8710..5bd02a3d6 100644
--- a/tests/arrays/test_arrays.py
+++ b/tests/arrays/test_arrays.py
@@ -128,32 +128,32 @@ def test_arrays(install_test_package):
# Test BPMs array
# Using aggregator
- pos = sr.design.bpms.get("BPMS").positions.get()
+ pos = sr.design.diagnostic.bpms.get("BPMS").positions.get()
assert np.abs(pos[0][0] - 7.22262850488348e-05) < 1e-10
assert np.abs(pos[0][1] - 3.4291613955705856e-05) < 1e-10
assert np.abs(pos[1][0] + 1.1696152238807462e-04) < 1e-10
assert np.abs(pos[1][1] - 7.4265634524358045e-06) < 1e-10
# Using aggregator (h and v)
- pos_h = sr.design.bpms.get("BPMS").h.get()
- pos_v = sr.design.bpms.get("BPMS").v.get()
+ pos_h = sr.design.diagnostic.bpms.get("BPMS").h.get()
+ pos_v = sr.design.diagnostic.bpms.get("BPMS").v.get()
assert np.all(np.isclose(pos[:, 0], pos_h, rtol=1e-15, atol=1e-15))
assert np.all(np.isclose(pos[:, 1], pos_v, rtol=1e-15, atol=1e-15))
# Test BPM transformation matrices
- sr.design.bpm.get("BPM_C04-01").offset.set([0.1, 0.2])
- sr.design.bpm.get("BPM_C04-02").offset.set([0.3, 0.4])
- pos = sr.design.bpms.get("BPMS").positions.get()
+ sr.design.diagnostic.bpm.get("BPM_C04-01").offset.set([0.1, 0.2])
+ sr.design.diagnostic.bpm.get("BPM_C04-02").offset.set([0.3, 0.4])
+ pos = sr.design.diagnostic.bpms.get("BPMS").positions.get()
assert np.abs(pos[0][0] - 7.22262850488348e-05 - 0.1) < 1e-10
assert np.abs(pos[0][1] - 3.4291613955705856e-05 - 0.2) < 1e-10
assert np.abs(pos[1][0] + 1.1696152238807462e-04 - 0.3) < 1e-10
assert np.abs(pos[1][1] - 7.4265634524358045e-06 - 0.4) < 1e-10
- sr.design.bpm.get("BPM_C04-01").offset.set([0.0, 0.0])
- sr.design.bpm.get("BPM_C04-02").offset.set([0.0, 0.0])
+ sr.design.diagnostic.bpm.get("BPM_C04-01").offset.set([0.0, 0.0])
+ sr.design.diagnostic.bpm.get("BPM_C04-02").offset.set([0.0, 0.0])
# No aggregator
bpms = []
- for b in sr.design.bpms.get("BPMS"):
+ for b in sr.design.diagnostic.bpms.get("BPMS"):
bpms.append(b)
bpms = BPMArray("BPM_noagg", bpms, use_aggregator=False)
@@ -164,10 +164,10 @@ def test_arrays(install_test_package):
assert np.abs(pos[1][1] - 7.4265634524358045e-06) < 1e-10
# Radom array
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
# Create an array that contains all elements
- allElts = ElementArray("AllElements", sr.design.get_all_elements())
+ allElts = ElementArray("AllElements", sr.design.get())
assert len(allElts) == 11
# Create an array that contains all elements
@@ -175,7 +175,7 @@ def test_arrays(install_test_package):
assert len(allMags) == 7
# Create an array that contains all BPM
- allBpms = BPMArray("AllBPMs", sr.design.bpm.all())
+ allBpms = BPMArray("AllBPMs", sr.design.diagnostic.bpm.all())
assert len(allBpms) == 2
cfm = sr.design.combined_function_magnets.get("CFM")
@@ -204,13 +204,13 @@ def test_arrays(install_test_package):
assert np.abs(strHVSQ[4] + 0.000017) < 1e-10 # V
assert np.abs(strHVSQ[5] - 1e-6) < 1e-10 # SQ
- bpmsLive = BPMArray("", sr.live.bpm.all())
+ bpmsLive = BPMArray("", sr.live.diagnostic.bpm.all())
bpmsLive.positions.get()
# Test dynamic arrays
sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False)
- ae = ElementArray("All", sr.design.get_all_elements())
+ ae = ElementArray("All", sr.design.get())
acfm = ElementArray("AllCFM", sr.design.combined_function_magnet.all(), use_aggregator=False)
bpmC5 = ae["BPM*"][10:20] # All BPM C5
@@ -232,7 +232,7 @@ def test_arrays(install_test_package):
emptyBPM = BPM(name="emptyBPM", elements=[])
emptyBPM.fill_array(sr.design) # Attach the array
- v = sr.design.bpms.get("emptyBPM").positions.get() # Ensure good attach
+ v = sr.design.diagnostic.bpms.get("emptyBPM").positions.get() # Ensure good attach
assert np.shape(v) == (0,)
emptyCFM = CombinedFunctionMagnet(name="emptyCFM", elements=[])
diff --git a/tests/arrays/test_arrays_ops.py b/tests/arrays/test_arrays_ops.py
index 5fd706e2c..fd8c961fc 100644
--- a/tests/arrays/test_arrays_ops.py
+++ b/tests/arrays/test_arrays_ops.py
@@ -43,7 +43,7 @@ def test_element_array_and_mask_filters_and_is_autotyped_list_mask(
sr.design.get_lattice().disable_6d()
# "ElArray" is a mixed ElementArray in the dummy config (see existing tests)
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
assert isinstance(elts, ElementArray)
assert len(elts) > 0
@@ -71,7 +71,7 @@ def test_element_array_and_mask_filters_and_is_autotyped_numpy_mask(
sr = accelerator_from_fragments(*sr_configuration_fragments)
sr.design.get_lattice().disable_6d()
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
assert len(elts) > 0
mask_list = [isinstance(e, Magnet) for e in elts]
@@ -97,7 +97,7 @@ def test_element_array_sub_mask_removes_true_inverse_of_and(
sr = accelerator_from_fragments(*sr_configuration_fragments)
sr.design.get_lattice().disable_6d()
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
assert len(elts) > 0
# Keep only magnets with '& mask'
@@ -134,7 +134,7 @@ def test_element_array_mask_length_mismatch_raises_for_and_and_sub(
sr = accelerator_from_fragments(*sr_configuration_fragments)
sr.design.get_lattice().disable_6d()
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
assert len(elts) > 0
bad_mask = [True] * (len(elts) - 1)
@@ -159,7 +159,7 @@ def test_mask_by_type_returns_correct_boolean_mask(
sr = accelerator_from_fragments(*sr_configuration_fragments)
sr.design.get_lattice().disable_6d()
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
mask = elts.mask_by_type(Magnet)
assert isinstance(mask, list)
@@ -182,7 +182,7 @@ def test_filter_by_type_returns_autotyped_array(install_test_package, accelerato
sr = accelerator_from_fragments(*sr_configuration_fragments)
sr.design.get_lattice().disable_6d()
- elts = sr.design.get_elements("ElArray")
+ elts = sr.design.get("ElArray")
filtered = elts.of_type(Magnet)
if len(filtered) == 0:
diff --git a/tests/bpm/test_bpm_controlsystem.py b/tests/bpm/test_bpm_controlsystem.py
deleted file mode 100644
index 13321ca12..000000000
--- a/tests/bpm/test_bpm_controlsystem.py
+++ /dev/null
@@ -1,96 +0,0 @@
-import numpy as np
-import pytest
-
-from pyaml.accelerator import Accelerator
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_bpm_tilt(install_test_package):
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
- bpm = sr.live.bpm.get("BPM_C01-01")
- print(bpm.tilt.get())
-
- assert bpm.tilt.get() == 0
- bpm.tilt.set(0.01)
- assert bpm.tilt.get() == 0.01
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_bpm_offset(install_test_package):
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
- bpm = sr.live.bpm.get("BPM_C01-01")
-
- assert bpm.offset.get()[0] == 0
- assert bpm.offset.get()[1] == 0
- bpm.offset.set(np.array([0.1, 0.2]))
- assert bpm.offset.get()[0] == 0.1
- assert bpm.offset.get()[1] == 0.2
- assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_bpm_position(install_test_package):
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
- bpm = sr.live.bpm.get("BPM_C01-01")
- bpm_simple = sr.live.bpm.get("BPM_C01-02")
-
- assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
- assert np.allclose(bpm_simple.positions.get(), np.array([0.0, 0.0]))
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_get_devices_returns_attached_devices(install_test_package):
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
-
- devs = sr.live.get_devices_access(["srdiag/bpm/c01-01/SA_HPosition", "srdiag/bpm/c01-01/SA_VPosition"])
-
- assert devs[0].name() == "//ebs-simu-3:10000/srdiag/bpm/c01-01/SA_HPosition"
- assert devs[1].name() == "//ebs-simu-3:10000/srdiag/bpm/c01-01/SA_VPosition"
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_get_device_accepts_backend_config_model(install_test_package):
- from tango.pyaml.attribute import ConfigModel as AttributeConfigModel
-
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
-
- dev = sr.live.get_device_access(AttributeConfigModel(attribute="srdiag/bpm/c01-05/SA_HPosition", unit="mm"))
-
- assert dev.name() == "//ebs-simu-3:10000/srdiag/bpm/c01-05/SA_HPosition"
- assert dev.unit() == "mm"
-
-
-@pytest.mark.parametrize(
- "install_test_package",
- [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
- indirect=True,
-)
-def test_controlsystem_bpm_position_indexed(install_test_package):
- from tango.pyaml.attribute_store import set_attribute
-
- set_attribute("srdiag/bpm/c01-04/Position", [0.0, 1.0], unit="mm")
-
- sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
- bpm = sr.live.bpm.get("BPM_C01-04")
-
- assert np.allclose(bpm.positions.get(), np.array([0.0, 1.0]))
diff --git a/tests/common/test_array_holder_navigation.py b/tests/common/test_array_holder_navigation.py
new file mode 100644
index 000000000..8bd0d2a9b
--- /dev/null
+++ b/tests/common/test_array_holder_navigation.py
@@ -0,0 +1,315 @@
+import pytest
+
+from pyaml.accelerator import Accelerator
+from pyaml.arrays.cfm_magnet_array import CombinedFunctionMagnetArray
+from pyaml.arrays.magnet_array import MagnetArray
+from pyaml.common.exception import PyAMLException
+from pyaml.configuration.manager import ConfigurationManager
+
+
+@pytest.fixture
+def holder(accelerator_from_fragments, sr_configuration_fragments):
+ sr = accelerator_from_fragments(*sr_configuration_fragments)
+ sr.design.get_lattice().disable_6d()
+ return sr.design
+
+
+@pytest.fixture
+def serialized_holder():
+ sr = Accelerator.load("tests/config/sr_serialized_magnets.yaml", include_locations=False, ignore_external=True)
+ return sr.design
+
+
+def test_dynamic_attribute_returns_named_magnet_array(holder):
+ assert holder.magnets.HCORR is holder.magnets.get("HCORR")
+ assert holder.magnets.VCORR is holder.magnets.get("VCORR")
+ assert holder.magnets.HVCORR is holder.magnets.get("HVCORR")
+
+
+def test_dynamic_attribute_returns_named_combined_function_magnet_array(holder):
+ assert holder.combined_function_magnets.CFM is holder.combined_function_magnets.get("CFM")
+
+
+def test_dynamic_attribute_returns_named_bpm_array(holder):
+ assert holder.diagnostic.bpms.BPMS is holder.diagnostic.bpms.get("BPMS")
+
+
+def test_dynamic_attribute_returns_named_serialized_magnet_array(serialized_holder):
+ assert serialized_holder.serialized_magnets.QForTune is serialized_holder.serialized_magnets.get("QForTune")
+ assert serialized_holder.serialized_magnets.series is serialized_holder.serialized_magnets.get("series")
+
+
+def test_dynamic_attribute_unknown_name_raises_attribute_error(holder):
+ with pytest.raises(AttributeError):
+ _ = holder.magnets.UNKNOWN
+
+
+def test_dynamic_attribute_does_not_shadow_existing_methods(holder):
+ holder.magnets._array_store["get"] = holder.magnets.get("HCORR")
+ holder.magnets._array_store["add"] = holder.magnets.get("HCORR")
+
+ assert callable(holder.magnets.get)
+ assert callable(holder.magnets.add)
+ assert holder.magnets.get("HCORR").names() == ["SH1A-C01-H", "SH1A-C02-H"]
+
+
+def test_dynamic_attribute_rejects_non_identifier_names(holder):
+ holder.magnets._array_store["not-an-id"] = holder.magnets.get("HCORR")
+
+ with pytest.raises(AttributeError):
+ getattr(holder.magnets, "not-an-id")
+
+
+def test_dir_includes_configured_array_names(holder):
+ assert {"HCORR", "VCORR", "HVCORR"} <= set(dir(holder.magnets))
+ assert "CFM" in dir(holder.combined_function_magnets)
+ assert "BPMS" in dir(holder.diagnostic.bpms)
+
+
+def test_dir_excludes_non_identifier_array_names(holder):
+ holder.magnets._array_store["not-an-id"] = holder.magnets.get("HCORR")
+
+ assert "not-an-id" not in dir(holder.magnets)
+
+
+def test_get_cfm_returns_all_combined_function_magnets(holder):
+ combined_function_magnets = holder.magnets.get_cfm()
+
+ assert type(combined_function_magnets) is CombinedFunctionMagnetArray
+ assert combined_function_magnets.names() == holder.combined_function_magnets.get().names()
+
+
+def test_issue_373_example():
+ """Reproduce the #373 example verbatim, against real test lattice data."""
+ sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True)
+ sr.design.get_lattice().disable_6d()
+
+ all_magnets = sr.design.magnets[:]
+ quad_family = sr.design.magnets.get("QForTune")
+ same_quad_family = sr.design.magnets.QForTune
+ assert same_quad_family.names() == quad_family.names()
+ assert len(quad_family) == 124
+ assert len(all_magnets) >= len(quad_family)
+
+ combined_function_magnets = sr.design.magnets.get_cfm()
+ assert len(combined_function_magnets) == 0
+
+ matching_quadrupoles = sr.design.magnets["QF1*"]
+ assert matching_quadrupoles.names() == sr.design.magnets["QF1*"].names()
+
+ one_magnet = sr.design.magnet.get("QF1E-C04")
+ one_magnet.strength.set(0.8)
+ assert one_magnet.strength.get() == pytest.approx(0.8)
+
+
+def test_configured_exclusion_family_reproduced_with_selection_and_difference():
+ """QForTest is QForTune minus a `~name`/`~pattern` YAML exclusion; `[]` and `-` reproduce it."""
+ sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True)
+ sr.design.get_lattice().disable_6d()
+
+ q_for_tune = sr.design.magnets.get("QForTune")
+ q_for_test = sr.design.magnets.get("QForTest") # QForTune, minus ~QF1E-C05 and ~Q???-C06
+
+ reproduced = q_for_tune - sr.design.magnets["QF1E-C05"] - sr.design.magnets["Q???-C06"]
+
+ assert reproduced == q_for_test
+
+
+def test_configured_exclusion_family_reproduced_in_a_single_getitem_call():
+ """The YAML `elements:` selector list (`[QD2*, QF1*, ~QF1E-C05, ~Q???-C06]`) selects the
+ same *family* of elements through `[]` as declared for `QForTest`.
+
+ Selection goes through the top-level holder, not `.magnets`, so it resolves patterns
+ against the same global element pool `find_elements()`/`_fill_array` use to build
+ `QForTest` in the YAML. The two therefore agree on *which* elements are selected, but not
+ necessarily on their order: `_fill_array` concatenates matches pattern by pattern (all
+ `QD2*` matches, then all `QF1*` matches) to build the named array, while `[]` (like every
+ other list-selection accessor, see `test_every_accessor_returns_a_list_selection_in_configuration_order`)
+ normalizes its result to configuration order regardless of how many patterns were
+ involved or in what order they matched.
+ """
+ sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True)
+ sr.design.get_lattice().disable_6d()
+
+ q_for_test = sr.design.magnets.get("QForTest")
+ reproduced = sr.design[["QD2*", "QF1*", "~QF1E-C05", "~Q???-C06"]]
+
+ assert type(reproduced) is type(q_for_test)
+ assert set(reproduced.names()) == set(q_for_test.names())
+ assert reproduced.names() == [n for n in sr.design.get().names() if n in set(q_for_test.names())]
+
+
+def test_array_getitem_supports_a_negated_regex_pattern():
+ """`~re:...` on an ElementArray excludes regex matches, same as `~wildcard`."""
+ sr = Accelerator.load("tests/config/EBSTune-patterns.yaml", ignore_external=True)
+ sr.design.get_lattice().disable_6d()
+
+ magnets = sr.design.magnets[:]
+ wildcard_exclusion = magnets["~QF1*"]
+ regex_exclusion = magnets["~re:^QF1.*$"]
+
+ assert len(regex_exclusion) > 0
+ assert len(regex_exclusion) < len(magnets)
+ assert regex_exclusion == wildcard_exclusion
+
+
+def test_fill_array_supports_an_exclusion_outside_a_single_getitem_call_shape():
+ """A YAML `elements:` list combining an inclusion and an exclusion builds an array, not a ValueError.
+
+ `_fill_array` previously did its own include/exclude bookkeeping with `list.remove`,
+ which raised whenever the excluded name wasn't already gathered by an inclusion
+ pattern processed earlier in the same call. Delegating to `find_elements` (used here
+ with the same list, for comparison) avoids that ordering trap.
+ """
+ manager = ConfigurationManager()
+ manager.add("tests/config/EBSTune-patterns.yaml")
+ manager.add({"arrays": [{"type": "pyaml.arrays.magnet", "name": "QD2Family", "elements": ["QD2*", "~QF1E-C05"]}]})
+ sr = manager.build(ignore_external=True)
+ sr.design.get_lattice().disable_6d()
+
+ qd2_family = sr.design.magnets.get("QD2Family")
+
+ assert qd2_family.names() == sr.design.find_elements(["QD2*", "~QF1E-C05"])
+
+
+def test_magnet_holder_getitem_exact_name_matches_get(holder):
+ assert holder.magnet["SH1A-C01-H"] is holder.magnet.get("SH1A-C01-H")
+
+
+def test_magnet_holder_getitem_exact_name_miss_raises(holder):
+ with pytest.raises(PyAMLException):
+ holder.magnet["UNKNOWN"]
+
+
+def test_magnet_holder_getitem_wildcard_and_list_return_an_array(holder):
+ wildcard = holder.magnet["SH1A-C01-[HV]"]
+ assert sorted(wildcard.names()) == ["SH1A-C01-H", "SH1A-C01-V"]
+ assert holder.magnet["MISSING*"].names() == []
+
+ listed = holder.magnet[["SH1A-C01-H", "SH1A-C01-V"]]
+ assert listed.names() == ["SH1A-C01-H", "SH1A-C01-V"]
+
+
+def test_magnet_holder_getitem_wildcard_returns_a_magnet_array(holder):
+ """A wildcard restricted to the .magnet store is auto-typed as MagnetArray, like the
+ top-level and .magnets holders, instead of falling back to a generic ElementArray."""
+ wildcard = holder.magnet["SH1A-C0[12]-[HVQ]*"]
+ assert type(wildcard) is MagnetArray
+
+
+def test_magnet_and_magnets_holder_getitem_agree_on_order(holder):
+ """.magnet (singular) and .magnets (plural) must return the same elements in the same
+ order for the same name list, regardless of the order the names were requested in. The
+ reference order is the configuration order, not the order of the requested names. This
+ must also hold for the top-level holder itself (`[]` and `find_elements`), not just its
+ typed sub-holders."""
+ forward = holder.magnet[["SH1A-C01-H", "SH1A-C01-V"]]
+ backward = holder.magnet[["SH1A-C01-V", "SH1A-C01-H"]]
+ assert forward.names() == backward.names() == ["SH1A-C01-H", "SH1A-C01-V"]
+
+ forward_plural = holder.magnets[["SH1A-C01-H", "SH1A-C01-V"]]
+ backward_plural = holder.magnets[["SH1A-C01-V", "SH1A-C01-H"]]
+ assert forward_plural.names() == backward_plural.names() == forward.names()
+
+ forward_top_level = holder[["SH1A-C01-H", "SH1A-C01-V"]]
+ backward_top_level = holder[["SH1A-C01-V", "SH1A-C01-H"]]
+ assert forward_top_level.names() == backward_top_level.names() == forward.names()
+
+ assert holder.find_elements(["SH1A-C01-H", "SH1A-C01-V"]) == forward.names()
+ assert holder.find_elements(["SH1A-C01-V", "SH1A-C01-H"]) == forward.names()
+
+
+def test_combined_function_magnet_and_bpm_holders_return_list_selections_in_configuration_order(holder):
+ """Every typed sub-holder must normalize list selections to configuration order, not just
+ .magnet/.magnets: this must also hold for .combined_function_magnet(s) and .bpm(s)."""
+ cfm_forward = holder.combined_function_magnet[["SH1A-C01", "SH1A-C02"]]
+ cfm_backward = holder.combined_function_magnet[["SH1A-C02", "SH1A-C01"]]
+ assert cfm_forward.names() == cfm_backward.names() == ["SH1A-C01", "SH1A-C02"]
+
+ cfm_forward_plural = holder.combined_function_magnets[["SH1A-C01", "SH1A-C02"]]
+ cfm_backward_plural = holder.combined_function_magnets[["SH1A-C02", "SH1A-C01"]]
+ assert cfm_forward_plural.names() == cfm_backward_plural.names() == cfm_forward.names()
+
+ bpm_forward = holder.diagnostic.bpm[["BPM_C04-01", "BPM_C04-02"]]
+ bpm_backward = holder.diagnostic.bpm[["BPM_C04-02", "BPM_C04-01"]]
+ assert bpm_forward.names() == bpm_backward.names() == ["BPM_C04-01", "BPM_C04-02"]
+
+ bpm_forward_plural = holder.diagnostic.bpms[["BPM_C04-01", "BPM_C04-02"]]
+ bpm_backward_plural = holder.diagnostic.bpms[["BPM_C04-02", "BPM_C04-01"]]
+ assert bpm_forward_plural.names() == bpm_backward_plural.names() == bpm_forward.names()
+
+
+@pytest.mark.parametrize(
+ "select",
+ [
+ pytest.param(lambda h, k: h[k].names(), id="holder[]"),
+ pytest.param(lambda h, k: h.find_elements(k), id="holder.find_elements"),
+ pytest.param(lambda h, k: h.get()[k].names(), id="holder.get()[]"),
+ pytest.param(lambda h, k: h.magnet[k].names(), id="holder.magnet[]"),
+ pytest.param(lambda h, k: h.magnets[k].names(), id="holder.magnets[]"),
+ ],
+)
+@pytest.mark.parametrize("reverse", [False, True], ids=["forward", "reversed"])
+@pytest.mark.parametrize(
+ "key, expected_members",
+ [
+ pytest.param(
+ ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"],
+ {"SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"},
+ id="literal-names",
+ ),
+ pytest.param(
+ ["SH1A-C0?-H", "SH1A-C01-V"],
+ {"SH1A-C01-H", "SH1A-C02-H", "SH1A-C01-V"},
+ id="wildcard-and-literal",
+ ),
+ ],
+)
+def test_every_accessor_returns_a_list_selection_in_configuration_order(holder, select, reverse, key, expected_members):
+ """Every name-based accessor must return a list-of-patterns selection in configuration
+ order, whatever the order of the requested names/patterns, so that positional values line
+ up the same way whichever accessor built the array. This must hold both for a list of
+ literal names and for a list mixing a wildcard (matching several names) with a literal
+ name, since a wildcard entry is where a naive pattern-order passthrough diverges from
+ configuration order the most visibly."""
+ expected = [n for n in holder.get().names() if n in expected_members]
+ assert select(holder, key[::-1] if reverse else key) == expected
+
+
+def test_subtracting_a_magnet_selection_from_a_mixed_selection_yields_a_cfm_array(holder):
+ """A top-level selection mixing CombinedFunctionMagnet and their virtual correctors, minus
+ the corrector-only .magnets selection, must yield the CFMs alone as a
+ CombinedFunctionMagnetArray. Regression test: this used to raise 'Aggregator not
+ implemented for CombinedFunctionMagnetArray' because the derived array blindly inherited
+ the use_aggregator flag of the ElementArray it was built from."""
+ mixed = holder["SH*"]
+ only_magnets = holder.magnets["SH*"]
+ only_cfm = mixed - only_magnets
+
+ assert type(only_cfm) is CombinedFunctionMagnetArray
+ assert only_cfm.names() == ["SH1A-C01", "SH1A-C02"]
+
+
+def test_magnet_holder_getitem_regex(holder):
+ matching = holder.magnet["re:^SH1A-C0[12]-H$"]
+ assert sorted(matching.names()) == ["SH1A-C01-H", "SH1A-C02-H"]
+
+
+def test_combined_function_magnet_holder_getitem_exact_name_matches_get(holder):
+ assert holder.combined_function_magnet["SH1A-C01"] is holder.combined_function_magnet.get("SH1A-C01")
+
+
+def test_combined_function_magnet_holder_getitem_exact_name_miss_raises(holder):
+ with pytest.raises(PyAMLException):
+ holder.combined_function_magnet["UNKNOWN"]
+
+
+def test_serialized_magnet_holder_getitem_exact_name_matches_get(serialized_holder):
+ assert serialized_holder.serialized_magnet["mySeriesOfMagnets"] is serialized_holder.serialized_magnet.get(
+ "mySeriesOfMagnets"
+ )
+
+
+def test_serialized_magnet_holder_getitem_exact_name_miss_raises(serialized_holder):
+ with pytest.raises(PyAMLException):
+ serialized_holder.serialized_magnet["UNKNOWN"]
diff --git a/tests/common/test_element_holder_collection.py b/tests/common/test_element_holder_collection.py
index 937d2da79..01585cf9f 100644
--- a/tests/common/test_element_holder_collection.py
+++ b/tests/common/test_element_holder_collection.py
@@ -3,8 +3,8 @@
from pyaml.arrays.bpm_array import BPMArray
from pyaml.arrays.element_array import ElementArray
from pyaml.arrays.magnet_array import MagnetArray
-from pyaml.bpm.bpm import BPM
from pyaml.common.exception import PyAMLException
+from pyaml.diagnostics.bpm.bpm import BPM
from pyaml.lattice.simulator import Simulator
@@ -15,13 +15,14 @@ def holder(accelerator_from_fragments, sr_configuration_fragments):
return sr.design
-def test_exact_name_returns_the_element_or_none(holder):
- assert holder["BPM_C04-01"] is holder.bpm.get("BPM_C04-01")
- assert holder["UNKNOWN"] is None
+def test_exact_name_returns_the_element_or_raises(holder):
+ assert holder["BPM_C04-01"] is holder.diagnostic.bpm.get("BPM_C04-01")
+ with pytest.raises(PyAMLException):
+ holder["UNKNOWN"]
def test_get_and_full_slice_keep_registration_order(holder):
- names = [element.get_name() for element in holder.get_all_elements()]
+ names = [element.get_name() for element in holder.get()]
assert type(holder.get()) is ElementArray
assert type(holder[:]) is ElementArray
@@ -47,7 +48,7 @@ def test_new_calls_reflect_registry_additions(holder):
assert "EXTRA_BPM" not in previous.names()
assert holder.get().names() == previous.names() + ["EXTRA_BPM"]
- assert holder["EXTRA_BPM"] is holder.bpm.get("EXTRA_BPM")
+ assert holder["EXTRA_BPM"] is holder.diagnostic.bpm.get("EXTRA_BPM")
def test_patterns_always_return_arrays(holder):
@@ -70,7 +71,7 @@ def test_character_classes_in_name_patterns(holder):
def test_colons_are_part_of_names(holder):
holder.fill_device([BPM("CELL04:BPM01", lattice_names="list(BPM_C04-01)")])
- assert holder["CELL04:BPM01"] is holder.bpm.get("CELL04:BPM01")
+ assert holder["CELL04:BPM01"] is holder.diagnostic.bpm.get("CELL04:BPM01")
assert holder["CELL04:BPM*"].names() == ["CELL04:BPM01"]
assert holder["model_name:*"].names() == []
@@ -78,7 +79,7 @@ def test_colons_are_part_of_names(holder):
def test_magnet_subclasses_share_a_typed_array_in_either_order(holder):
horizontal = holder.magnet.get("SH1A-C01-H")
vertical = holder.magnet.get("SH1A-C01-V")
- start = holder.get_all_elements().index(horizontal)
+ start = holder.get().index(horizontal)
assert type(horizontal) is not type(vertical)
assert isinstance(holder["SH1A-C01-[HV]"], MagnetArray)
@@ -96,7 +97,7 @@ def test_mixed_selection_returns_a_generic_array(holder):
def test_indices_and_slices_follow_insertion_order(holder):
- registered = holder.get_all_elements()
+ registered = holder.get()
assert holder[0] is registered[0]
assert holder[-1] is registered[-1]
@@ -113,11 +114,12 @@ def test_empty_holder_returns_empty_collections(ebs_lattice_file):
assert type(holder.get()) is ElementArray
assert holder[:].names() == []
assert holder["BPM*"].names() == []
- assert holder["BPM_C04-01"] is None
+ with pytest.raises(PyAMLException):
+ holder["BPM_C04-01"]
def test_invalid_indices_and_keys_raise_clear_errors(holder):
- size = len(holder.get_all_elements())
+ size = len(holder.get())
with pytest.raises(IndexError):
holder[size]
@@ -130,14 +132,21 @@ def test_invalid_indices_and_keys_raise_clear_errors(holder):
def test_selection_intersects_with_a_configured_family(holder):
- selected = holder["SH1A-C0?-H"] & holder.get_elements("ElArray")
+ selected = holder["SH1A-C0?-H"] & holder.get("ElArray")
assert isinstance(selected, MagnetArray)
assert selected.names() == ["SH1A-C02-H"]
- assert holder.get_element("SH1A-C02-H") is holder["SH1A-C02-H"]
- assert holder.get_all_elements() == list(holder.get())
+
+
+def test_get_resolves_a_named_array_regardless_of_its_concrete_family(holder):
+ """`get(name)` must not be limited to generic element arrays, unlike the old `get_elements`."""
+ assert isinstance(holder.get("HCORR"), MagnetArray)
+ assert holder.get("HCORR").names() == ["SH1A-C01-H", "SH1A-C02-H"]
+ assert isinstance(holder.get("BPMS"), BPMArray)
+ assert holder.get("BPMS").names() == ["BPM_C04-01", "BPM_C04-02"]
+ assert holder.get("ElArray").names() == ["BPM_C04-01", "BPM_C04-02", "SH1A-C01-V", "SH1A-C02-H"]
with pytest.raises(PyAMLException):
- holder.get_element("UNKNOWN")
+ holder.get("UNKNOWN")
def test_existing_array_field_filters_still_work(holder):
@@ -148,3 +157,130 @@ def test_existing_array_field_filters_still_work(holder):
def test_existing_empty_intersection_stays_a_list(holder):
assert type(holder["SH1A-C0?-H"] & holder["SH1A-C0?-V"]) is list
+
+
+def test_intersecting_two_wildcard_selections(holder):
+ """Two overlapping wildcard selections combined with `&` narrow down to their overlap."""
+ by_cell = holder["SH1A-C01*"] # SH1A-C01-H, SH1A-C01-V, SH1A-C01-SQ
+ by_plane = holder["SH1A-C0?-H"] # SH1A-C01-H, SH1A-C02-H
+
+ selected = by_cell & by_plane
+
+ assert isinstance(selected, MagnetArray)
+ assert selected.names() == ["SH1A-C01-H"]
+
+
+def test_union_of_a_list_selection_and_a_wildcard_selection(holder):
+ """A list-of-patterns selection and a wildcard selection combine with `|` like any array."""
+ cell_01 = holder[["SH1A-C01-H", "SH1A-C01-V"]]
+ cell_02 = holder["SH1A-C02*"] # the CFM magnet SH1A-C02, plus its -H, -V, -SQ sub-magnets
+
+ combined = cell_01 | cell_02
+
+ # Mixes a CombinedFunctionMagnet (SH1A-C02) with plain Magnets, so the union
+ # stays a generic ElementArray rather than a MagnetArray.
+ assert type(combined) is ElementArray
+ assert sorted(combined.names()) == [
+ "SH1A-C01-H",
+ "SH1A-C01-V",
+ "SH1A-C02",
+ "SH1A-C02-H",
+ "SH1A-C02-SQ",
+ "SH1A-C02-V",
+ ]
+
+
+def test_difference_with_a_regex_selection(holder):
+ """`-` removes a `re:` selection's matches from a wildcard selection, like any array."""
+ both_planes_h = holder["SH1A-C0?-H"] # SH1A-C01-H, SH1A-C02-H
+ cell_01_h = holder["re:^SH1A-C01-H$"]
+
+ selected = both_planes_h - cell_01_h
+
+ assert isinstance(selected, MagnetArray)
+ assert selected.names() == ["SH1A-C02-H"]
+
+
+def test_disjoint_regex_and_list_selections_produce_a_plain_list(holder):
+ """The same empty-result-is-a-plain-list quirk applies to the new selection styles too."""
+ cell_01_h = holder["re:^SH1A-C01-H$"]
+ cell_02_h_v = holder[["SH1A-C02-H", "SH1A-C02-V"]]
+
+ assert type(cell_01_h & cell_02_h_v) is list
+
+
+def test_selection_combined_with_a_configured_family_via_regex_and_list(holder):
+ """`re:` and list-of-patterns selections intersect with a configured family, same as wildcards."""
+ el_array = holder.get("ElArray") # BPM_C04-01, BPM_C04-02, SH1A-C01-V, SH1A-C02-H
+
+ by_regex = holder["re:^SH1A-C0[12]-H$"] & el_array
+ assert isinstance(by_regex, MagnetArray)
+ assert by_regex.names() == ["SH1A-C02-H"]
+
+ by_list = holder[["BPM_C04-01", "BPM_C04-02"]] & el_array
+ assert isinstance(by_list, BPMArray)
+ assert by_list.names() == ["BPM_C04-01", "BPM_C04-02"]
+
+
+def test_regex_pattern_is_supported(holder):
+ assert holder["re:^BPM_C04-0[12]$"].names() == ["BPM_C04-01", "BPM_C04-02"]
+ assert holder["re:^NOTHING$"].names() == []
+
+
+def test_invalid_regex_raises_pyaml_exception(holder):
+ with pytest.raises(PyAMLException, match="Invalid regex"):
+ holder["re:("]
+
+
+def test_list_of_patterns_unions_results(holder):
+ """Order follows configuration (registration) order, not the order patterns were requested in."""
+ selected = holder[["BPM_C04-01", "SH1A-C0?-H"]]
+ assert selected.names() == ["SH1A-C01-H", "SH1A-C02-H", "BPM_C04-01"]
+
+
+def test_list_of_patterns_with_missing_literal_raises(holder):
+ with pytest.raises(PyAMLException):
+ holder[["BPM_C04-01", "UNKNOWN"]]
+
+
+def test_wildcard_matching_is_case_sensitive(holder):
+ assert holder["bpm_c04*"].names() == []
+
+
+def test_find_elements_literal_miss_raises(holder):
+ with pytest.raises(PyAMLException):
+ holder.find_elements("UNKNOWN")
+
+
+def test_find_elements_bracket_only_pattern_is_a_wildcard(holder):
+ assert holder.find_elements("BPM_C04-0[12]") == ["BPM_C04-01", "BPM_C04-02"]
+
+
+def test_find_elements_supports_regex(holder):
+ assert holder.find_elements("re:^BPM_C04-0[12]$") == ["BPM_C04-01", "BPM_C04-02"]
+
+
+def test_find_elements_supports_a_list_of_patterns(holder):
+ """Order follows configuration (registration) order, not the order patterns were requested in."""
+ assert holder.find_elements(["BPM_C04-01", "SH1A-C0?-H"]) == ["SH1A-C01-H", "SH1A-C02-H", "BPM_C04-01"]
+
+
+def test_find_elements_supports_an_exclusion_in_a_list(holder):
+ both_planes = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V"])
+ assert both_planes == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H", "SH1A-C02-V"]
+
+ minus_one = holder.find_elements(["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"])
+ assert minus_one == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"]
+
+
+def test_getitem_supports_an_exclusion_in_a_list(holder):
+ selected = holder[["SH1A-C0?-H", "SH1A-C0?-V", "~SH1A-C02-V"]]
+ assert selected.names() == ["SH1A-C01-H", "SH1A-C01-V", "SH1A-C02-H"]
+
+
+def test_getitem_lone_exclusion_pattern_means_everything_except(holder):
+ all_names = holder.get()
+ selected = holder["~QF1A-C01"]
+
+ assert "QF1A-C01" not in selected.names()
+ assert len(selected) == len(all_names) - 1
diff --git a/tests/common/test_errors.py b/tests/common/test_errors.py
index 38ce79f56..ec7496df8 100644
--- a/tests/common/test_errors.py
+++ b/tests/common/test_errors.py
@@ -43,24 +43,24 @@ def test_tune(install_test_package):
assert "Magnet QF1A-C05XX not defined" in str(exc.value)
with pytest.raises(PyAMLException) as exc:
- m2 = sr.design.bpm.get("QF1A-C05XX")
+ m2 = sr.design.diagnostic.bpm.get("QF1A-C05XX")
assert "BPM QF1A-C05XX not defined" in str(exc.value)
def test_duplicate_error_reports_source_line_and_column_across_files(tmp_path):
devices_a = tmp_path / "devices_a.yaml"
devices_a.write_text(
- "- type: pyaml.bpm.bpm\n name: BPM_DUPLICATE\n",
+ "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_DUPLICATE\n",
encoding="utf-8",
)
devices_b = tmp_path / "devices_b.yaml"
devices_b.write_text(
- "- type: pyaml.bpm.bpm\n name: BPM_UNIQUE\n- type: pyaml.bpm.bpm\n name: BPM_DUPLICATE\n",
+ "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_UNIQUE\n- type: pyaml.diagnostics.bpm.bpm\n name: BPM_DUPLICATE\n",
encoding="utf-8",
)
root = tmp_path / "root.yaml"
root.write_text(
- "type: pyaml.accelerator\ndevices:\n - devices_a.yaml\n - devices_b.yaml\n",
+ "type: pyaml.accelerator\ndevices:\n - ${include:devices_a.yaml}\n - ${include:devices_b.yaml}\n",
encoding="utf-8",
)
@@ -76,7 +76,7 @@ def test_duplicate_error_reports_source_line_and_column_across_files(tmp_path):
def test_malformed_local_included_yaml_reports_source_line_and_column(tmp_path):
broken_devices = tmp_path / "broken_devices.yaml"
broken_devices.write_text(
- "- type: pyaml.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n",
+ "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n",
encoding="utf-8",
)
root = tmp_path / "root.yaml"
@@ -86,7 +86,7 @@ def test_malformed_local_included_yaml_reports_source_line_and_column(tmp_path):
"machine: sr\n"
"energy: 6e9\n"
"data_folder: /data/store\n"
- "devices: broken_devices.yaml\n",
+ "devices: ${include:broken_devices.yaml}\n",
encoding="utf-8",
)
@@ -101,7 +101,7 @@ def test_malformed_local_included_yaml_reports_source_line_and_column(tmp_path):
def test_truncated_local_included_json_reports_source_and_position(tmp_path):
broken_devices = tmp_path / "broken_devices.json"
broken_devices.write_text(
- '{"type": "pyaml.bpm.bpm", "name": "BPM_BROKEN", "model": ',
+ '{"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_BROKEN", "model": ',
encoding="utf-8",
)
root = tmp_path / "root.yaml"
@@ -111,7 +111,7 @@ def test_truncated_local_included_json_reports_source_and_position(tmp_path):
"machine: sr\n"
"energy: 6e9\n"
"data_folder: /data/store\n"
- "devices: broken_devices.json\n",
+ "devices: ${include:broken_devices.json}\n",
encoding="utf-8",
)
@@ -131,9 +131,11 @@ def test_malformed_remote_included_yaml_reports_source_line_and_column(http_conf
"machine: sr\n"
"energy: 6000000000.0\n"
"data_folder: /data/store\n"
- "devices: fragments/broken_devices.yaml\n"
+ "devices: ${include:fragments/broken_devices.yaml}\n"
+ ),
+ "/configs/fragments/broken_devices.yaml": (
+ "- type: pyaml.diagnostics.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n"
),
- "/configs/fragments/broken_devices.yaml": ("- type: pyaml.bpm.bpm\n name: BPM_BROKEN\n model:\n type: [oops\n"),
}
with http_config_server(routes) as base_url:
@@ -153,10 +155,10 @@ def test_truncated_remote_included_json_reports_source_and_position(http_config_
"machine: sr\n"
"energy: 6000000000.0\n"
"data_folder: /data/store\n"
- "devices: fragments/broken_devices.json\n"
+ "devices: ${include:fragments/broken_devices.json}\n"
),
"/configs/fragments/broken_devices.json": (
- '{"type": "pyaml.bpm.bpm", "name": "BPM_BROKEN", "model": ',
+ '{"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_BROKEN", "model": ',
"application/json",
200,
),
diff --git a/tests/common/test_name_matching.py b/tests/common/test_name_matching.py
new file mode 100644
index 000000000..c73658625
--- /dev/null
+++ b/tests/common/test_name_matching.py
@@ -0,0 +1,114 @@
+import pytest
+
+from pyaml.common.exception import PyAMLException
+from pyaml.common.name_matching import is_wildcard, resolve_names
+
+NAMES = ["BPM_C04-01", "BPM_C04-02", "QF1A-C01", "QF1A-C02"]
+
+
+def test_is_wildcard_triggers_on_star_question_and_bracket():
+ assert is_wildcard("BPM*")
+ assert is_wildcard("BPM?")
+ assert is_wildcard("BPM[01]")
+ assert not is_wildcard("BPM_C04-01")
+ assert not is_wildcard("re:^BPM")
+
+
+def test_literal_hit_returns_the_single_name():
+ assert resolve_names(NAMES, "QF1A-C01") == ["QF1A-C01"]
+
+
+def test_literal_miss_raises():
+ with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"):
+ resolve_names(NAMES, "UNKNOWN")
+
+
+def test_literal_miss_uses_the_provided_what_label():
+ with pytest.raises(PyAMLException, match="Magnet UNKNOWN not defined"):
+ resolve_names(NAMES, "UNKNOWN", what="Magnet")
+
+
+def test_wildcard_hit_and_empty_are_not_errors():
+ assert resolve_names(NAMES, "BPM*") == ["BPM_C04-01", "BPM_C04-02"]
+ assert resolve_names(NAMES, "MISSING*") == []
+
+
+def test_wildcard_is_case_sensitive():
+ assert resolve_names(NAMES, "bpm*") == []
+
+
+def test_bracket_only_pattern_is_a_wildcard_not_a_literal():
+ assert resolve_names(NAMES, "QF1A-C0[12]") == ["QF1A-C01", "QF1A-C02"]
+
+
+def test_regex_hit_and_empty_are_not_errors():
+ assert resolve_names(NAMES, "re:^BPM_C04-0[12]$") == ["BPM_C04-01", "BPM_C04-02"]
+ assert resolve_names(NAMES, "re:^NOTHING$") == []
+
+
+def test_regex_is_a_fullmatch():
+ assert resolve_names(NAMES, "re:BPM_C04") == []
+
+
+def test_invalid_regex_raises_pyaml_exception_not_re_error():
+ with pytest.raises(PyAMLException, match="Invalid regex"):
+ resolve_names(NAMES, "re:(")
+
+
+def test_list_of_patterns_unions_and_deduplicates_in_order():
+ result = resolve_names(NAMES, ["QF1A-C01", "BPM*", "QF1A-C01"])
+ assert result == ["QF1A-C01", "BPM_C04-01", "BPM_C04-02"]
+
+
+def test_tuple_of_patterns_is_also_accepted():
+ assert resolve_names(NAMES, ("QF1A-C01", "QF1A-C02")) == ["QF1A-C01", "QF1A-C02"]
+
+
+def test_list_with_one_missing_literal_raises():
+ with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"):
+ resolve_names(NAMES, ["QF1A-C01", "UNKNOWN"])
+
+
+def test_list_mixing_literal_wildcard_and_regex():
+ result = resolve_names(NAMES, ["QF1A-C01", "BPM*", "re:^QF1A-C02$"])
+ assert result == ["QF1A-C01", "BPM_C04-01", "BPM_C04-02", "QF1A-C02"]
+
+
+def test_overlapping_wildcard_patterns_in_a_list_do_not_duplicate_a_match():
+ names = ["BPM_01", "BPM_02", "BPM_03", "BPM_04", "BPM_05"]
+ result = resolve_names(names, ["BPM_0[1-3]", "BPM_0[3-5]"])
+ assert result == ["BPM_01", "BPM_02", "BPM_03", "BPM_04", "BPM_05"]
+
+
+def test_lone_exclusion_pattern_means_everything_except():
+ assert resolve_names(NAMES, "~QF1A-C01") == ["BPM_C04-01", "BPM_C04-02", "QF1A-C02"]
+
+
+def test_list_of_only_exclusion_patterns_means_everything_except():
+ result = resolve_names(NAMES, ["~QF1A-C01", "~QF1A-C02"])
+ assert result == ["BPM_C04-01", "BPM_C04-02"]
+
+
+def test_exclusion_removes_matches_from_an_inclusion_pattern():
+ assert resolve_names(NAMES, ["BPM*", "~BPM_C04-01"]) == ["BPM_C04-02"]
+
+
+def test_exclusion_order_does_not_matter():
+ forward = resolve_names(NAMES, ["BPM*", "~BPM_C04-01"])
+ backward = resolve_names(NAMES, ["~BPM_C04-01", "BPM*"])
+ assert forward == backward == ["BPM_C04-02"]
+
+
+def test_exclusion_of_a_wildcard_pattern_removes_all_its_matches():
+ result = resolve_names(NAMES, ["QF1A-C01", "QF1A-C02", "BPM_C04-01", "~QF1A-*"])
+ assert result == ["BPM_C04-01"]
+
+
+def test_exclusion_of_a_regex_pattern_removes_all_its_matches():
+ result = resolve_names(NAMES, ["BPM*", "~re:^BPM_C04-01$"])
+ assert result == ["BPM_C04-02"]
+
+
+def test_exclusion_of_a_missing_literal_raises():
+ with pytest.raises(PyAMLException, match="Element UNKNOWN not defined"):
+ resolve_names(NAMES, ["BPM*", "~UNKNOWN"])
diff --git a/tests/config/EBSNames-linker.yaml b/tests/config/EBSNames-linker.yaml
new file mode 100644
index 000000000..e322320e1
--- /dev/null
+++ b/tests/config/EBSNames-linker.yaml
@@ -0,0 +1,95 @@
+type: pyaml.accelerator
+facility: ESRF
+machine: sr
+energy: 6e9
+simulators:
+ - type: pyaml.lattice.simulator
+ lattice: sr/lattices/ebs-original-names.mat
+ name: design
+ linker:
+ type: pyaml.lattice.attribute_linker
+ attribute_name: FamName # equivalent to the default linker
+controls:
+ - type: tango.pyaml.controlsystem
+ tango_host: ebs-simu-3:10000
+ name: live
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
+data_folder: /data/store
+devices:
+- type: pyaml.magnet.quadrupole
+ name: QF1E
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 1.00054
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c04-e/current
+- type: pyaml.magnet.quadrupole
+ name: QF1E-ALL
+ lattice_names: list(QF1E,QF1I)
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 1.00054
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c04-e/current
+- type: pyaml.magnet.quadrupole
+ name: QF1E-C05
+ lattice_names: QF1E@1
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 0.996841
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c05-a/current
+- type: pyaml.magnet.quadrupole
+ name: QF1E-C04-C05-C06
+ lattice_names: QF1E@0,1,2
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 1.00191
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c05-e/current
+- type: pyaml.magnet.quadrupole
+ name: QF1E-C04-C05-C06-2
+ lattice_names: "@140,290,424"
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 1.00191
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c05-e/current
+- type: pyaml.magnet.quadrupole
+ name: QF1E-C04-C05-C06-3
+ lattice_names: QF1E#0..3
+ model:
+ type: pyaml.magnet.linear_model
+ calibration_factor: 1.00191
+ crosstalk: 1.0
+ curve:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: srmag/vps-qf1/c05-e/current
diff --git a/tests/config/EBSNames.yaml b/tests/config/EBSNames.yaml
index b0eee6afc..cde710651 100644
--- a/tests/config/EBSNames.yaml
+++ b/tests/config/EBSNames.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
devices:
- type: pyaml.magnet.quadrupole
diff --git a/tests/config/EBSOrbit.yaml b/tests/config/EBSOrbit.yaml
index 5d6ea2570..c77128006 100644
--- a/tests/config/EBSOrbit.yaml
+++ b/tests/config/EBSOrbit.yaml
@@ -11,7 +11,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
@@ -5713,1285 +5713,1285 @@ devices:
- srmag/ps-corr-sh3/c03-e-ch3/current
- srmag/ps-corr-sh3/c03-e-ch5/current
- srmag/ps-corr-sh3/c03-e-ch6/current
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-01
x_pos: srdiag/bpm/c04-01/SA_HPosition
y_pos: srdiag/bpm/c04-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-02
x_pos: srdiag/bpm/c04-02/SA_HPosition
y_pos: srdiag/bpm/c04-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-03
x_pos: srdiag/bpm/c04-03/SA_HPosition
y_pos: srdiag/bpm/c04-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-04
x_pos: srdiag/bpm/c04-04/SA_HPosition
y_pos: srdiag/bpm/c04-04/SA_VPosition
x_offset: srdiag/bpm/c04-04/HOffset
y_offset: srdiag/bpm/c04-04/VOffset
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-05
x_pos: srdiag/bpm/c04-05/SA_HPosition
y_pos: srdiag/bpm/c04-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-06
x_pos: srdiag/bpm/c04-06/SA_HPosition
y_pos: srdiag/bpm/c04-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-07
x_pos: srdiag/bpm/c04-07/SA_HPosition
y_pos: srdiag/bpm/c04-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-08
x_pos: srdiag/bpm/c04-08/SA_HPosition
y_pos: srdiag/bpm/c04-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-09
x_pos: srdiag/bpm/c04-09/SA_HPosition
y_pos: srdiag/bpm/c04-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-10
x_pos: srdiag/bpm/c04-10/SA_HPosition
y_pos: srdiag/bpm/c04-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-01
x_pos: srdiag/bpm/c05-01/SA_HPosition
y_pos: srdiag/bpm/c05-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-02
x_pos: srdiag/bpm/c05-02/SA_HPosition
y_pos: srdiag/bpm/c05-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-03
x_pos: srdiag/bpm/c05-03/SA_HPosition
y_pos: srdiag/bpm/c05-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-04
x_pos: srdiag/bpm/c05-04/SA_HPosition
y_pos: srdiag/bpm/c05-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-05
x_pos: srdiag/bpm/c05-05/SA_HPosition
y_pos: srdiag/bpm/c05-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-06
x_pos: srdiag/bpm/c05-06/SA_HPosition
y_pos: srdiag/bpm/c05-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-07
x_pos: srdiag/bpm/c05-07/SA_HPosition
y_pos: srdiag/bpm/c05-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-08
x_pos: srdiag/bpm/c05-08/SA_HPosition
y_pos: srdiag/bpm/c05-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-09
x_pos: srdiag/bpm/c05-09/SA_HPosition
y_pos: srdiag/bpm/c05-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C05-10
x_pos: srdiag/bpm/c05-10/SA_HPosition
y_pos: srdiag/bpm/c05-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-01
x_pos: srdiag/bpm/c06-01/SA_HPosition
y_pos: srdiag/bpm/c06-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-02
x_pos: srdiag/bpm/c06-02/SA_HPosition
y_pos: srdiag/bpm/c06-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-03
x_pos: srdiag/bpm/c06-03/SA_HPosition
y_pos: srdiag/bpm/c06-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-04
x_pos: srdiag/bpm/c06-04/SA_HPosition
y_pos: srdiag/bpm/c06-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-05
x_pos: srdiag/bpm/c06-05/SA_HPosition
y_pos: srdiag/bpm/c06-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-06
x_pos: srdiag/bpm/c06-06/SA_HPosition
y_pos: srdiag/bpm/c06-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-07
x_pos: srdiag/bpm/c06-07/SA_HPosition
y_pos: srdiag/bpm/c06-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-08
x_pos: srdiag/bpm/c06-08/SA_HPosition
y_pos: srdiag/bpm/c06-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-09
x_pos: srdiag/bpm/c06-09/SA_HPosition
y_pos: srdiag/bpm/c06-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C06-10
x_pos: srdiag/bpm/c06-10/SA_HPosition
y_pos: srdiag/bpm/c06-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-01
x_pos: srdiag/bpm/c07-01/SA_HPosition
y_pos: srdiag/bpm/c07-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-02
x_pos: srdiag/bpm/c07-02/SA_HPosition
y_pos: srdiag/bpm/c07-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-03
x_pos: srdiag/bpm/c07-03/SA_HPosition
y_pos: srdiag/bpm/c07-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-04
x_pos: srdiag/bpm/c07-04/SA_HPosition
y_pos: srdiag/bpm/c07-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-05
x_pos: srdiag/bpm/c07-05/SA_HPosition
y_pos: srdiag/bpm/c07-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-06
x_pos: srdiag/bpm/c07-06/SA_HPosition
y_pos: srdiag/bpm/c07-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-07
x_pos: srdiag/bpm/c07-07/SA_HPosition
y_pos: srdiag/bpm/c07-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-08
x_pos: srdiag/bpm/c07-08/SA_HPosition
y_pos: srdiag/bpm/c07-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-09
x_pos: srdiag/bpm/c07-09/SA_HPosition
y_pos: srdiag/bpm/c07-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C07-10
x_pos: srdiag/bpm/c07-10/SA_HPosition
y_pos: srdiag/bpm/c07-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-01
x_pos: srdiag/bpm/c08-01/SA_HPosition
y_pos: srdiag/bpm/c08-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-02
x_pos: srdiag/bpm/c08-02/SA_HPosition
y_pos: srdiag/bpm/c08-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-03
x_pos: srdiag/bpm/c08-03/SA_HPosition
y_pos: srdiag/bpm/c08-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-04
x_pos: srdiag/bpm/c08-04/SA_HPosition
y_pos: srdiag/bpm/c08-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-05
x_pos: srdiag/bpm/c08-05/SA_HPosition
y_pos: srdiag/bpm/c08-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-06
x_pos: srdiag/bpm/c08-06/SA_HPosition
y_pos: srdiag/bpm/c08-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-07
x_pos: srdiag/bpm/c08-07/SA_HPosition
y_pos: srdiag/bpm/c08-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-08
x_pos: srdiag/bpm/c08-08/SA_HPosition
y_pos: srdiag/bpm/c08-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-09
x_pos: srdiag/bpm/c08-09/SA_HPosition
y_pos: srdiag/bpm/c08-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C08-10
x_pos: srdiag/bpm/c08-10/SA_HPosition
y_pos: srdiag/bpm/c08-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-01
x_pos: srdiag/bpm/c09-01/SA_HPosition
y_pos: srdiag/bpm/c09-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-02
x_pos: srdiag/bpm/c09-02/SA_HPosition
y_pos: srdiag/bpm/c09-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-03
x_pos: srdiag/bpm/c09-03/SA_HPosition
y_pos: srdiag/bpm/c09-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-04
x_pos: srdiag/bpm/c09-04/SA_HPosition
y_pos: srdiag/bpm/c09-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-05
x_pos: srdiag/bpm/c09-05/SA_HPosition
y_pos: srdiag/bpm/c09-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-06
x_pos: srdiag/bpm/c09-06/SA_HPosition
y_pos: srdiag/bpm/c09-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-07
x_pos: srdiag/bpm/c09-07/SA_HPosition
y_pos: srdiag/bpm/c09-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-08
x_pos: srdiag/bpm/c09-08/SA_HPosition
y_pos: srdiag/bpm/c09-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-09
x_pos: srdiag/bpm/c09-09/SA_HPosition
y_pos: srdiag/bpm/c09-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C09-10
x_pos: srdiag/bpm/c09-10/SA_HPosition
y_pos: srdiag/bpm/c09-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-01
x_pos: srdiag/bpm/c10-01/SA_HPosition
y_pos: srdiag/bpm/c10-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-02
x_pos: srdiag/bpm/c10-02/SA_HPosition
y_pos: srdiag/bpm/c10-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-03
x_pos: srdiag/bpm/c10-03/SA_HPosition
y_pos: srdiag/bpm/c10-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-04
x_pos: srdiag/bpm/c10-04/SA_HPosition
y_pos: srdiag/bpm/c10-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-05
x_pos: srdiag/bpm/c10-05/SA_HPosition
y_pos: srdiag/bpm/c10-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-06
x_pos: srdiag/bpm/c10-06/SA_HPosition
y_pos: srdiag/bpm/c10-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-07
x_pos: srdiag/bpm/c10-07/SA_HPosition
y_pos: srdiag/bpm/c10-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-08
x_pos: srdiag/bpm/c10-08/SA_HPosition
y_pos: srdiag/bpm/c10-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-09
x_pos: srdiag/bpm/c10-09/SA_HPosition
y_pos: srdiag/bpm/c10-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C10-10
x_pos: srdiag/bpm/c10-10/SA_HPosition
y_pos: srdiag/bpm/c10-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-01
x_pos: srdiag/bpm/c11-01/SA_HPosition
y_pos: srdiag/bpm/c11-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-02
x_pos: srdiag/bpm/c11-02/SA_HPosition
y_pos: srdiag/bpm/c11-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-03
x_pos: srdiag/bpm/c11-03/SA_HPosition
y_pos: srdiag/bpm/c11-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-04
x_pos: srdiag/bpm/c11-04/SA_HPosition
y_pos: srdiag/bpm/c11-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-05
x_pos: srdiag/bpm/c11-05/SA_HPosition
y_pos: srdiag/bpm/c11-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-06
x_pos: srdiag/bpm/c11-06/SA_HPosition
y_pos: srdiag/bpm/c11-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-07
x_pos: srdiag/bpm/c11-07/SA_HPosition
y_pos: srdiag/bpm/c11-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-08
x_pos: srdiag/bpm/c11-08/SA_HPosition
y_pos: srdiag/bpm/c11-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-09
x_pos: srdiag/bpm/c11-09/SA_HPosition
y_pos: srdiag/bpm/c11-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C11-10
x_pos: srdiag/bpm/c11-10/SA_HPosition
y_pos: srdiag/bpm/c11-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-01
x_pos: srdiag/bpm/c12-01/SA_HPosition
y_pos: srdiag/bpm/c12-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-02
x_pos: srdiag/bpm/c12-02/SA_HPosition
y_pos: srdiag/bpm/c12-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-03
x_pos: srdiag/bpm/c12-03/SA_HPosition
y_pos: srdiag/bpm/c12-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-04
x_pos: srdiag/bpm/c12-04/SA_HPosition
y_pos: srdiag/bpm/c12-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-05
x_pos: srdiag/bpm/c12-05/SA_HPosition
y_pos: srdiag/bpm/c12-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-06
x_pos: srdiag/bpm/c12-06/SA_HPosition
y_pos: srdiag/bpm/c12-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-07
x_pos: srdiag/bpm/c12-07/SA_HPosition
y_pos: srdiag/bpm/c12-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-08
x_pos: srdiag/bpm/c12-08/SA_HPosition
y_pos: srdiag/bpm/c12-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-09
x_pos: srdiag/bpm/c12-09/SA_HPosition
y_pos: srdiag/bpm/c12-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C12-10
x_pos: srdiag/bpm/c12-10/SA_HPosition
y_pos: srdiag/bpm/c12-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-01
x_pos: srdiag/bpm/c13-01/SA_HPosition
y_pos: srdiag/bpm/c13-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-02
x_pos: srdiag/bpm/c13-02/SA_HPosition
y_pos: srdiag/bpm/c13-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-03
x_pos: srdiag/bpm/c13-03/SA_HPosition
y_pos: srdiag/bpm/c13-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-04
x_pos: srdiag/bpm/c13-04/SA_HPosition
y_pos: srdiag/bpm/c13-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-05
x_pos: srdiag/bpm/c13-05/SA_HPosition
y_pos: srdiag/bpm/c13-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-06
x_pos: srdiag/bpm/c13-06/SA_HPosition
y_pos: srdiag/bpm/c13-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-07
x_pos: srdiag/bpm/c13-07/SA_HPosition
y_pos: srdiag/bpm/c13-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-08
x_pos: srdiag/bpm/c13-08/SA_HPosition
y_pos: srdiag/bpm/c13-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-09
x_pos: srdiag/bpm/c13-09/SA_HPosition
y_pos: srdiag/bpm/c13-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C13-10
x_pos: srdiag/bpm/c13-10/SA_HPosition
y_pos: srdiag/bpm/c13-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-01
x_pos: srdiag/bpm/c14-01/SA_HPosition
y_pos: srdiag/bpm/c14-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-02
x_pos: srdiag/bpm/c14-02/SA_HPosition
y_pos: srdiag/bpm/c14-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-03
x_pos: srdiag/bpm/c14-03/SA_HPosition
y_pos: srdiag/bpm/c14-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-04
x_pos: srdiag/bpm/c14-04/SA_HPosition
y_pos: srdiag/bpm/c14-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-05
x_pos: srdiag/bpm/c14-05/SA_HPosition
y_pos: srdiag/bpm/c14-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-06
x_pos: srdiag/bpm/c14-06/SA_HPosition
y_pos: srdiag/bpm/c14-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-07
x_pos: srdiag/bpm/c14-07/SA_HPosition
y_pos: srdiag/bpm/c14-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-08
x_pos: srdiag/bpm/c14-08/SA_HPosition
y_pos: srdiag/bpm/c14-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-09
x_pos: srdiag/bpm/c14-09/SA_HPosition
y_pos: srdiag/bpm/c14-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C14-10
x_pos: srdiag/bpm/c14-10/SA_HPosition
y_pos: srdiag/bpm/c14-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-01
x_pos: srdiag/bpm/c15-01/SA_HPosition
y_pos: srdiag/bpm/c15-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-02
x_pos: srdiag/bpm/c15-02/SA_HPosition
y_pos: srdiag/bpm/c15-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-03
x_pos: srdiag/bpm/c15-03/SA_HPosition
y_pos: srdiag/bpm/c15-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-04
x_pos: srdiag/bpm/c15-04/SA_HPosition
y_pos: srdiag/bpm/c15-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-05
x_pos: srdiag/bpm/c15-05/SA_HPosition
y_pos: srdiag/bpm/c15-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-06
x_pos: srdiag/bpm/c15-06/SA_HPosition
y_pos: srdiag/bpm/c15-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-07
x_pos: srdiag/bpm/c15-07/SA_HPosition
y_pos: srdiag/bpm/c15-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-08
x_pos: srdiag/bpm/c15-08/SA_HPosition
y_pos: srdiag/bpm/c15-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-09
x_pos: srdiag/bpm/c15-09/SA_HPosition
y_pos: srdiag/bpm/c15-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C15-10
x_pos: srdiag/bpm/c15-10/SA_HPosition
y_pos: srdiag/bpm/c15-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-01
x_pos: srdiag/bpm/c16-01/SA_HPosition
y_pos: srdiag/bpm/c16-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-02
x_pos: srdiag/bpm/c16-02/SA_HPosition
y_pos: srdiag/bpm/c16-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-03
x_pos: srdiag/bpm/c16-03/SA_HPosition
y_pos: srdiag/bpm/c16-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-04
x_pos: srdiag/bpm/c16-04/SA_HPosition
y_pos: srdiag/bpm/c16-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-05
x_pos: srdiag/bpm/c16-05/SA_HPosition
y_pos: srdiag/bpm/c16-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-06
x_pos: srdiag/bpm/c16-06/SA_HPosition
y_pos: srdiag/bpm/c16-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-07
x_pos: srdiag/bpm/c16-07/SA_HPosition
y_pos: srdiag/bpm/c16-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-08
x_pos: srdiag/bpm/c16-08/SA_HPosition
y_pos: srdiag/bpm/c16-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-09
x_pos: srdiag/bpm/c16-09/SA_HPosition
y_pos: srdiag/bpm/c16-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C16-10
x_pos: srdiag/bpm/c16-10/SA_HPosition
y_pos: srdiag/bpm/c16-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-01
x_pos: srdiag/bpm/c17-01/SA_HPosition
y_pos: srdiag/bpm/c17-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-02
x_pos: srdiag/bpm/c17-02/SA_HPosition
y_pos: srdiag/bpm/c17-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-03
x_pos: srdiag/bpm/c17-03/SA_HPosition
y_pos: srdiag/bpm/c17-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-04
x_pos: srdiag/bpm/c17-04/SA_HPosition
y_pos: srdiag/bpm/c17-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-05
x_pos: srdiag/bpm/c17-05/SA_HPosition
y_pos: srdiag/bpm/c17-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-06
x_pos: srdiag/bpm/c17-06/SA_HPosition
y_pos: srdiag/bpm/c17-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-07
x_pos: srdiag/bpm/c17-07/SA_HPosition
y_pos: srdiag/bpm/c17-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-08
x_pos: srdiag/bpm/c17-08/SA_HPosition
y_pos: srdiag/bpm/c17-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-09
x_pos: srdiag/bpm/c17-09/SA_HPosition
y_pos: srdiag/bpm/c17-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C17-10
x_pos: srdiag/bpm/c17-10/SA_HPosition
y_pos: srdiag/bpm/c17-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-01
x_pos: srdiag/bpm/c18-01/SA_HPosition
y_pos: srdiag/bpm/c18-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-02
x_pos: srdiag/bpm/c18-02/SA_HPosition
y_pos: srdiag/bpm/c18-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-03
x_pos: srdiag/bpm/c18-03/SA_HPosition
y_pos: srdiag/bpm/c18-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-04
x_pos: srdiag/bpm/c18-04/SA_HPosition
y_pos: srdiag/bpm/c18-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-05
x_pos: srdiag/bpm/c18-05/SA_HPosition
y_pos: srdiag/bpm/c18-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-06
x_pos: srdiag/bpm/c18-06/SA_HPosition
y_pos: srdiag/bpm/c18-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-07
x_pos: srdiag/bpm/c18-07/SA_HPosition
y_pos: srdiag/bpm/c18-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-08
x_pos: srdiag/bpm/c18-08/SA_HPosition
y_pos: srdiag/bpm/c18-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-09
x_pos: srdiag/bpm/c18-09/SA_HPosition
y_pos: srdiag/bpm/c18-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C18-10
x_pos: srdiag/bpm/c18-10/SA_HPosition
y_pos: srdiag/bpm/c18-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-01
x_pos: srdiag/bpm/c19-01/SA_HPosition
y_pos: srdiag/bpm/c19-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-02
x_pos: srdiag/bpm/c19-02/SA_HPosition
y_pos: srdiag/bpm/c19-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-03
x_pos: srdiag/bpm/c19-03/SA_HPosition
y_pos: srdiag/bpm/c19-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-04
x_pos: srdiag/bpm/c19-04/SA_HPosition
y_pos: srdiag/bpm/c19-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-05
x_pos: srdiag/bpm/c19-05/SA_HPosition
y_pos: srdiag/bpm/c19-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-06
x_pos: srdiag/bpm/c19-06/SA_HPosition
y_pos: srdiag/bpm/c19-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-07
x_pos: srdiag/bpm/c19-07/SA_HPosition
y_pos: srdiag/bpm/c19-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-08
x_pos: srdiag/bpm/c19-08/SA_HPosition
y_pos: srdiag/bpm/c19-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-09
x_pos: srdiag/bpm/c19-09/SA_HPosition
y_pos: srdiag/bpm/c19-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C19-10
x_pos: srdiag/bpm/c19-10/SA_HPosition
y_pos: srdiag/bpm/c19-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-01
x_pos: srdiag/bpm/c20-01/SA_HPosition
y_pos: srdiag/bpm/c20-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-02
x_pos: srdiag/bpm/c20-02/SA_HPosition
y_pos: srdiag/bpm/c20-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-03
x_pos: srdiag/bpm/c20-03/SA_HPosition
y_pos: srdiag/bpm/c20-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-04
x_pos: srdiag/bpm/c20-04/SA_HPosition
y_pos: srdiag/bpm/c20-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-05
x_pos: srdiag/bpm/c20-05/SA_HPosition
y_pos: srdiag/bpm/c20-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-06
x_pos: srdiag/bpm/c20-06/SA_HPosition
y_pos: srdiag/bpm/c20-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-07
x_pos: srdiag/bpm/c20-07/SA_HPosition
y_pos: srdiag/bpm/c20-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-08
x_pos: srdiag/bpm/c20-08/SA_HPosition
y_pos: srdiag/bpm/c20-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-09
x_pos: srdiag/bpm/c20-09/SA_HPosition
y_pos: srdiag/bpm/c20-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C20-10
x_pos: srdiag/bpm/c20-10/SA_HPosition
y_pos: srdiag/bpm/c20-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-01
x_pos: srdiag/bpm/c21-01/SA_HPosition
y_pos: srdiag/bpm/c21-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-02
x_pos: srdiag/bpm/c21-02/SA_HPosition
y_pos: srdiag/bpm/c21-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-03
x_pos: srdiag/bpm/c21-03/SA_HPosition
y_pos: srdiag/bpm/c21-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-04
x_pos: srdiag/bpm/c21-04/SA_HPosition
y_pos: srdiag/bpm/c21-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-05
x_pos: srdiag/bpm/c21-05/SA_HPosition
y_pos: srdiag/bpm/c21-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-06
x_pos: srdiag/bpm/c21-06/SA_HPosition
y_pos: srdiag/bpm/c21-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-07
x_pos: srdiag/bpm/c21-07/SA_HPosition
y_pos: srdiag/bpm/c21-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-08
x_pos: srdiag/bpm/c21-08/SA_HPosition
y_pos: srdiag/bpm/c21-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-09
x_pos: srdiag/bpm/c21-09/SA_HPosition
y_pos: srdiag/bpm/c21-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C21-10
x_pos: srdiag/bpm/c21-10/SA_HPosition
y_pos: srdiag/bpm/c21-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-01
x_pos: srdiag/bpm/c22-01/SA_HPosition
y_pos: srdiag/bpm/c22-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-02
x_pos: srdiag/bpm/c22-02/SA_HPosition
y_pos: srdiag/bpm/c22-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-03
x_pos: srdiag/bpm/c22-03/SA_HPosition
y_pos: srdiag/bpm/c22-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-04
x_pos: srdiag/bpm/c22-04/SA_HPosition
y_pos: srdiag/bpm/c22-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-05
x_pos: srdiag/bpm/c22-05/SA_HPosition
y_pos: srdiag/bpm/c22-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-06
x_pos: srdiag/bpm/c22-06/SA_HPosition
y_pos: srdiag/bpm/c22-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-07
x_pos: srdiag/bpm/c22-07/SA_HPosition
y_pos: srdiag/bpm/c22-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-08
x_pos: srdiag/bpm/c22-08/SA_HPosition
y_pos: srdiag/bpm/c22-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-09
x_pos: srdiag/bpm/c22-09/SA_HPosition
y_pos: srdiag/bpm/c22-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C22-10
x_pos: srdiag/bpm/c22-10/SA_HPosition
y_pos: srdiag/bpm/c22-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-01
x_pos: srdiag/bpm/c23-01/SA_HPosition
y_pos: srdiag/bpm/c23-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-02
x_pos: srdiag/bpm/c23-02/SA_HPosition
y_pos: srdiag/bpm/c23-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-03
x_pos: srdiag/bpm/c23-03/SA_HPosition
y_pos: srdiag/bpm/c23-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-04
x_pos: srdiag/bpm/c23-04/SA_HPosition
y_pos: srdiag/bpm/c23-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-05
x_pos: srdiag/bpm/c23-05/SA_HPosition
y_pos: srdiag/bpm/c23-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-06
x_pos: srdiag/bpm/c23-06/SA_HPosition
y_pos: srdiag/bpm/c23-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-07
x_pos: srdiag/bpm/c23-07/SA_HPosition
y_pos: srdiag/bpm/c23-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-08
x_pos: srdiag/bpm/c23-08/SA_HPosition
y_pos: srdiag/bpm/c23-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-09
x_pos: srdiag/bpm/c23-09/SA_HPosition
y_pos: srdiag/bpm/c23-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C23-10
x_pos: srdiag/bpm/c23-10/SA_HPosition
y_pos: srdiag/bpm/c23-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-01
x_pos: srdiag/bpm/c24-01/SA_HPosition
y_pos: srdiag/bpm/c24-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-02
x_pos: srdiag/bpm/c24-02/SA_HPosition
y_pos: srdiag/bpm/c24-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-03
x_pos: srdiag/bpm/c24-03/SA_HPosition
y_pos: srdiag/bpm/c24-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-04
x_pos: srdiag/bpm/c24-04/SA_HPosition
y_pos: srdiag/bpm/c24-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-05
x_pos: srdiag/bpm/c24-05/SA_HPosition
y_pos: srdiag/bpm/c24-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-06
x_pos: srdiag/bpm/c24-06/SA_HPosition
y_pos: srdiag/bpm/c24-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-07
x_pos: srdiag/bpm/c24-07/SA_HPosition
y_pos: srdiag/bpm/c24-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-08
x_pos: srdiag/bpm/c24-08/SA_HPosition
y_pos: srdiag/bpm/c24-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-09
x_pos: srdiag/bpm/c24-09/SA_HPosition
y_pos: srdiag/bpm/c24-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C24-10
x_pos: srdiag/bpm/c24-10/SA_HPosition
y_pos: srdiag/bpm/c24-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-01
x_pos: srdiag/bpm/c25-01/SA_HPosition
y_pos: srdiag/bpm/c25-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-02
x_pos: srdiag/bpm/c25-02/SA_HPosition
y_pos: srdiag/bpm/c25-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-03
x_pos: srdiag/bpm/c25-03/SA_HPosition
y_pos: srdiag/bpm/c25-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-04
x_pos: srdiag/bpm/c25-04/SA_HPosition
y_pos: srdiag/bpm/c25-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-05
x_pos: srdiag/bpm/c25-05/SA_HPosition
y_pos: srdiag/bpm/c25-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-06
x_pos: srdiag/bpm/c25-06/SA_HPosition
y_pos: srdiag/bpm/c25-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-07
x_pos: srdiag/bpm/c25-07/SA_HPosition
y_pos: srdiag/bpm/c25-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-08
x_pos: srdiag/bpm/c25-08/SA_HPosition
y_pos: srdiag/bpm/c25-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-09
x_pos: srdiag/bpm/c25-09/SA_HPosition
y_pos: srdiag/bpm/c25-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C25-10
x_pos: srdiag/bpm/c25-10/SA_HPosition
y_pos: srdiag/bpm/c25-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-01
x_pos: srdiag/bpm/c26-01/SA_HPosition
y_pos: srdiag/bpm/c26-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-02
x_pos: srdiag/bpm/c26-02/SA_HPosition
y_pos: srdiag/bpm/c26-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-03
x_pos: srdiag/bpm/c26-03/SA_HPosition
y_pos: srdiag/bpm/c26-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-04
x_pos: srdiag/bpm/c26-04/SA_HPosition
y_pos: srdiag/bpm/c26-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-05
x_pos: srdiag/bpm/c26-05/SA_HPosition
y_pos: srdiag/bpm/c26-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-06
x_pos: srdiag/bpm/c26-06/SA_HPosition
y_pos: srdiag/bpm/c26-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-07
x_pos: srdiag/bpm/c26-07/SA_HPosition
y_pos: srdiag/bpm/c26-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-08
x_pos: srdiag/bpm/c26-08/SA_HPosition
y_pos: srdiag/bpm/c26-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-09
x_pos: srdiag/bpm/c26-09/SA_HPosition
y_pos: srdiag/bpm/c26-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C26-10
x_pos: srdiag/bpm/c26-10/SA_HPosition
y_pos: srdiag/bpm/c26-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-01
x_pos: srdiag/bpm/c27-01/SA_HPosition
y_pos: srdiag/bpm/c27-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-02
x_pos: srdiag/bpm/c27-02/SA_HPosition
y_pos: srdiag/bpm/c27-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-03
x_pos: srdiag/bpm/c27-03/SA_HPosition
y_pos: srdiag/bpm/c27-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-04
x_pos: srdiag/bpm/c27-04/SA_HPosition
y_pos: srdiag/bpm/c27-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-05
x_pos: srdiag/bpm/c27-05/SA_HPosition
y_pos: srdiag/bpm/c27-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-06
x_pos: srdiag/bpm/c27-06/SA_HPosition
y_pos: srdiag/bpm/c27-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-07
x_pos: srdiag/bpm/c27-07/SA_HPosition
y_pos: srdiag/bpm/c27-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-08
x_pos: srdiag/bpm/c27-08/SA_HPosition
y_pos: srdiag/bpm/c27-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-09
x_pos: srdiag/bpm/c27-09/SA_HPosition
y_pos: srdiag/bpm/c27-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C27-10
x_pos: srdiag/bpm/c27-10/SA_HPosition
y_pos: srdiag/bpm/c27-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-01
x_pos: srdiag/bpm/c28-01/SA_HPosition
y_pos: srdiag/bpm/c28-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-02
x_pos: srdiag/bpm/c28-02/SA_HPosition
y_pos: srdiag/bpm/c28-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-03
x_pos: srdiag/bpm/c28-03/SA_HPosition
y_pos: srdiag/bpm/c28-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-04
x_pos: srdiag/bpm/c28-04/SA_HPosition
y_pos: srdiag/bpm/c28-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-05
x_pos: srdiag/bpm/c28-05/SA_HPosition
y_pos: srdiag/bpm/c28-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-06
x_pos: srdiag/bpm/c28-06/SA_HPosition
y_pos: srdiag/bpm/c28-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-07
x_pos: srdiag/bpm/c28-07/SA_HPosition
y_pos: srdiag/bpm/c28-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-08
x_pos: srdiag/bpm/c28-08/SA_HPosition
y_pos: srdiag/bpm/c28-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-09
x_pos: srdiag/bpm/c28-09/SA_HPosition
y_pos: srdiag/bpm/c28-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C28-10
x_pos: srdiag/bpm/c28-10/SA_HPosition
y_pos: srdiag/bpm/c28-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-01
x_pos: srdiag/bpm/c29-01/SA_HPosition
y_pos: srdiag/bpm/c29-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-02
x_pos: srdiag/bpm/c29-02/SA_HPosition
y_pos: srdiag/bpm/c29-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-03
x_pos: srdiag/bpm/c29-03/SA_HPosition
y_pos: srdiag/bpm/c29-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-04
x_pos: srdiag/bpm/c29-04/SA_HPosition
y_pos: srdiag/bpm/c29-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-05
x_pos: srdiag/bpm/c29-05/SA_HPosition
y_pos: srdiag/bpm/c29-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-06
x_pos: srdiag/bpm/c29-06/SA_HPosition
y_pos: srdiag/bpm/c29-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-07
x_pos: srdiag/bpm/c29-07/SA_HPosition
y_pos: srdiag/bpm/c29-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-08
x_pos: srdiag/bpm/c29-08/SA_HPosition
y_pos: srdiag/bpm/c29-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-09
x_pos: srdiag/bpm/c29-09/SA_HPosition
y_pos: srdiag/bpm/c29-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C29-10
x_pos: srdiag/bpm/c29-10/SA_HPosition
y_pos: srdiag/bpm/c29-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-01
x_pos: srdiag/bpm/c30-01/SA_HPosition
y_pos: srdiag/bpm/c30-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-02
x_pos: srdiag/bpm/c30-02/SA_HPosition
y_pos: srdiag/bpm/c30-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-03
x_pos: srdiag/bpm/c30-03/SA_HPosition
y_pos: srdiag/bpm/c30-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-04
x_pos: srdiag/bpm/c30-04/SA_HPosition
y_pos: srdiag/bpm/c30-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-05
x_pos: srdiag/bpm/c30-05/SA_HPosition
y_pos: srdiag/bpm/c30-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-06
x_pos: srdiag/bpm/c30-06/SA_HPosition
y_pos: srdiag/bpm/c30-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-07
x_pos: srdiag/bpm/c30-07/SA_HPosition
y_pos: srdiag/bpm/c30-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-08
x_pos: srdiag/bpm/c30-08/SA_HPosition
y_pos: srdiag/bpm/c30-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-09
x_pos: srdiag/bpm/c30-09/SA_HPosition
y_pos: srdiag/bpm/c30-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C30-10
x_pos: srdiag/bpm/c30-10/SA_HPosition
y_pos: srdiag/bpm/c30-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-01
x_pos: srdiag/bpm/c31-01/SA_HPosition
y_pos: srdiag/bpm/c31-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-02
x_pos: srdiag/bpm/c31-02/SA_HPosition
y_pos: srdiag/bpm/c31-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-03
x_pos: srdiag/bpm/c31-03/SA_HPosition
y_pos: srdiag/bpm/c31-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-04
x_pos: srdiag/bpm/c31-04/SA_HPosition
y_pos: srdiag/bpm/c31-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-05
x_pos: srdiag/bpm/c31-05/SA_HPosition
y_pos: srdiag/bpm/c31-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-06
x_pos: srdiag/bpm/c31-06/SA_HPosition
y_pos: srdiag/bpm/c31-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-07
x_pos: srdiag/bpm/c31-07/SA_HPosition
y_pos: srdiag/bpm/c31-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-08
x_pos: srdiag/bpm/c31-08/SA_HPosition
y_pos: srdiag/bpm/c31-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-09
x_pos: srdiag/bpm/c31-09/SA_HPosition
y_pos: srdiag/bpm/c31-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C31-10
x_pos: srdiag/bpm/c31-10/SA_HPosition
y_pos: srdiag/bpm/c31-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-01
x_pos: srdiag/bpm/c32-01/SA_HPosition
y_pos: srdiag/bpm/c32-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-02
x_pos: srdiag/bpm/c32-02/SA_HPosition
y_pos: srdiag/bpm/c32-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-03
x_pos: srdiag/bpm/c32-03/SA_HPosition
y_pos: srdiag/bpm/c32-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-04
x_pos: srdiag/bpm/c32-04/SA_HPosition
y_pos: srdiag/bpm/c32-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-05
x_pos: srdiag/bpm/c32-05/SA_HPosition
y_pos: srdiag/bpm/c32-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-06
x_pos: srdiag/bpm/c32-06/SA_HPosition
y_pos: srdiag/bpm/c32-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-07
x_pos: srdiag/bpm/c32-07/SA_HPosition
y_pos: srdiag/bpm/c32-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-08
x_pos: srdiag/bpm/c32-08/SA_HPosition
y_pos: srdiag/bpm/c32-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-09
x_pos: srdiag/bpm/c32-09/SA_HPosition
y_pos: srdiag/bpm/c32-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C32-10
x_pos: srdiag/bpm/c32-10/SA_HPosition
y_pos: srdiag/bpm/c32-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-01
x_pos: srdiag/bpm/c01-01/SA_HPosition
y_pos: srdiag/bpm/c01-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-02
x_pos: srdiag/bpm/c01-02/SA_HPosition
y_pos: srdiag/bpm/c01-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-03
x_pos: srdiag/bpm/c01-03/SA_HPosition
y_pos: srdiag/bpm/c01-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-04
x_pos: srdiag/bpm/c01-04/SA_HPosition
y_pos: srdiag/bpm/c01-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-05
x_pos: srdiag/bpm/c01-05/SA_HPosition
y_pos: srdiag/bpm/c01-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-06
x_pos: srdiag/bpm/c01-06/SA_HPosition
y_pos: srdiag/bpm/c01-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-07
x_pos: srdiag/bpm/c01-07/SA_HPosition
y_pos: srdiag/bpm/c01-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-08
x_pos: srdiag/bpm/c01-08/SA_HPosition
y_pos: srdiag/bpm/c01-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-09
x_pos: srdiag/bpm/c01-09/SA_HPosition
y_pos: srdiag/bpm/c01-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-10
x_pos: srdiag/bpm/c01-10/SA_HPosition
y_pos: srdiag/bpm/c01-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-01
x_pos: srdiag/bpm/c02-01/SA_HPosition
y_pos: srdiag/bpm/c02-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-02
x_pos: srdiag/bpm/c02-02/SA_HPosition
y_pos: srdiag/bpm/c02-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-03
x_pos: srdiag/bpm/c02-03/SA_HPosition
y_pos: srdiag/bpm/c02-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-04
x_pos: srdiag/bpm/c02-04/SA_HPosition
y_pos: srdiag/bpm/c02-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-05
x_pos: srdiag/bpm/c02-05/SA_HPosition
y_pos: srdiag/bpm/c02-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-06
x_pos: srdiag/bpm/c02-06/SA_HPosition
y_pos: srdiag/bpm/c02-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-07
x_pos: srdiag/bpm/c02-07/SA_HPosition
y_pos: srdiag/bpm/c02-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-08
x_pos: srdiag/bpm/c02-08/SA_HPosition
y_pos: srdiag/bpm/c02-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-09
x_pos: srdiag/bpm/c02-09/SA_HPosition
y_pos: srdiag/bpm/c02-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C02-10
x_pos: srdiag/bpm/c02-10/SA_HPosition
y_pos: srdiag/bpm/c02-10/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-01
x_pos: srdiag/bpm/c03-01/SA_HPosition
y_pos: srdiag/bpm/c03-01/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-02
x_pos: srdiag/bpm/c03-02/SA_HPosition
y_pos: srdiag/bpm/c03-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-03
x_pos: srdiag/bpm/c03-03/SA_HPosition
y_pos: srdiag/bpm/c03-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-04
x_pos: srdiag/bpm/c03-04/SA_HPosition
y_pos: srdiag/bpm/c03-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-05
x_pos: srdiag/bpm/c03-05/SA_HPosition
y_pos: srdiag/bpm/c03-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-06
x_pos: srdiag/bpm/c03-06/SA_HPosition
y_pos: srdiag/bpm/c03-06/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-07
x_pos: srdiag/bpm/c03-07/SA_HPosition
y_pos: srdiag/bpm/c03-07/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-08
x_pos: srdiag/bpm/c03-08/SA_HPosition
y_pos: srdiag/bpm/c03-08/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-09
x_pos: srdiag/bpm/c03-09/SA_HPosition
y_pos: srdiag/bpm/c03-09/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C03-10
x_pos: srdiag/bpm/c03-10/SA_HPosition
y_pos: srdiag/bpm/c03-10/SA_VPosition
diff --git a/tests/config/EBSTune-patterns.yaml b/tests/config/EBSTune-patterns.yaml
index 0c258bdea..c0bad0f4c 100644
--- a/tests/config/EBSTune-patterns.yaml
+++ b/tests/config/EBSTune-patterns.yaml
@@ -12,7 +12,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
diff --git a/tests/config/EBSTune.yaml b/tests/config/EBSTune.yaml
index f5a8d5c08..52c7d0119 100644
--- a/tests/config/EBSTune.yaml
+++ b/tests/config/EBSTune.yaml
@@ -12,7 +12,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
diff --git a/tests/config/EBS_rf_multi.yaml b/tests/config/EBS_rf_multi.yaml
index d3c7133be..f1025118b 100644
--- a/tests/config/EBS_rf_multi.yaml
+++ b/tests/config/EBS_rf_multi.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
devices:
- type: pyaml.rf.rf_plant
diff --git a/tests/config/EBS_rf_notrans.yaml b/tests/config/EBS_rf_notrans.yaml
index 1306d8c28..daff32790 100644
--- a/tests/config/EBS_rf_notrans.yaml
+++ b/tests/config/EBS_rf_notrans.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
devices:
- type: pyaml.rf.rf_plant
diff --git a/tests/config/bad_conf.yml b/tests/config/bad_conf.yml
index 178733b4a..513aafebe 100644
--- a/tests/config/bad_conf.yml
+++ b/tests/config/bad_conf.yml
@@ -19,6 +19,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/bad_conf_cycles.json b/tests/config/bad_conf_cycles.json
index 26af53c1f..11f0d6498 100644
--- a/tests/config/bad_conf_cycles.json
+++ b/tests/config/bad_conf_cycles.json
@@ -3,7 +3,7 @@
"facility": "ESRF",
"machine": "sr",
"energy": 6e9,
- "simulators": ["../config/bad_conf_cycles.json"],
+ "simulators": ["${include:../config/bad_conf_cycles.json}"],
"data_folder": "/data/store",
"arrays": [
{
@@ -21,8 +21,8 @@
}
],
"devices": [
- "sr/quadrupoles/QF1AC01.yaml",
- "sr/correctors/SH1AC01.yaml",
- "sr/correctors/SH1AC02.yaml"
+ "${include:sr/quadrupoles/QF1AC01.yaml}",
+ "${include:sr/correctors/SH1AC01.yaml}",
+ "${include:sr/correctors/SH1AC02.yaml}"
]
}
diff --git a/tests/config/bad_conf_cycles.yml b/tests/config/bad_conf_cycles.yml
index c0361864a..7cfa167d3 100644
--- a/tests/config/bad_conf_cycles.yml
+++ b/tests/config/bad_conf_cycles.yml
@@ -19,7 +19,7 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - ../config/bad_conf_cycles.yml # Cycle here
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:../config/bad_conf_cycles.yml} # Cycle here
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/bad_conf_duplicate_1.yaml b/tests/config/bad_conf_duplicate_1.yaml
index 209c3be09..608d07655 100644
--- a/tests/config/bad_conf_duplicate_1.yaml
+++ b/tests/config/bad_conf_duplicate_1.yaml
@@ -20,6 +20,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/bad_conf_duplicate_2.yaml b/tests/config/bad_conf_duplicate_2.yaml
index 346957aa8..a36c5400f 100644
--- a/tests/config/bad_conf_duplicate_2.yaml
+++ b/tests/config/bad_conf_duplicate_2.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.bpm
@@ -21,15 +21,15 @@ arrays:
- BPM_C04-06
- BPM_C04-06 # duplicate name in array
devices:
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-04
x_pos: srdiag/bpm/c04-04/SA_HPosition
y_pos: srdiag/bpm/c04-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-05
x_pos: srdiag/bpm/c04-05/SA_HPosition
y_pos: srdiag/bpm/c04-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-06
x_pos: srdiag/bpm/c04-06/SA_HPosition
y_pos: srdiag/bpm/c04-06/SA_VPosition
diff --git a/tests/config/bad_conf_duplicate_3.yaml b/tests/config/bad_conf_duplicate_3.yaml
index 9149009fb..ed1024a4d 100644
--- a/tests/config/bad_conf_duplicate_3.yaml
+++ b/tests/config/bad_conf_duplicate_3.yaml
@@ -12,7 +12,7 @@ controls:
name: live
catalog: bpm-catalog
catalogs:
- - catalogs/sr_catalogs.yaml
+ - ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.bpm
@@ -22,19 +22,19 @@ arrays:
- BPM_C04-05
- BPM_C04-06
devices:
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-04
x_pos: srdiag/bpm/c04-04/SA_HPosition
y_pos: srdiag/bpm/c04-04/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-05
x_pos: srdiag/bpm/c04-05/SA_HPosition
y_pos: srdiag/bpm/c04-05/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-06
x_pos: srdiag/bpm/c04-06/SA_HPosition
y_pos: srdiag/bpm/c04-06/SA_VPosition
-- type: pyaml.bpm.bpm # duplicate device
+- type: pyaml.diagnostics.bpm.bpm # duplicate device
name: BPM_C04-06
x_pos: srdiag/bpm/c04-06/SA_HPosition
y_pos: srdiag/bpm/c04-06/SA_VPosition
diff --git a/tests/config/bad_conf_duplicate_4.yaml b/tests/config/bad_conf_duplicate_4.yaml
index 95beb2f24..fc1faad04 100644
--- a/tests/config/bad_conf_duplicate_4.yaml
+++ b/tests/config/bad_conf_duplicate_4.yaml
@@ -19,6 +19,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/bpms.yaml b/tests/config/bpms.yaml
index 07caf59af..3312a186e 100644
--- a/tests/config/bpms.yaml
+++ b/tests/config/bpms.yaml
@@ -10,25 +10,25 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
devices:
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-01
x_pos: srdiag/bpm/c01-01/SA_HPosition
y_pos: srdiag/bpm/c01-01/SA_VPosition
x_offset: srdiag/bpm/c01-01/HOffset
y_offset: srdiag/bpm/c01-01/VOffset
tilt: srdiag/bpm/c01-01/Tilt_Angle
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-02
x_pos: srdiag/bpm/c01-02/SA_HPosition
y_pos: srdiag/bpm/c01-02/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-03
x_pos: srdiag/bpm/c01-03/SA_HPosition
y_pos: srdiag/bpm/c01-03/SA_VPosition
-- type: pyaml.bpm.bpm
+- type: pyaml.diagnostics.bpm.bpm
name: BPM_C01-04
x_pos: srdiag/bpm/c01-04/SA_HPosition
y_pos: srdiag/bpm/c01-04/SA_VPosition
@@ -42,4 +42,4 @@ devices:
- [B0, SH1A-C01-H]
- [A0, SH1A-C01-V]
- [A1, SH1A-C01-SQ]
- model: sr/magnet_models/SH1AC01.yaml
+ model: ${include:sr/magnet_models/SH1AC01.yaml}
diff --git a/tests/config/catalogs/ebs_catalogs.yaml b/tests/config/catalogs/ebs_catalogs.yaml
index d15349d6f..b3da9a0d4 100644
--- a/tests/config/catalogs/ebs_catalogs.yaml
+++ b/tests/config/catalogs/ebs_catalogs.yaml
@@ -1,8 +1,8 @@
type: tango.pyaml.static_catalog
entries:
- - catalogs/ebs_bpm_catalogs.yaml
- - catalogs/ebs_rf_catalogs.yaml
- - catalogs/ebs_diag_catalogs.yaml
- - catalogs/ebs_magnets_catalogs.yaml
- - catalogs/ebs_sh_catalogs.yaml
- - catalogs/ebs_sext_catalogs.yaml
+ - ${include:catalogs/ebs_bpm_catalogs.yaml}
+ - ${include:catalogs/ebs_rf_catalogs.yaml}
+ - ${include:catalogs/ebs_diag_catalogs.yaml}
+ - ${include:catalogs/ebs_magnets_catalogs.yaml}
+ - ${include:catalogs/ebs_sh_catalogs.yaml}
+ - ${include:catalogs/ebs_sext_catalogs.yaml}
diff --git a/tests/config/config_manager_sr_base.yaml b/tests/config/config_manager_sr_base.yaml
index c842221ac..0d829bfda 100644
--- a/tests/config/config_manager_sr_base.yaml
+++ b/tests/config/config_manager_sr_base.yaml
@@ -10,5 +10,5 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
diff --git a/tests/config/config_manager_sr_catalogs.yaml b/tests/config/config_manager_sr_catalogs.yaml
index 2a0f93347..6fae41e5f 100644
--- a/tests/config/config_manager_sr_catalogs.yaml
+++ b/tests/config/config_manager_sr_catalogs.yaml
@@ -1,2 +1,2 @@
catalogs:
- - catalogs/sr_catalogs.yaml
+ - ${include:catalogs/sr_catalogs.yaml}
diff --git a/tests/config/config_manager_sr_devices.yaml b/tests/config/config_manager_sr_devices.yaml
index c6d3e2124..f763942a6 100644
--- a/tests/config/config_manager_sr_devices.yaml
+++ b/tests/config/config_manager_sr_devices.yaml
@@ -1,11 +1,11 @@
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01-C02.yaml
- - type: pyaml.bpm.bpm
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01-C02.yaml}
+ - type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-01
x_pos: srdiag/bpm/c04-01/SA_HPosition
y_pos: srdiag/bpm/c04-01/SA_VPosition
- - type: pyaml.bpm.bpm
+ - type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-02
x_pos: srdiag/bpm/c04-02/SA_HPosition
y_pos: srdiag/bpm/c04-02/SA_VPosition
diff --git a/tests/config/sr-attribute-linker.yaml b/tests/config/sr-attribute-linker.yaml
index 1eb8edbbf..98d531d8c 100644
--- a/tests/config/sr-attribute-linker.yaml
+++ b/tests/config/sr-attribute-linker.yaml
@@ -22,6 +22,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/sr-ident-cfm.yaml b/tests/config/sr-ident-cfm.yaml
index 7bc833fdf..11e0fbd4c 100644
--- a/tests/config/sr-ident-cfm.yaml
+++ b/tests/config/sr-ident-cfm.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
@@ -24,6 +24,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01-ident.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01-ident.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/sr-range-cfm.yaml b/tests/config/sr-range-cfm.yaml
index fc1b37217..466531e79 100644
--- a/tests/config/sr-range-cfm.yaml
+++ b/tests/config/sr-range-cfm.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
@@ -24,6 +24,6 @@ arrays:
- SH1A-C01-V
- SH1A-C02-V
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01-range.yaml
- - sr/correctors/SH1AC02.yaml
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01-range.yaml}
+ - ${include:sr/correctors/SH1AC02.yaml}
diff --git a/tests/config/sr.yaml b/tests/config/sr.yaml
index 3e9561e81..a5363f929 100644
--- a/tests/config/sr.yaml
+++ b/tests/config/sr.yaml
@@ -10,7 +10,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/sr_catalogs.yaml
+ catalog: ${include:catalogs/sr_catalogs.yaml}
data_folder: /data/store
arrays:
- type: pyaml.arrays.magnet
@@ -41,13 +41,13 @@ arrays:
- SH1A-C01-V
- SH1A-C02-H
devices:
- - sr/quadrupoles/QF1AC01.yaml
- - sr/correctors/SH1AC01-C02.yaml
- - type: pyaml.bpm.bpm
+ - ${include:sr/quadrupoles/QF1AC01.yaml}
+ - ${include:sr/correctors/SH1AC01-C02.yaml}
+ - type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-01
x_pos: srdiag/bpm/c04-01/SA_HPosition
y_pos: srdiag/bpm/c04-01/SA_VPosition
- - type: pyaml.bpm.bpm
+ - type: pyaml.diagnostics.bpm.bpm
name: BPM_C04-02
x_pos: srdiag/bpm/c04-02/SA_HPosition
y_pos: srdiag/bpm/c04-02/SA_VPosition
diff --git a/tests/config/sr/correctors/SH1AC01-C02.yaml b/tests/config/sr/correctors/SH1AC01-C02.yaml
index 0bba2e4f0..295d1e520 100644
--- a/tests/config/sr/correctors/SH1AC01-C02.yaml
+++ b/tests/config/sr/correctors/SH1AC01-C02.yaml
@@ -8,7 +8,7 @@
- [B0, SH1A-C01-H]
- [A0, SH1A-C01-V]
- [A1, SH1A-C01-SQ]
- model: sr/magnet_models/SH1AC01.yaml
+ model: ${include:sr/magnet_models/SH1AC01.yaml}
- type: pyaml.magnet.cfm_magnet
name: SH1A-C02 #Name of the element in the lattice model
mapping:
@@ -19,4 +19,4 @@
- [B0, SH1A-C02-H]
- [A0, SH1A-C02-V]
- [A1, SH1A-C02-SQ]
- model: sr/magnet_models/SH1AC02.yaml
+ model: ${include:sr/magnet_models/SH1AC02.yaml}
diff --git a/tests/config/sr/correctors/SH1AC01-ident.yaml b/tests/config/sr/correctors/SH1AC01-ident.yaml
index f5f568953..0f634c2a9 100644
--- a/tests/config/sr/correctors/SH1AC01-ident.yaml
+++ b/tests/config/sr/correctors/SH1AC01-ident.yaml
@@ -8,4 +8,4 @@ mapping:
- [B0, SH1A-C01-H]
- [A0, SH1A-C01-V]
- [A1, SH1A-C01-SQ]
-model: sr/magnet_models/SH1AC01-ident.yaml
+model: ${include:sr/magnet_models/SH1AC01-ident.yaml}
diff --git a/tests/config/sr/correctors/SH1AC01-range.yaml b/tests/config/sr/correctors/SH1AC01-range.yaml
index ff9eeee85..0cffc86c2 100644
--- a/tests/config/sr/correctors/SH1AC01-range.yaml
+++ b/tests/config/sr/correctors/SH1AC01-range.yaml
@@ -8,4 +8,4 @@ mapping:
- [B0, SH1A-C01-H]
- [A0, SH1A-C01-V]
- [A1, SH1A-C01-SQ]
-model: sr/magnet_models/SH1AC01-range.yaml
+model: ${include:sr/magnet_models/SH1AC01-range.yaml}
diff --git a/tests/config/sr/correctors/SH1AC01.yaml b/tests/config/sr/correctors/SH1AC01.yaml
index 717ad973d..9facc0bec 100644
--- a/tests/config/sr/correctors/SH1AC01.yaml
+++ b/tests/config/sr/correctors/SH1AC01.yaml
@@ -8,4 +8,4 @@ mapping:
- [B0, SH1A-C01-H]
- [A0, SH1A-C01-V]
- [A1, SH1A-C01-SQ]
-model: sr/magnet_models/SH1AC01.yaml
+model: ${include:sr/magnet_models/SH1AC01.yaml}
diff --git a/tests/config/sr/correctors/SH1AC02.yaml b/tests/config/sr/correctors/SH1AC02.yaml
index 590d69b93..3818d5ade 100644
--- a/tests/config/sr/correctors/SH1AC02.yaml
+++ b/tests/config/sr/correctors/SH1AC02.yaml
@@ -8,4 +8,4 @@ mapping:
- [B0, SH1A-C02-H]
- [A0, SH1A-C02-V]
- [A1, SH1A-C02-SQ]
-model: sr/magnet_models/SH1AC02.yaml
+model: ${include:sr/magnet_models/SH1AC02.yaml}
diff --git a/tests/config/sr/magnet_models/QF1AC01.json b/tests/config/sr/magnet_models/QF1AC01.json
index b9b4e8abd..966a5a459 100644
--- a/tests/config/sr/magnet_models/QF1AC01.json
+++ b/tests/config/sr/magnet_models/QF1AC01.json
@@ -2,7 +2,7 @@
"type": "pyaml.magnet.linear_model",
"calibration_factor": 1.00504,
"calibration_offset": 0.0,
- "curve": "sr/magnet_models/quadcurve.json",
+ "curve": "${include:sr/magnet_models/quadcurve.json}",
"unit": "1/m",
"hardware_unit": "A",
"powerconverter": "sr/ps-qf1/c01-a/current"
diff --git a/tests/config/sr/magnet_models/QF1AC01.yaml b/tests/config/sr/magnet_models/QF1AC01.yaml
index c2f1ac30c..8d31dee13 100644
--- a/tests/config/sr/magnet_models/QF1AC01.yaml
+++ b/tests/config/sr/magnet_models/QF1AC01.yaml
@@ -1,7 +1,7 @@
type: pyaml.magnet.linear_model
calibration_factor: 1.00504
calibration_offset: 0.0
-curve: sr/magnet_models/quadcurve.yaml
+curve: ${include:sr/magnet_models/quadcurve.yaml}
unit: 1/m
hardware_unit: A
powerconverter: sr/ps-qf1/c01-a/current
diff --git a/tests/config/sr/quadrupoles/QD5D-C04_serialized.yaml b/tests/config/sr/quadrupoles/QD5D-C04_serialized.yaml
index 18f5a9123..48dcc7e2a 100644
--- a/tests/config/sr/quadrupoles/QD5D-C04_serialized.yaml
+++ b/tests/config/sr/quadrupoles/QD5D-C04_serialized.yaml
@@ -1,6 +1,6 @@
type: pyaml.magnet.quadrupole
name: QD5D-C04
-model: sr/magnet_models/QF1AC01.yaml
+model: ${include:sr/magnet_models/QF1AC01.yaml}
linked_elements:
- QF8B-C04
- QF8D-C04
diff --git a/tests/config/sr/quadrupoles/QF1AC01.json b/tests/config/sr/quadrupoles/QF1AC01.json
index 655d06994..164fdccda 100644
--- a/tests/config/sr/quadrupoles/QF1AC01.json
+++ b/tests/config/sr/quadrupoles/QF1AC01.json
@@ -1,5 +1,5 @@
{
"type": "pyaml.magnet.quadrupole",
"name": "QF1A-C01",
- "model": "sr/magnet_models/QF1AC01.json"
+ "model": "${include:sr/magnet_models/QF1AC01.json}"
}
diff --git a/tests/config/sr/quadrupoles/QF1AC01.yaml b/tests/config/sr/quadrupoles/QF1AC01.yaml
index 627702adc..507d3d9dc 100644
--- a/tests/config/sr/quadrupoles/QF1AC01.yaml
+++ b/tests/config/sr/quadrupoles/QF1AC01.yaml
@@ -1,3 +1,3 @@
type: pyaml.magnet.quadrupole
name: QF1A-C01
-model: sr/magnet_models/QF1AC01.yaml
+model: ${include:sr/magnet_models/QF1AC01.yaml}
diff --git a/tests/config/sr/quadrupoles/QF1C01A_2.yaml b/tests/config/sr/quadrupoles/QF1C01A_2.yaml
index 6ab7f120d..6c9c21e78 100644
--- a/tests/config/sr/quadrupoles/QF1C01A_2.yaml
+++ b/tests/config/sr/quadrupoles/QF1C01A_2.yaml
@@ -4,7 +4,7 @@ model:
type: pyaml.magnet.linear_model
calibration_factor: 1.006560
calibration_offset: 0.0034
- curve: sr/magnet_models/quadcurve.yaml
+ curve: ${include:sr/magnet_models/quadcurve.yaml}
unit: 1/m
hardware_unit: A
powerconverter: sr/ps-qf1/c01-a/current
diff --git a/tests/config/sr_serialized_magnets_cs.yaml b/tests/config/sr_serialized_magnets_cs.yaml
new file mode 100644
index 000000000..2db7546ff
--- /dev/null
+++ b/tests/config/sr_serialized_magnets_cs.yaml
@@ -0,0 +1,57 @@
+type: pyaml.accelerator
+facility: ESRF
+machine: sr
+energy: 6e9
+simulators:
+ - type: pyaml.lattice.simulator
+ lattice: sr/lattices/ebs.mat
+ name: design
+controls:
+ - type: tango.pyaml.controlsystem
+ tango_host: ebs-simu-3:10000
+ name: live
+ catalog:
+ type: tango.pyaml.tango_catalog
+data_folder: /data/store
+arrays:
+ - type: pyaml.arrays.magnet
+ name: ALL_SERIALIZED
+ elements:
+ - QF1A-C*
+ - QD2A-C*
+devices:
+ - type: pyaml.magnet.serialized_magnet
+ name: QF1A
+ function: B1
+ elements:
+ - QF1A-C05
+ - QF1A-C06
+ - QF1A-C07
+ - QF1A-C08
+ model:
+ type: pyaml.magnet.linear_serialized_model
+ calibration_factors: [1.0, 1.01, 0.99, 1.02]
+ calibration_offsets: 0.0
+ unit: m-1
+ hardware_unit: A
+ curves:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QF1_strength.csv
+ powerconverter: srmag/ps-qf1a/series/current
+ - type: pyaml.magnet.serialized_magnet
+ name: QD2A
+ function: B1
+ elements:
+ - QD2A-C05
+ - QD2A-C06
+ - QD2A-C07
+ model:
+ type: pyaml.magnet.linear_serialized_model
+ calibration_factors: 1.0
+ calibration_offsets: 0.0
+ unit: m-1
+ hardware_unit: A
+ curves:
+ type: pyaml.magnet.csvcurve
+ file: sr/magnet_models/QD2_strength.csv
+ powerconverter: srmag/ps-qd2a/series/current
diff --git a/tests/config/tl2/tl2.mat b/tests/config/tl2/tl2.mat
new file mode 100644
index 000000000..0d1a909d4
Binary files /dev/null and b/tests/config/tl2/tl2.mat differ
diff --git a/tests/config/tl2/tl2.yml b/tests/config/tl2/tl2.yml
new file mode 100644
index 000000000..8fef60f8a
--- /dev/null
+++ b/tests/config/tl2/tl2.yml
@@ -0,0 +1,215 @@
+type: pyaml.accelerator
+facility: ESRF
+machine: tl2
+energy: 6e9
+
+simulators:
+ - class: pyaml.lattice.simulator.Simulator
+ lattice: tl2.mat
+ name: design
+ twiss_in:
+ class: pyaml.lattice.twiss_in.TwissIn
+ alpha: [-1.71, 1.47]
+ beta: [5.9 , 5.65]
+ dispersion: [-0.145, -0.092, 0, 0]
+
+data_folder: /data/store
+
+arrays:
+
+ - type: pyaml.arrays.magnet
+ name: HCORR
+ elements:
+ - CH*
+ - type: pyaml.arrays.magnet
+ name: VCORR
+ elements:
+ - CV*
+ - type: pyaml.arrays.bpm
+ name: BPMS
+ elements:
+ - BPM*
+
+devices:
+
+ - class: pyaml.tuning_tools.orbit.Orbit
+ bpm_array_name: BPMS
+ hcorr_array_name: HCORR
+ vcorr_array_name: VCORR
+ name: DEFAULT_ORBIT_CORRECTION
+ singular_values: 5
+ response_matrix: ideal_tl2_orm.json
+
+ - class: pyaml.tuning_tools.orbit_response_matrix.OrbitResponseMatrix
+ bpm_array_name: BPMS
+ hcorr_array_name: HCORR
+ vcorr_array_name: VCORR
+ corrector_delta: 1e-6
+ name: DEFAULT_ORBIT_RESPONSE_MATRIX
+
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_CV1
+ x_pos: tl2/d-bpm/cv1/X_Position
+ y_pos: tl2/d-bpm/cv1/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_CH3
+ x_pos: tl2/d-bpm/d2/X_Position
+ y_pos: tl2/d-bpm/d2/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_QD5
+ x_pos: tl2/d-bpm/q5/X_Position
+ y_pos: tl2/d-bpm/q5/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_QF6
+ x_pos: tl2/d-bpm/q6/X_Position
+ y_pos: tl2/d-bpm/q6/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_SX
+ x_pos: tl2/d-bpm/sx/X_Position
+ y_pos: tl2/d-bpm/sx/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_QD8
+ x_pos: tl2/d-bpm/q8/X_Position
+ y_pos: tl2/d-bpm/q8/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_QD12
+ x_pos: tl2/d-bpm/q12/X_Position
+ y_pos: tl2/d-bpm/q12/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_QF14
+ x_pos: tl2/d-bpm/q14/X_Position
+ y_pos: tl2/d-bpm/q14/Z_Position
+ - class: pyaml.diagnostics.bpm.bpm.BPM
+ name: BPM_S1PM
+ x_pos: tl2/d-bpm/s1pm/X_Position
+ y_pos: tl2/d-bpm/s1pm/Z_Position
+
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH1
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch1/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH2
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch2/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH3
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch3/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH4
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch4/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH5
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch5/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH6
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch6/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH7
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch7/Current
+ - class: pyaml.magnet.hcorrector.HCorrector
+ name: CH8
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/ch8/Current
+
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV0
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv0/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV1
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv1/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV3
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv3/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV4
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv4/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV5
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv5/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV6
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv6/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV7
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv7/Current
+ - class: pyaml.magnet.vcorrector.VCorrector
+ name: CV8
+ model:
+ class: pyaml.magnet.linear_model.LinearMagnetModel
+ calibration_factor: 3.222e-3
+ unit: 1/m
+ hardware_unit: A
+ powerconverter: tl2/ps-c1/cv8/Current
diff --git a/tests/config/tune_monitor.yaml b/tests/config/tune_monitor.yaml
index f782a2c1c..791a62dee 100644
--- a/tests/config/tune_monitor.yaml
+++ b/tests/config/tune_monitor.yaml
@@ -11,7 +11,7 @@ controls:
- type: tango.pyaml.controlsystem
tango_host: ebs-simu-3:10000
name: live
- catalog: catalogs/ebs_catalogs.yaml
+ catalog: ${include:catalogs/ebs_catalogs.yaml}
data_folder: /data/store
devices:
- type: pyaml.diagnostics.tune_monitor
diff --git a/tests/configuration/test_configuration_manager.py b/tests/configuration/test_configuration_manager.py
index f36c37dd1..ae5699951 100644
--- a/tests/configuration/test_configuration_manager.py
+++ b/tests/configuration/test_configuration_manager.py
@@ -189,7 +189,7 @@ def test_configuration_manager_accumulates_multiple_device_fragments(
assert manager.has("devices", "BETATRON_TUNE")
assert manager.get("devices", "QF1A-C01")["class_path"] == "pyaml.magnet.quadrupole.Quadrupole"
assert manager.get("devices", "SH1A-C01")["class_path"] == "pyaml.magnet.cfm_magnet.CombinedFunctionMagnet"
- assert manager.get("devices", "BPM_C04-01")["class_path"] == "pyaml.bpm.bpm.BPM"
+ assert manager.get("devices", "BPM_C04-01")["class_path"] == "pyaml.diagnostics.bpm.bpm.BPM"
assert manager.get("devices", "BETATRON_TUNE")["class_path"] == "pyaml.diagnostics.tune_monitor.BetatronTuneMonitor"
@@ -222,7 +222,7 @@ def test_configuration_manager_adds_remote_source_with_relative_includes(http_co
energy: 3000000000.0
data_folder: remote-data
description: Loaded over HTTP
-simulators: fragments/simulators.json
+simulators: ${include:fragments/simulators.json}
devices: []
""",
"/configs/fragments/simulators.json": """
@@ -273,7 +273,7 @@ def test_configuration_manager_repr_is_yellow_pages_like(
assert "live (tango.pyaml.controlsystem.TangoControlSystem) source=config_manager_sr_base.yaml" in output
assert "design (pyaml.lattice.simulator.Simulator) source=config_manager_sr_base.yaml" in output
assert "HCORR (pyaml.arrays.magnet.Magnet) patterns=1 source=config_manager_sr_arrays.yaml" in output
- assert "BPM_C04-01 (pyaml.bpm.bpm.BPM) source=config_manager_sr_devices.yaml" in output
+ assert "BPM_C04-01 (pyaml.diagnostics.bpm.bpm.BPM) source=config_manager_sr_devices.yaml" in output
assert " ." in output
diff --git a/tests/configuration/test_fileloader.py b/tests/configuration/test_fileloader.py
index 53b234a66..6fae602a0 100644
--- a/tests/configuration/test_fileloader.py
+++ b/tests/configuration/test_fileloader.py
@@ -9,7 +9,6 @@
ROOT,
LoadContext,
RootFolder,
- _is_supported_file,
load,
)
@@ -54,16 +53,6 @@ def test_rootfolder_set_updates_root(tmp_path):
assert after == (new_root / "config.yaml").resolve()
-def test_is_supported_file():
- assert _is_supported_file("config.yaml")
- assert _is_supported_file("config.yml")
- assert _is_supported_file("config.json")
-
- assert not _is_supported_file("config.txt")
- assert not _is_supported_file(1)
- assert not _is_supported_file(None)
-
-
def test_load_context_adds_and_removes_paths(tmp_path):
ctx = LoadContext()
path = tmp_path / "config.yaml"
@@ -113,7 +102,7 @@ def test_load_nested_yaml(tmp_path):
(tmp_path / "child.yaml").write_text("answer: 42\n")
- (tmp_path / "parent.yaml").write_text("child: child.yaml\n")
+ (tmp_path / "parent.yaml").write_text("child: ${include:child.yaml}\n")
result = load("parent.yaml")
@@ -125,19 +114,19 @@ def test_load_nested_json(tmp_path):
(tmp_path / "child.json").write_text(json.dumps({"answer": 42}))
- (tmp_path / "parent.json").write_text(json.dumps({"child": "child.json"}))
+ (tmp_path / "parent.json").write_text(json.dumps({"child": "${include:child.json}"}))
result = load("parent.json")
assert result["child"]["answer"] == 42
-def test_load_file_resolver_loads_nested_file(tmp_path):
+def test_load_include_resolver_loads_nested_file(tmp_path):
ROOT.set(tmp_path)
(tmp_path / "subdir").mkdir()
(tmp_path / "subdir" / "child.yaml").write_text("answer: 42\n")
- (tmp_path / "parent.yaml").write_text('target: "${file:subdir/child.yaml}"\n')
+ (tmp_path / "parent.yaml").write_text('target: "${include:subdir/child.yaml}"\n')
result = load("parent.yaml")
@@ -199,11 +188,11 @@ def test_load_path_resolver_resolves_without_loading_file(tmp_path):
assert result["target"] == str((tmp_path / "subdir" / "missing.json").resolve())
-def test_load_interpolated_file_resolver_inside_string_raises(tmp_path):
+def test_load_interpolated_include_resolver_inside_string_raises(tmp_path):
ROOT.set(tmp_path)
(tmp_path / "child.yaml").write_text("answer: 42\n")
- (tmp_path / "config.yaml").write_text('value: "prefix-${file:child.yaml}-suffix"\n')
+ (tmp_path / "config.yaml").write_text('value: "prefix-${include:child.yaml}-suffix"\n')
with pytest.raises(PyAMLException, match="cannot be interpolated into a string"):
load("config.yaml")
@@ -227,7 +216,7 @@ def test_load_list_include_extends_list(tmp_path):
"""
values:
- start
- - items.yaml
+ - ${include:items.yaml}
- end
""".strip()
)
@@ -285,8 +274,8 @@ def test_load_invalid_json_raises_pyaml_exception(tmp_path):
def test_load_circular_include_raises_pyaml_exception(tmp_path):
ROOT.set(tmp_path)
- (tmp_path / "a.yaml").write_text("b: b.yaml\n")
- (tmp_path / "b.yaml").write_text("a: a.yaml\n")
+ (tmp_path / "a.yaml").write_text("b: ${include:b.yaml}\n")
+ (tmp_path / "b.yaml").write_text("a: ${include:a.yaml}\n")
with pytest.raises(PyAMLException, match="Circular file inclusion"):
load("a.yaml")
diff --git a/tests/bpm/test_bpm.py b/tests/diagnostics/bpm/test_bpm.py
similarity index 86%
rename from tests/bpm/test_bpm.py
rename to tests/diagnostics/bpm/test_bpm.py
index 93ac68ec5..3bf8ee712 100644
--- a/tests/bpm/test_bpm.py
+++ b/tests/diagnostics/bpm/test_bpm.py
@@ -9,7 +9,7 @@ def test_simulator_bpm_tilt():
sr.design.get_lattice().disable_6d()
sr.design.magnet.get("SH1A-C01-H").strength.set(10e-6) # Add orbit
sr.design.magnet.get("SH1A-C01-V").strength.set(10e-6) # Add orbit
- bpm = sr.design.bpm.get("BPM_C01-01")
+ bpm = sr.design.diagnostic.bpm.get("BPM_C01-01")
assert np.allclose(bpm.positions.get(), np.array([5.90809968e-05, 2.24832853e-05]))
assert bpm.tilt.get() == 0
alpha = np.pi / 3
@@ -30,7 +30,7 @@ def test_simulator_bpm_tilt():
def test_simulator_bpm_offset():
sr: Accelerator = Accelerator.load("tests/config/bpms.yaml", ignore_external=True)
sr.design.get_lattice().disable_6d()
- bpm = sr.design.bpm.get("BPM_C01-01")
+ bpm = sr.design.diagnostic.bpm.get("BPM_C01-01")
assert bpm.offset.get()[0] == 0
assert bpm.offset.get()[1] == 0
@@ -48,8 +48,8 @@ def test_simulator_bpm_offset():
def test_simulator_bpm_position(install_test_package):
sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
sr.design.get_lattice().disable_6d()
- bpm = sr.design.bpm.get("BPM_C01-01")
- bpm_simple = sr.live.bpm.get("BPM_C01-02")
+ bpm = sr.design.diagnostic.bpm.get("BPM_C01-01")
+ bpm_simple = sr.live.diagnostic.bpm.get("BPM_C01-02")
assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
assert np.allclose(bpm_simple.positions.get(), np.array([0.0, 0.0]))
@@ -58,9 +58,9 @@ def test_simulator_bpm_position(install_test_package):
def test_simulator_bpm_position_with_bad_corrector_strength():
sr: Accelerator = Accelerator.load("tests/config/bpms.yaml", ignore_external=True)
sr.design.get_lattice().disable_6d()
- bpm1 = sr.design.bpm.get("BPM_C01-01")
- bpm_simple = sr.design.bpm.get("BPM_C01-02")
- bpm3 = sr.design.bpm.get("BPM_C01-03")
+ bpm1 = sr.design.diagnostic.bpm.get("BPM_C01-01")
+ bpm_simple = sr.design.diagnostic.bpm.get("BPM_C01-02")
+ bpm3 = sr.design.diagnostic.bpm.get("BPM_C01-03")
sr.design.magnet.get("SH1A-C01-H").strength.set(-1e-6)
sr.design.magnet.get("SH1A-C01-V").strength.set(-1e-6)
diff --git a/tests/diagnostics/bpm/test_bpm_controlsystem.py b/tests/diagnostics/bpm/test_bpm_controlsystem.py
new file mode 100644
index 000000000..54eeb0686
--- /dev/null
+++ b/tests/diagnostics/bpm/test_bpm_controlsystem.py
@@ -0,0 +1,199 @@
+import numpy as np
+import pytest
+
+from pyaml.accelerator import Accelerator
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_tilt(install_test_package):
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+ bpm = sr.live.diagnostic.bpm.get("BPM_C01-01")
+ print(bpm.tilt.get())
+
+ assert bpm.tilt.get() == 0
+ bpm.tilt.set(0.01)
+ assert bpm.tilt.get() == 0.01
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_offset(install_test_package):
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+ bpm = sr.live.diagnostic.bpm.get("BPM_C01-01")
+
+ assert bpm.offset.get()[0] == 0
+ assert bpm.offset.get()[1] == 0
+ bpm.offset.set(np.array([0.1, 0.2]))
+ assert bpm.offset.get()[0] == 0.1
+ assert bpm.offset.get()[1] == 0.2
+ assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_position(install_test_package):
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+ bpm = sr.live.diagnostic.bpm.get("BPM_C01-01")
+ bpm_simple = sr.live.diagnostic.bpm.get("BPM_C01-02")
+
+ assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
+ assert np.allclose(bpm_simple.positions.get(), np.array([0.0, 0.0]))
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_get_devices_returns_attached_devices(install_test_package):
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+
+ devs = sr.live.get_devices_access(["srdiag/bpm/c01-01/SA_HPosition", "srdiag/bpm/c01-01/SA_VPosition"])
+
+ assert devs[0].name() == "//ebs-simu-3:10000/srdiag/bpm/c01-01/SA_HPosition"
+ assert devs[1].name() == "//ebs-simu-3:10000/srdiag/bpm/c01-01/SA_VPosition"
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_get_device_accepts_backend_config_model(install_test_package):
+ from tango.pyaml.attribute import ConfigModel as AttributeConfigModel
+
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+
+ dev = sr.live.get_device_access(AttributeConfigModel(attribute="srdiag/bpm/c01-05/SA_HPosition", unit="mm"))
+
+ assert dev.name() == "//ebs-simu-3:10000/srdiag/bpm/c01-05/SA_HPosition"
+ assert dev.unit() == "mm"
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_position_indexed(install_test_package):
+ from tango.pyaml.attribute_store import set_attribute
+
+ set_attribute("srdiag/bpm/c01-04/Position", [0.0, 1.0], unit="mm")
+
+ sr: Accelerator = Accelerator.load("tests/config/bpms.yaml")
+ bpm = sr.live.diagnostic.bpm.get("BPM_C01-04")
+
+ assert np.allclose(bpm.positions.get(), np.array([0.0, 1.0]))
+
+
+def _single_plane_bpm_config() -> dict:
+ """Two full BPMs and one vertical-only XBPM, grouped in one BPM array."""
+ entries = []
+ for key in ["c01-01/H", "c01-01/V", "c01-02/H", "c01-02/V", "xbpm/V"]:
+ entries.append(
+ {
+ "type": "tango.pyaml.static_catalog_entry",
+ "key": key,
+ "device": {"type": "tango.pyaml.attribute_read_only", "attribute": f"sr/bpm/{key}", "unit": "mm"},
+ }
+ )
+ return {
+ "type": "pyaml.accelerator",
+ "facility": "ESRF",
+ "machine": "sr",
+ "energy": 6e9,
+ "data_folder": "/data/store",
+ "controls": [
+ {
+ "type": "tango.pyaml.controlsystem",
+ "tango_host": "ebs-simu-3:10000",
+ "name": "live",
+ "catalog": {"type": "tango.pyaml.static_catalog", "entries": entries},
+ }
+ ],
+ "arrays": [{"type": "pyaml.arrays.bpm", "name": "BPM", "elements": ["BPM_1", "BPM_2", "XBPM"]}],
+ "devices": [
+ {"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_1", "x_pos": "c01-01/H", "y_pos": "c01-01/V"},
+ {"type": "pyaml.diagnostics.bpm.bpm", "name": "BPM_2", "x_pos": "c01-02/H", "y_pos": "c01-02/V"},
+ {"type": "pyaml.diagnostics.bpm.bpm", "name": "XBPM", "y_pos": "xbpm/V"},
+ ],
+ }
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_single_plane(install_test_package):
+ from tango.pyaml.attribute_store import set_attribute
+
+ set_attribute("sr/bpm/xbpm/V", 0.3, unit="mm")
+ sr = Accelerator.from_dict(_single_plane_bpm_config())
+ xbpm = sr.live.diagnostic.bpm.get("XBPM")
+
+ pos = xbpm.positions.get()
+ assert np.isnan(pos[0])
+ assert pos[1] == pytest.approx(0.3)
+ assert xbpm.positions.unit() == "mm"
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_array_with_single_plane_bpm(install_test_package):
+ from tango.pyaml.attribute_store import set_attribute
+
+ for name, value in [("c01-01/H", 0.1), ("c01-01/V", -0.1), ("c01-02/H", 0.2), ("c01-02/V", -0.2), ("xbpm/V", 0.3)]:
+ set_attribute(f"sr/bpm/{name}", value, unit="mm")
+ sr = Accelerator.from_dict(_single_plane_bpm_config())
+ bpms = sr.live.diagnostic.bpms.get("BPM")
+
+ pos = bpms.positions.get()
+ assert pos.shape == (3, 2)
+ assert np.isnan(pos[2, 0])
+ assert np.allclose(pos[:2], [[0.1, -0.1], [0.2, -0.2]])
+ assert pos[2, 1] == pytest.approx(0.3)
+
+ h = bpms.h.get()
+ assert np.allclose(h[:2], [0.1, 0.2])
+ assert np.isnan(h[2])
+ assert np.allclose(bpms.v.get(), [-0.1, -0.2, 0.3])
+
+ # The missing plane must not disable the grouped reads
+ agg, aggh, aggv = sr.live.create_bpm_aggregators(list(bpms))
+ assert [agg.nb_device(), aggh.nb_device(), aggv.nb_device()] == [6, 3, 3]
+ assert np.allclose(agg.get(), pos.flatten(), equal_nan=True)
+ assert np.allclose(aggh.get(), h, equal_nan=True)
+ assert np.allclose(aggv.get(), [-0.1, -0.2, 0.3])
+
+
+@pytest.mark.parametrize(
+ "install_test_package",
+ [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}],
+ indirect=True,
+)
+def test_controlsystem_bpm_array_without_horizontal_plane(install_test_package):
+ from tango.pyaml.attribute_store import set_attribute
+
+ set_attribute("sr/bpm/xbpm/V", 0.3, unit="mm")
+ config = _single_plane_bpm_config()
+ config["arrays"][0]["elements"] = ["XBPM"]
+ sr = Accelerator.from_dict(config)
+ bpms = sr.live.diagnostic.bpms.get("BPM")
+
+ assert np.isnan(bpms.h.get()).all()
+ assert np.allclose(bpms.v.get(), [0.3])
+ assert bpms.positions.get().shape == (1, 2)
diff --git a/tests/diagnostics/test_diagnostic_accessors.py b/tests/diagnostics/test_diagnostic_accessors.py
new file mode 100644
index 000000000..0046d975e
--- /dev/null
+++ b/tests/diagnostics/test_diagnostic_accessors.py
@@ -0,0 +1,172 @@
+import copy
+
+import pytest
+
+from pyaml.accelerator import Accelerator
+from pyaml.common.exception import PyAMLException
+from pyaml.lattice.simulator import Simulator
+
+
+def test_diagnostic_get_returns_named_monitor():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.diagnostic.get("BETATRON_TUNE") is design._DIAG["BETATRON_TUNE"]
+
+
+def test_diagnostic_get_with_no_name_returns_all_configured_diagnostics():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ all_diagnostics = design.diagnostic.get()
+ assert design.diagnostic.get("BETATRON_TUNE") in all_diagnostics
+
+
+def test_diagnostic_betatron_tune_returns_default_monitor():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.diagnostic.betatron_tune is design.diagnostic.get("BETATRON_TUNE")
+
+
+def test_diagnostic_raises_when_default_missing(ebs_lattice_file):
+ holder = Simulator(name="empty", lattice=str(ebs_lattice_file))
+
+ with pytest.raises(PyAMLException) as exc:
+ _ = holder.diagnostic.betatron_tune
+ assert "BETATRON_TUNE" in str(exc.value)
+
+
+def test_diagnostic_raises_when_default_wrong_type():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ # Swap the registered default so it points to an object of the wrong type.
+ design._DIAG["BETATRON_TUNE"] = design.tool.orbit
+
+ with pytest.raises(PyAMLException) as exc:
+ _ = design.diagnostic.betatron_tune
+ assert "BETATRON_TUNE" in str(exc.value)
+ assert "BetatronTuneMonitor" in str(exc.value)
+
+
+def test_diagnostic_bpm_returns_named_bpm():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.diagnostic.bpm.get("BPM_C04-04").get_name() == "BPM_C04-04"
+
+
+def test_diagnostic_bpms_returns_named_array():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ bpms = design.diagnostic.bpms.get("BPM")
+ assert design.diagnostic.bpm.get("BPM_C04-04") in bpms
+
+
+def test_diagnostic_getitem_exact_name_matches_get():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.diagnostic["BETATRON_TUNE"] is design.diagnostic.get("BETATRON_TUNE")
+
+
+def test_diagnostic_getitem_exact_name_miss_raises():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ with pytest.raises(PyAMLException):
+ design.diagnostic["UNKNOWN"]
+
+
+def test_diagnostic_getitem_wildcard_returns_an_array():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ matching = design.diagnostic["BETATRON*"]
+ assert matching.names() == ["BETATRON_TUNE"]
+ assert design.diagnostic["MISSING*"].names() == []
+
+
+def test_diagnostic_getitem_list_selection_ignores_request_order():
+ """A list-of-patterns selection lands in configuration order, whatever order the names
+ were requested in, same as every other holder (see
+ test_every_accessor_returns_a_list_selection_in_configuration_order). Only one diagnostic
+ is registered by any existing fixture, so a distinct second entry is poked directly into
+ the store (a renamed copy of the existing monitor) to make request order and
+ configuration order observably different."""
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+ spare_monitor = copy.copy(design.diagnostic.get("BETATRON_TUNE"))
+ spare_monitor._name = "SPARE_BETATRON_TUNE"
+ design._DIAG["SPARE_BETATRON_TUNE"] = spare_monitor
+
+ forward = design.diagnostic[["BETATRON_TUNE", "SPARE_BETATRON_TUNE"]]
+ backward = design.diagnostic[["SPARE_BETATRON_TUNE", "BETATRON_TUNE"]]
+ assert forward.names() == backward.names() == ["BETATRON_TUNE", "SPARE_BETATRON_TUNE"]
+
+
+def test_diagnostic_bpm_getitem_exact_name_matches_get():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.diagnostic.bpm["BPM_C04-04"] is design.diagnostic.bpm.get("BPM_C04-04")
+
+
+def test_diagnostic_bpm_getitem_exact_name_miss_raises():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ with pytest.raises(PyAMLException):
+ design.diagnostic.bpm["UNKNOWN"]
+
+
+def test_diagnostic_bpm_getitem_wildcard_and_list_return_an_array():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ wildcard = design.diagnostic.bpm["BPM_C04-0[14]"]
+ assert sorted(wildcard.names()) == ["BPM_C04-01", "BPM_C04-04"]
+
+ listed = design.diagnostic.bpm[["BPM_C04-01", "BPM_C04-04"]]
+ assert listed.names() == ["BPM_C04-01", "BPM_C04-04"]
diff --git a/tests/integration/test_dt4acc_twin_smoke.py b/tests/integration/test_dt4acc_twin_smoke.py
index 549bdb4e7..d9edec864 100644
--- a/tests/integration/test_dt4acc_twin_smoke.py
+++ b/tests/integration/test_dt4acc_twin_smoke.py
@@ -3,7 +3,6 @@
import numpy as np
import pytest
-import yaml
from pyaml_test_lattice import configurations, lattices
from pyaml.accelerator import Accelerator
@@ -37,22 +36,17 @@ def _readback_value(device_access):
def _load_fragment(config_key: str) -> dict:
"""Load one pyaml-test-lattice merged config fragment as a plain dict.
- Bypasses pyaml's own YAML loader (which auto-loads any bare
- ``*.yaml``/``*.json`` string value as a nested file relative to the
- parent file's directory) since the lattice file ships under a different
+ The ``lattice`` reference is overridden since it lives in a different
package subtree (``data/lattice``) than the config fragment
- (``data/configuration``). The ``lattice`` and ``catalog`` references are
- resolved explicitly instead.
+ (``data/configuration``).
"""
config_path = Path(configurations[config_key])
- fragment = yaml.safe_load(config_path.read_text())
+ manager = ConfigurationManager()
+ manager.add(config_path)
+ fragment = manager.to_dict()
fragment["simulators"][0]["lattice"] = str(Path(lattices[FODO_LATTICE_KEY]))
- catalog_name = fragment["controls"][0]["catalog"]
- catalog_path = config_path.parent / catalog_name
- fragment["controls"][0]["catalog"] = yaml.safe_load(catalog_path.read_text())
-
return fragment
@@ -134,9 +128,9 @@ def deactivated_test_orbit_correction(config_key: str):
try:
accelerator = _build_accelerator(config_key)
control_mode = accelerator.live
- bpms = control_mode.bpms.get("bpms")
- orbit_response_matrix = control_mode.get_orm_tuning("DEFAULT_ORBIT_RESPONSE_MATRIX")
- orbit_correction = control_mode.get_orbit_tuning("DEFAULT_ORBIT_CORRECTION")
+ bpms = control_mode.diagnostic.bpms.get("bpms")
+ orbit_response_matrix = control_mode.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX")
+ orbit_correction = control_mode.tool.get("DEFAULT_ORBIT_CORRECTION")
orbit_response_matrix.measure()
ormdata = orbit_response_matrix.get()
orbit_response_matrix.save("orm.json")
@@ -179,7 +173,7 @@ def deactivated_test_chromaticity_measurement(config_key: str):
accelerator = _build_accelerator(config_key)
control_mode = accelerator.live
- chromaticity_measurement = control_mode.get_chromaticity_monitor("DEFAULT_CHROMATICITY_MEASUREMENT")
+ chromaticity_measurement = control_mode.tool.get("DEFAULT_CHROMATICITY_MEASUREMENT")
def chroma_callback(action: int, cb_data: dict):
if action == Action.MEASURE:
diff --git a/tests/lattice/test_linkers.py b/tests/lattice/test_linkers.py
index 75585da74..957c2cae8 100644
--- a/tests/lattice/test_linkers.py
+++ b/tests/lattice/test_linkers.py
@@ -1,3 +1,4 @@
+import at
import pytest
from pyaml import PyAMLException
@@ -6,6 +7,7 @@
PyAtAttributeElementsLinker,
PyAtAttributeIdentifier,
)
+from pyaml.lattice.simulator import Simulator
# -----------------------
# Dummy PyAML Element
@@ -13,14 +15,18 @@
class DummyPyAMLElement:
- """Minimal stand-in for a PyAML Element: only provides .name."""
+ """Minimal stand-in for a PyAML Element: only provides .name and .lattice_names."""
- def __init__(self, name: str):
+ def __init__(self, name: str, lattice_names: str | None = None):
self._name = name
+ self._lattice_names = lattice_names
def get_name(self) -> str:
return self._name
+ def get_lattice_names(self) -> str | None:
+ return self._lattice_names
+
def test_conf_with_linker():
sr: Accelerator = Accelerator.load("tests/config/sr-attribute-linker.yaml")
@@ -94,90 +100,27 @@ def check_index(ring, elts, indices):
assert ring.index(e) == indices[idx]
-def test_various_naming_addressing():
- sr = Accelerator.load("tests/config/EBSNames.yaml", ignore_external=True)
+# Ring indices of the QF1E / QF1I quadrupoles of sr/lattices/ebs-original-names.mat
+QF1E_INDICES = [
+ 140, 290, 424, 576, 712, 848, 982, 1116, 1250, 1384, 1525, 1662, 1803, 1937, 2078, 2212,
+ 2348, 2482, 2616, 2762, 2898, 3046, 3182, 3316, 3452, 3593, 3732, 3873, 4009, 4150, 4286,
+] # fmt: skip
+QF1E_ALL_INDICES = QF1E_INDICES + [4430]
+
+
+@pytest.mark.parametrize("config", ["tests/config/EBSNames.yaml", "tests/config/EBSNames-linker.yaml"])
+def test_various_naming_addressing(config):
+ """lattice_names selectors give the same elements with and without a linker."""
+ sr = Accelerator.load(config, ignore_external=True)
ring = sr.design.get_lattice()
elts = sr.design.magnet.get("QF1E").strength._elements
assert len(elts) == 31
- check_index(
- ring,
- elts,
- [
- 140,
- 290,
- 424,
- 576,
- 712,
- 848,
- 982,
- 1116,
- 1250,
- 1384,
- 1525,
- 1662,
- 1803,
- 1937,
- 2078,
- 2212,
- 2348,
- 2482,
- 2616,
- 2762,
- 2898,
- 3046,
- 3182,
- 3316,
- 3452,
- 3593,
- 3732,
- 3873,
- 4009,
- 4150,
- 4286,
- ],
- )
+ check_index(ring, elts, QF1E_INDICES)
elts = sr.design.magnet.get("QF1E-ALL").strength._elements
assert len(elts) == 32
- check_index(
- ring,
- elts,
- [
- 140,
- 290,
- 424,
- 576,
- 712,
- 848,
- 982,
- 1116,
- 1250,
- 1384,
- 1525,
- 1662,
- 1803,
- 1937,
- 2078,
- 2212,
- 2348,
- 2482,
- 2616,
- 2762,
- 2898,
- 3046,
- 3182,
- 3316,
- 3452,
- 3593,
- 3732,
- 3873,
- 4009,
- 4150,
- 4286,
- 4430,
- ],
- )
+ check_index(ring, elts, QF1E_ALL_INDICES)
elts = sr.design.magnet.get("QF1E-C05").strength._elements
assert len(elts) == 1
@@ -194,3 +137,60 @@ def test_various_naming_addressing():
elts = sr.design.magnet.get("QF1E-C04-C05-C06-3").strength._elements
assert len(elts) == 3
check_index(ring, elts, [140, 290, 424])
+
+
+# -----------------------
+# lattice_names selectors with a linker
+# -----------------------
+
+
+@pytest.fixture
+def simulator_with_tag_linker(lattice_with_custom_attr, tmp_path) -> Simulator:
+ """Simulator on the 'Tag' lattice: D1(Tag=D1) QF(Tag=QF) QF2(Tag=QF) QD(Tag=QD)."""
+ lattice_file = tmp_path / "tag_lattice.m"
+ at.save_m(lattice_with_custom_attr, str(lattice_file))
+ return Simulator(name="design", lattice=str(lattice_file), linker=PyAtAttributeElementsLinker(attribute_name="Tag"))
+
+
+def _tags(elements):
+ return [getattr(e, "Tag", None) for e in elements]
+
+
+def test_linker_without_lattice_names_uses_element_name(simulator_with_tag_linker):
+ elts = simulator_with_tag_linker.get_at_elems(DummyPyAMLElement("QF"))
+ assert _tags(elts) == ["QF", "QF"]
+
+
+def test_linker_lattice_names_list(simulator_with_tag_linker):
+ sim = simulator_with_tag_linker
+ assert _tags(sim.get_at_elems(DummyPyAMLElement("anything", "list(QF)"))) == ["QF", "QF"]
+ assert _tags(sim.get_at_elems(DummyPyAMLElement("anything", "list(QF,QD)"))) == ["QF", "QF", "QD"]
+
+
+def test_linker_lattice_names_indices(simulator_with_tag_linker):
+ sim = simulator_with_tag_linker
+ ring = sim.ring
+ assert sim.get_at_elems(DummyPyAMLElement("x", "QF@1")) == [ring[2]]
+ assert sim.get_at_elems(DummyPyAMLElement("x", "QF@0,1")) == [ring[1], ring[2]]
+ assert sim.get_at_elems(DummyPyAMLElement("x", "QF#0..2")) == [ring[1], ring[2]]
+ # Empty name: direct indexing in the whole ring
+ assert sim.get_at_elems(DummyPyAMLElement("x", "@3")) == [ring[3]]
+ assert sim.get_at_elems(DummyPyAMLElement("x", "#1..3")) == [ring[1], ring[2]]
+
+
+def test_linker_lattice_names_share_lattice_element(simulator_with_tag_linker):
+ """Two PyAML elements with different names can drive the same PyAT element."""
+ sim = simulator_with_tag_linker
+ main = sim.get_at_elems(DummyPyAMLElement("QD"))
+ coil = sim.get_at_elems(DummyPyAMLElement("QD_H", "list(QD)"))
+ assert main == coil == [sim.ring[3]]
+
+
+def test_linker_lattice_names_errors(simulator_with_tag_linker):
+ sim = simulator_with_tag_linker
+ with pytest.raises(PyAMLException):
+ sim.get_at_elems(DummyPyAMLElement("x", "list(ZZ)"))
+ with pytest.raises(PyAMLException):
+ sim.get_at_elems(DummyPyAMLElement("x", "ZZ@0"))
+ with pytest.raises(PyAMLException):
+ sim.get_at_elems(DummyPyAMLElement("x", "QF@5"))
diff --git a/tests/lattice/test_magnet_accessors.py b/tests/lattice/test_magnet_accessors.py
new file mode 100644
index 000000000..e585b37ef
--- /dev/null
+++ b/tests/lattice/test_magnet_accessors.py
@@ -0,0 +1,100 @@
+import at
+import numpy as np
+import pytest
+
+from pyaml import PyAMLException
+from pyaml.lattice.abstract_impl import (
+ RWHardwareArray,
+ RWHardwareScalar,
+ RWSerializedStrength,
+ RWStrengthArray,
+ RWStrengthScalar,
+)
+from pyaml.magnet.hcorrector import HCorrector
+from pyaml.magnet.identity_cfm_model import IdentityCFMagnetModel
+from pyaml.magnet.identity_model import IdentityMagnetModel
+from pyaml.magnet.vcorrector import VCorrector
+
+
+def _thin_corrector(name="COR"):
+ return at.Corrector(name, 0.0, [0.0, 0.0], PolynomA=[0.0], PolynomB=[0.0])
+
+
+@pytest.mark.parametrize("accessor_type", [RWStrengthScalar, RWHardwareScalar])
+def test_zero_length_scalar_magnet_stores_integrated_strength(accessor_type):
+ element = _thin_corrector()
+ model = IdentityMagnetModel(physics="COR", unit="rad")
+ accessor = accessor_type([element], HCorrector.polynom, model)
+
+ accessor.set(1.0e-6)
+
+ # AT convention: a thin element stores the integrated strength in its polynom
+ assert element.PolynomB[0] == pytest.approx(-1.0e-6)
+ assert accessor.get() == pytest.approx(1.0e-6)
+
+
+@pytest.mark.parametrize("accessor_type", [RWStrengthScalar, RWHardwareScalar])
+def test_zero_length_split_magnet_shares_integrated_strength_equally(accessor_type):
+ elements = [_thin_corrector("COR_A"), _thin_corrector("COR_B")]
+ model = IdentityMagnetModel(physics="COR", unit="rad")
+ accessor = accessor_type(elements, HCorrector.polynom, model)
+
+ accessor.set(1.0e-6)
+
+ assert elements[0].PolynomB[0] == pytest.approx(-0.5e-6)
+ assert elements[1].PolynomB[0] == pytest.approx(-0.5e-6)
+ assert accessor.get() == pytest.approx(1.0e-6)
+
+
+@pytest.mark.parametrize("accessor_type", [RWStrengthScalar, RWHardwareScalar])
+def test_thick_scalar_magnet_is_unchanged(accessor_type):
+ element = at.Corrector("COR", 0.2, [0.0, 0.0], PolynomA=[0.0], PolynomB=[0.0])
+ model = IdentityMagnetModel(physics="COR", unit="rad")
+ accessor = accessor_type([element], HCorrector.polynom, model)
+
+ accessor.set(1.0e-6)
+
+ assert element.PolynomB[0] == pytest.approx(-5.0e-6)
+ assert accessor.get() == pytest.approx(1.0e-6)
+
+
+@pytest.mark.parametrize("accessor_type", [RWStrengthArray, RWHardwareArray])
+def test_zero_length_combined_function_magnet_stores_integrated_strengths(accessor_type):
+ element = _thin_corrector()
+ model = IdentityCFMagnetModel(
+ multipoles=["B0", "A0"],
+ physics=["HCOR", "VCOR"],
+ units=["rad", "rad"],
+ )
+ accessor = accessor_type([element], [HCorrector.polynom, VCorrector.polynom], model)
+
+ accessor.set(np.array([1.0e-6, -2.0e-6]))
+
+ assert element.PolynomB[0] == pytest.approx(-1.0e-6)
+ assert element.PolynomA[0] == pytest.approx(-2.0e-6)
+ np.testing.assert_allclose(accessor.get(), [1.0e-6, -2.0e-6])
+
+
+def test_zero_length_serialized_magnets_share_strength_equally():
+ elements = [_thin_corrector("COR_A"), _thin_corrector("COR_B")]
+ model = IdentityMagnetModel(physics="COR", unit="rad")
+ strengths = [RWStrengthScalar([e], HCorrector.polynom, model) for e in elements]
+ currents = [RWHardwareScalar([e], HCorrector.polynom, model) for e in elements]
+ serialized = [RWSerializedStrength(strengths, currents, i) for i in range(len(elements))]
+
+ serialized[0].set(1.0e-6)
+
+ assert serialized[0].get() == pytest.approx(0.5e-6)
+ assert serialized[1].get() == pytest.approx(0.5e-6)
+ assert elements[0].PolynomB[0] == pytest.approx(-0.5e-6)
+ assert elements[1].PolynomB[0] == pytest.approx(-0.5e-6)
+
+
+def test_serialized_magnets_mixing_thin_and_thick_is_rejected():
+ elements = [_thin_corrector("COR_A"), at.Corrector("COR_B", 0.2, [0.0, 0.0], PolynomA=[0.0], PolynomB=[0.0])]
+ model = IdentityMagnetModel(physics="COR", unit="rad")
+ strengths = [RWStrengthScalar([e], HCorrector.polynom, model) for e in elements]
+ currents = [RWHardwareScalar([e], HCorrector.polynom, model) for e in elements]
+
+ with pytest.raises(PyAMLException, match="all thin .* or all thick"):
+ RWSerializedStrength(strengths, currents, 0)
diff --git a/tests/magnet/test_serialized_magnets.py b/tests/magnet/test_serialized_magnets.py
index 1e95ca706..b362f7b77 100644
--- a/tests/magnet/test_serialized_magnets.py
+++ b/tests/magnet/test_serialized_magnets.py
@@ -27,11 +27,11 @@ def test_config_load(sr_file):
sr: Accelerator = Accelerator.load(sr_file, include_locations=False, ignore_external=True)
assert sr is not None
magnets = [
- sr.design.get_element("QF8B-C04"),
- sr.design.get_element("QF8B-C04"),
- sr.design.get_element("QD5D-C04"),
- sr.design.get_element("QF6D-C04"),
- sr.design.get_element("QF4D-C04"),
+ sr.design["QF8B-C04"],
+ sr.design["QF8B-C04"],
+ sr.design["QD5D-C04"],
+ sr.design["QF6D-C04"],
+ sr.design["QF4D-C04"],
]
assert None not in [magnets]
@@ -115,7 +115,7 @@ def test_tune(sr_file):
assert len(m.get_magnets()) == m.get_nb_magnets()
quadForTuneDesign = sr.design.serialized_magnets.get("QForTune")
- tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE")
# Build tune response matrix
tunemat = np.zeros((len(quadForTuneDesign), 2))
diff --git a/tests/magnet/test_serialized_magnets_cs.py b/tests/magnet/test_serialized_magnets_cs.py
new file mode 100644
index 000000000..cd4f29982
--- /dev/null
+++ b/tests/magnet/test_serialized_magnets_cs.py
@@ -0,0 +1,67 @@
+import numpy as np
+import pytest
+
+from pyaml.accelerator import Accelerator
+from pyaml.magnet.serialized_magnet import SerializedMagnets
+
+CONFIG = "tests/config/sr_serialized_magnets_cs.yaml"
+TANGO_DUMMY = [{"name": "tango-pyaml", "path": "tests/dummy_cs/tango-pyaml"}]
+
+
+def _sub_strengths(family: SerializedMagnets, current: float) -> np.ndarray:
+ return np.array([family.model.get_sub_model(i).compute_strengths([current])[0] for i in range(family.get_nb_magnets())])
+
+
+@pytest.mark.parametrize("install_test_package", TANGO_DUMMY, indirect=True)
+def test_serialized_magnets_attach_to_control_system(install_test_package):
+ sr: Accelerator = Accelerator.load(CONFIG)
+ family: SerializedMagnets = sr.live.serialized_magnet.get("QF1A")
+ magnets = family.get_magnets()
+
+ assert family.get_nb_magnets() == 4
+ assert [m.get_name() for m in magnets] == ["QF1A-C05", "QF1A-C06", "QF1A-C07", "QF1A-C08"]
+ for m in magnets:
+ assert sr.live.magnet.get(m.get_name()) is m
+
+
+@pytest.mark.parametrize("install_test_package", TANGO_DUMMY, indirect=True)
+def test_serialized_magnets_share_power_supply(install_test_package):
+ sr: Accelerator = Accelerator.load(CONFIG)
+ family: SerializedMagnets = sr.live.serialized_magnet.get("QF1A")
+ magnets = family.get_magnets()
+
+ magnets[2].hardware.set(80.0)
+ assert np.allclose([m.hardware.get() for m in magnets], 80.0)
+ assert np.allclose([m.strength.get() for m in magnets], _sub_strengths(family, 80.0))
+
+ # Setting the strength of one magnet drives the shared power supply with that magnet's own sub-model
+ magnets[1].strength.set(0.5)
+ current = family.model.get_sub_model(1).compute_hardware_values([0.5])[0]
+ assert np.allclose([m.hardware.get() for m in magnets], current)
+ assert magnets[1].strength.get() == pytest.approx(0.5)
+
+ # The other family is on its own power supply
+ assert np.allclose([m.hardware.get() for m in sr.live.serialized_magnet.get("QD2A").get_magnets()], 0.0)
+
+
+@pytest.mark.parametrize("install_test_package", TANGO_DUMMY, indirect=True)
+def test_serialized_magnets_aggregator(install_test_package):
+ sr: Accelerator = Accelerator.load(CONFIG)
+ qf1a: SerializedMagnets = sr.live.serialized_magnet.get("QF1A")
+ qd2a: SerializedMagnets = sr.live.serialized_magnet.get("QD2A")
+ qf1a.get_magnets()[0].hardware.set(30.0)
+ qd2a.get_magnets()[0].hardware.set(20.0)
+
+ array = sr.live.magnets.get("ALL_SERIALIZED")
+ expected = np.concatenate([_sub_strengths(qf1a, 30.0), _sub_strengths(qd2a, 20.0)])
+ assert np.allclose(array.strengths.get(), expected)
+ assert np.allclose(array.hardwares.get(), [30.0] * 4 + [20.0] * 3)
+
+ # Doubling every magnet of a series moves its power supply to the current of the doubled strength (no 1/N dilution)
+ array.strengths.set(2 * array.strengths.get())
+ assert np.allclose(array.strengths.get(), 2 * expected)
+ qf1a_current = qf1a.model.get_sub_model(0).compute_hardware_values([2 * expected[0]])[0]
+ assert np.allclose(array.hardwares.get()[:4], qf1a_current)
+
+ array.hardwares.set(array.hardwares.get())
+ assert np.allclose(array.strengths.get(), 2 * expected)
diff --git a/tests/rf/test_rf_holder.py b/tests/rf/test_rf_holder.py
new file mode 100644
index 000000000..b1839ea8c
--- /dev/null
+++ b/tests/rf/test_rf_holder.py
@@ -0,0 +1,75 @@
+import copy
+
+import pytest
+
+from pyaml.accelerator import Accelerator
+from pyaml.common.exception import PyAMLException
+
+
+@pytest.fixture
+def design():
+ return Accelerator.load("tests/config/EBS_rf_multi.yaml", ignore_external=True).design
+
+
+def test_rf_holder_getitem_exact_name_matches_get(design):
+ assert design.rf["DEFAULT_RF_PLANT"] is design.rf.get("DEFAULT_RF_PLANT")
+
+
+def test_rf_holder_getitem_exact_name_miss_raises(design):
+ with pytest.raises(PyAMLException):
+ design.rf["UNKNOWN"]
+
+
+def test_rf_holder_getitem_wildcard_returns_an_array(design):
+ matching = design.rf["DEFAULT_*"]
+ assert matching.names() == ["DEFAULT_RF_PLANT"]
+ assert design.rf["MISSING*"].names() == []
+
+
+def test_rf_transmitter_holder_getitem_exact_name_matches_get(design):
+ assert design.rf.transmitter["RFTRA1"] is design.rf.transmitter.get("RFTRA1")
+
+
+def test_rf_transmitter_holder_getitem_exact_name_miss_raises(design):
+ with pytest.raises(PyAMLException):
+ design.rf.transmitter["UNKNOWN"]
+
+
+def test_rf_transmitter_holder_getitem_wildcard_returns_an_array(design):
+ matching = design.rf.transmitter["RFTRA*"]
+ assert sorted(matching.names()) == ["RFTRA1", "RFTRA2", "RFTRA_HARMONIC"]
+
+
+def test_rf_transmitter_holder_getitem_list_of_patterns(design):
+ selected = design.rf.transmitter[["RFTRA1", "RFTRA2"]]
+ assert selected.names() == ["RFTRA1", "RFTRA2"]
+
+
+def test_rf_transmitter_holder_getitem_list_selection_ignores_request_order(design):
+ """A list-of-patterns selection lands in configuration order, whatever order the names
+ were requested in, same as every other holder (see
+ test_every_accessor_returns_a_list_selection_in_configuration_order)."""
+ forward = design.rf.transmitter[["RFTRA1", "RFTRA2"]]
+ backward = design.rf.transmitter[["RFTRA2", "RFTRA1"]]
+ assert forward.names() == backward.names() == ["RFTRA1", "RFTRA2"]
+
+
+def test_rf_holder_getitem_list_selection_ignores_request_order(design):
+ """Same configuration-order guarantee as the RF transmitter holder, at the RF plant level.
+
+ Only one RF plant is registered by this fixture, so a distinct second entry is poked
+ directly into the store (a renamed copy of the existing plant) to make request order and
+ configuration order observably different.
+ """
+ spare_plant = copy.copy(design.rf.get("DEFAULT_RF_PLANT"))
+ spare_plant._name = "SPARE_RF_PLANT"
+ design._RFPLANT["SPARE_RF_PLANT"] = spare_plant
+
+ forward = design.rf[["DEFAULT_RF_PLANT", "SPARE_RF_PLANT"]]
+ backward = design.rf[["SPARE_RF_PLANT", "DEFAULT_RF_PLANT"]]
+ assert forward.names() == backward.names() == ["DEFAULT_RF_PLANT", "SPARE_RF_PLANT"]
+
+
+def test_rf_transmitter_holder_getitem_regex(design):
+ matching = design.rf.transmitter["re:^RFTRA[12]$"]
+ assert sorted(matching.names()) == ["RFTRA1", "RFTRA2"]
diff --git a/tests/test_accelerator_load.py b/tests/test_accelerator_load.py
index f30a68e39..57e659f08 100644
--- a/tests/test_accelerator_load.py
+++ b/tests/test_accelerator_load.py
@@ -9,18 +9,18 @@
def test_peer():
sr = Accelerator.load("tests/config/tune_monitor.yaml")
- tm = sr.design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tm = sr.design.diagnostic.get("BETATRON_TUNE")
assert isinstance(tm.peer.peer, Accelerator)
assert isinstance(tm.peer, ElementHolder)
- tm = sr.live.get_betatron_tune_monitor("BETATRON_TUNE")
+ tm = sr.live.diagnostic.get("BETATRON_TUNE")
assert isinstance(tm.peer.peer, Accelerator)
assert isinstance(tm.peer, ElementHolder)
def test_repr_is_informative_and_bounded():
sr = Accelerator.load("tests/config/EBSOrbit.yaml")
- bpm = sr.design.bpm.get("BPM_C04-04")
- bpms = sr.design.bpms.get("BPM")
+ bpm = sr.design.diagnostic.bpm.get("BPM_C04-04")
+ bpms = sr.design.diagnostic.bpms.get("BPM")
assert repr(bpm) == (
"BPM(name='BPM_C04-04', lattice_names='BPM_C04-04', "
@@ -46,7 +46,7 @@ def test_repr_options_limit_sequences():
set_repr_options(max_items=1)
sr = Accelerator.load("tests/config/EBSOrbit.yaml")
- bpms = sr.design.bpms.get("BPM")
+ bpms = sr.design.diagnostic.bpms.get("BPM")
assert f"... +{len(bpms) - 1} more ..." in repr(bpms)
finally:
set_repr_options(
@@ -73,7 +73,7 @@ def test_accelerator_load_supports_remote_sources(http_config_server, ebs_lattic
energy: 3000000000.0
data_folder: remote-data
description: Remote accelerator
-simulators: fragments/simulators.json
+simulators: ${include:fragments/simulators.json}
devices: []
""",
"/config/fragments/simulators.json": f"""
@@ -160,5 +160,5 @@ def test_config_dict():
assert sr.live.dconfig()["prefix"] == "VA:"
assert sr.live.dconfig()["info"]["param1"] == "Param1 value"
assert sr.live.dconfig()["info"]["param2"] == 12345.0
- assert isinstance(sr.live.get_element("MY_ELEMENT"), MyElement)
- assert sr.live.get_element("MY_ELEMENT")._cfg.device_h == "TUNEZR:rdH"
+ assert isinstance(sr.live["MY_ELEMENT"], MyElement)
+ assert sr.live["MY_ELEMENT"]._cfg.device_h == "TUNEZR:rdH"
diff --git a/tests/test_catalogs.py b/tests/test_catalogs.py
index 828627aa5..bbe42f462 100644
--- a/tests/test_catalogs.py
+++ b/tests/test_catalogs.py
@@ -50,7 +50,7 @@ def test_inline_catalog_is_supported(install_test_package):
],
"devices": [
{
- "type": "pyaml.bpm.bpm",
+ "type": "pyaml.diagnostics.bpm.bpm",
"name": "BPM_C02-01",
"x_pos": "BPM_C02-01/x",
"y_pos": "BPM_C02-01/y",
@@ -59,7 +59,7 @@ def test_inline_catalog_is_supported(install_test_package):
}
)
- bpm = sr.live.bpm.get("BPM_C02-01")
+ bpm = sr.live.diagnostic.bpm.get("BPM_C02-01")
assert np.allclose(bpm.positions.get(), np.array([0.0, 0.0]))
@@ -103,7 +103,7 @@ def test_unresolved_catalog_key_raises_runtime_error(install_test_package):
],
"devices": [
{
- "type": "pyaml.bpm.bpm",
+ "type": "pyaml.diagnostics.bpm.bpm",
"name": "BPM_C03-01",
"x_pos": "BPM_C03-01/x",
"y_pos": "BPM_C03-01/y",
@@ -175,7 +175,7 @@ def test_indexed_catalog_entry_extracts_scalar_from_vector_attribute(install_tes
],
"devices": [
{
- "type": "pyaml.bpm.bpm",
+ "type": "pyaml.diagnostics.bpm.bpm",
"name": "BPM_TEST",
"x_pos": "bpm/SA_HPosition",
"y_pos": "bpm/SA_VPosition",
@@ -184,7 +184,7 @@ def test_indexed_catalog_entry_extracts_scalar_from_vector_attribute(install_tes
}
)
- bpm = sr.live.bpm.get("BPM_TEST")
+ bpm = sr.live.diagnostic.bpm.get("BPM_TEST")
positions = bpm.positions.get()
assert np.isclose(positions[0], 1.5)
assert np.isclose(positions[1], -0.3)
diff --git a/tests/test_load_conf_with_code.py b/tests/test_load_conf_with_code.py
index de4761023..41771dbfa 100644
--- a/tests/test_load_conf_with_code.py
+++ b/tests/test_load_conf_with_code.py
@@ -8,11 +8,13 @@ def test_load_conf_with_code():
config_path = parent_folder.joinpath("config", "EBSOrbit.yaml").resolve()
sr: Accelerator = Accelerator.load(config_path)
- bpms = sr.live.bpms.get("BPM")
+ bpms = sr.live.diagnostic.bpms.get("BPM")
assert bpms is not None
assert len(bpms) == 320
assert sr.live[bpms[0].get_name()] is bpms[0]
assert sr.live["BPM*"].names() == bpms.names()
- assert sr.live[:].names() == [element.get_name() for element in sr.live.get_all_elements()]
- assert sr.design["BPM*"].names() == sr.design.bpms.get("BPM").names()
+ assert sr.live[:].names() == [element.get_name() for element in sr.live.get()]
+ assert sr.design["BPM*"].names() == sr.design.diagnostic.bpms.get("BPM").names()
+
+ assert sr.live.diagnostic.bpms.BPM is bpms
diff --git a/tests/tuning_tools/test_bba.py b/tests/tuning_tools/test_bba.py
index 330c8118f..22f60c144 100644
--- a/tests/tuning_tools/test_bba.py
+++ b/tests/tuning_tools/test_bba.py
@@ -9,16 +9,16 @@ def test_bba():
SR = sr.design
# Add a misalignement
- SR.bpm.get("BPM_C04-04").offset.set([20e-6, -15e-6])
+ SR.diagnostic.bpm.get("BPM_C04-04").offset.set([20e-6, -15e-6])
# BBA (standard bow tie, model independant)
- bba = SR.get_bba("BBA-BPM_C04-04")
+ bba = SR.tool.get("BBA-BPM_C04-04")
bba.measure()
assert np.abs(bba.h_offset() - 20e-6) < 1e-6
assert np.abs(bba.v_offset() + 15e-6) < 1e-6
# BBA (model dependant method)
- bba = SR.get_bba("BBA2-BPM_C04-04")
+ bba = SR.tool.get("BBA2-BPM_C04-04")
bba.minicycle_sleep_time = 0
bba.measure()
assert np.abs(bba.h_offset() - 20e-6) < 1e-6
diff --git a/tests/tuning_tools/test_chromaticity_monitor.py b/tests/tuning_tools/test_chromaticity_monitor.py
index 3f7671d9f..4f9c7e115 100644
--- a/tests/tuning_tools/test_chromaticity_monitor.py
+++ b/tests/tuning_tools/test_chromaticity_monitor.py
@@ -13,7 +13,7 @@ def test_simulator_chromaticity_monitor():
sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", ignore_external=True)
sr.design.get_lattice().enable_6d()
chromaAT = sr.design.get_lattice().get_chrom()[:-1]
- chromaticity_monitor = sr.design.get_chromaticity_monitor("CHROMATICITY_MONITOR")
+ chromaticity_monitor = sr.design.tool.get("CHROMATICITY_MONITOR")
assert chromaticity_monitor.chromaticity.unit() == "1"
assert chromaticity_monitor.dispersion.unit() == "m"
chromaticity_monitor.measure(fit_dispersion=True, callback=callback)
@@ -43,7 +43,7 @@ def test_simulator_chromaticity_monitor():
)
def test_controlsystem_chromaticity_monitor(install_test_package):
sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml")
- chromaticity_monitor = sr.live.get_chromaticity_monitor("CHROMATICITY_MONITOR")
+ chromaticity_monitor = sr.live.tool.get("CHROMATICITY_MONITOR")
assert chromaticity_monitor.chromaticity.get() is None
chromaticity_monitor.measure(
do_plot=False,
diff --git a/tests/tuning_tools/test_tool_accessors.py b/tests/tuning_tools/test_tool_accessors.py
index 1ccbf5dfa..f582040ac 100644
--- a/tests/tuning_tools/test_tool_accessors.py
+++ b/tests/tuning_tools/test_tool_accessors.py
@@ -1,4 +1,8 @@
+import pytest
+
from pyaml.accelerator import Accelerator
+from pyaml.common.exception import PyAMLException
+from pyaml.lattice.simulator import Simulator
def test_tuning_tools_expose_configured_elements():
@@ -9,45 +13,97 @@ def test_tuning_tools_expose_configured_elements():
)
design = sr.design
- tune_monitor = design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = design.diagnostic.get("BETATRON_TUNE")
quadrupoles = design.magnets.get("QForTune")
- assert design.tune.tune_monitor is tune_monitor
- assert design.tune.quadrupoles is quadrupoles
- assert design.trm.tune_monitor is tune_monitor
- assert design.trm.quadrupoles is quadrupoles
+ assert design.tool.tune.tune_monitor is tune_monitor
+ assert design.tool.tune.quadrupoles is quadrupoles
+ assert design.tool.trm.tune_monitor is tune_monitor
+ assert design.tool.trm.quadrupoles is quadrupoles
- chromaticity_monitor = design.get_chromaticity_monitor("CHROMATICITY_MONITOR")
+ chromaticity_monitor = design.tool.get("CHROMATICITY_MONITOR")
sextupoles = design.magnets.get("Sext")
- assert design.chromaticity.chromaticity_monitor is chromaticity_monitor
- assert design.chromaticity.sextupoles is sextupoles
- assert design.crm.chromaticity_monitor is chromaticity_monitor
- assert design.crm.sextupoles is sextupoles
+ assert design.tool.chromaticity.chromaticity_monitor is chromaticity_monitor
+ assert design.tool.chromaticity.sextupoles is sextupoles
+ assert design.tool.crm.chromaticity_monitor is chromaticity_monitor
+ assert design.tool.crm.sextupoles is sextupoles
- bpms = design.bpms.get("BPM")
+ bpms = design.diagnostic.bpms.get("BPM")
rf_plant = design.rf.get("DEFAULT_RF_PLANT")
assert chromaticity_monitor.tune_monitor is tune_monitor
assert chromaticity_monitor.bpms is bpms
assert chromaticity_monitor.rf_plant is rf_plant
- assert design.dispersion.bpms is bpms
- assert design.dispersion.rf_plant is rf_plant
+ assert design.tool.dispersion.bpms is bpms
+ assert design.tool.dispersion.rf_plant is rf_plant
hcorrectors = design.magnets.get("HCorr")
vcorrectors = design.magnets.get("VCorr")
- assert design.orbit.bpms is bpms
- assert design.orbit.hcorrectors is hcorrectors
- assert design.orbit.vcorrectors is vcorrectors
- assert design.orbit.correctors.names() == hcorrectors.names() + vcorrectors.names()
- assert design.orbit.rf_plant is rf_plant
- assert design.orm.bpms is bpms
- assert design.orm.hcorrectors is hcorrectors
- assert design.orm.vcorrectors is vcorrectors
+ assert design.tool.orbit.bpms is bpms
+ assert design.tool.orbit.hcorrectors is hcorrectors
+ assert design.tool.orbit.vcorrectors is vcorrectors
+ assert design.tool.orbit.correctors.names() == hcorrectors.names() + vcorrectors.names()
+ assert design.tool.orbit.rf_plant is rf_plant
+ assert design.tool.orm.bpms is bpms
+ assert design.tool.orm.hcorrectors is hcorrectors
+ assert design.tool.orm.vcorrectors is vcorrectors
for name in ("BBA-BPM_C04-04", "BBA2-BPM_C04-04"):
- bba = design.get_bba(name)
+ bba = design.tool.get(name)
assert bba.bpms is bpms
- assert bba.bpm is design.bpm.get("BPM_C04-04")
+ assert bba.bpm is design.diagnostic.bpm.get("BPM_C04-04")
assert bba.hcorrector is design.magnet.get("SF2E-C02-H")
assert bba.vcorrector is design.magnet.get("SD1A-C26-V")
assert bba.quadrupole is design.magnet.get("QF6B-C04")
- assert design.get_bba("BBA2-BPM_C04-04").tune_correction is design.tune
+ assert design.tool.get("BBA2-BPM_C04-04").tune_correction is design.tool.tune
+
+
+def test_tool_get_returns_named_tool():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ assert design.tool.get("DEFAULT_TUNE_CORRECTION") is design.tool.tune
+ assert design.tool.get("DEFAULT_ORBIT_RESPONSE_MATRIX") is design.tool.orm
+
+
+def test_tool_get_with_no_name_returns_all_configured_tools():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ all_tools = design.tool.get()
+ assert design.tool.tune in all_tools
+ assert design.tool.trm in all_tools
+ assert design.tool.orbit in all_tools
+ assert design.tool.orm in all_tools
+ assert design.tool.chromaticity in all_tools
+ assert design.tool.crm in all_tools
+ assert design.tool.dispersion in all_tools
+
+
+def test_tool_raises_when_default_missing(ebs_lattice_file):
+ holder = Simulator(name="empty", lattice=str(ebs_lattice_file))
+
+ with pytest.raises(PyAMLException) as exc:
+ _ = holder.tool.tune
+ assert "DEFAULT_TUNE_CORRECTION" in str(exc.value)
+
+
+def test_tool_raises_when_default_wrong_type():
+ design = Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+ # Swap the registered default so it points to an object of the wrong type.
+ design._TOOLS["DEFAULT_TUNE_CORRECTION"] = design.tool.orbit
+
+ with pytest.raises(PyAMLException) as exc:
+ _ = design.tool.tune
+ assert "DEFAULT_TUNE_CORRECTION" in str(exc.value)
+ assert "Tune" in str(exc.value)
diff --git a/tests/tuning_tools/test_tool_holder.py b/tests/tuning_tools/test_tool_holder.py
new file mode 100644
index 000000000..cd921940d
--- /dev/null
+++ b/tests/tuning_tools/test_tool_holder.py
@@ -0,0 +1,47 @@
+import pytest
+
+from pyaml.accelerator import Accelerator
+from pyaml.common.exception import PyAMLException
+
+
+@pytest.fixture
+def design():
+ return Accelerator.load(
+ "tests/config/EBSOrbit.yaml",
+ ignore_external=True,
+ include_locations=False,
+ ).design
+
+
+def test_tool_holder_getitem_exact_name_matches_get(design):
+ assert design.tool["DEFAULT_TUNE_CORRECTION"] is design.tool.get("DEFAULT_TUNE_CORRECTION")
+
+
+def test_tool_holder_getitem_exact_name_miss_raises(design):
+ with pytest.raises(PyAMLException):
+ design.tool["UNKNOWN"]
+
+
+def test_tool_holder_getitem_wildcard_returns_an_array(design):
+ matching = design.tool["DEFAULT_TUNE*"]
+ assert sorted(matching.names()) == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_TUNE_RESPONSE_MATRIX"]
+ assert design.tool["MISSING*"].names() == []
+
+
+def test_tool_holder_getitem_list_of_patterns(design):
+ selected = design.tool[["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]]
+ assert selected.names() == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]
+
+
+def test_tool_holder_getitem_list_selection_ignores_request_order(design):
+ """A list-of-patterns selection lands in configuration order, whatever order the names
+ were requested in, same as every other holder (see
+ test_every_accessor_returns_a_list_selection_in_configuration_order)."""
+ forward = design.tool[["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]]
+ backward = design.tool[["DEFAULT_ORBIT_CORRECTION", "DEFAULT_TUNE_CORRECTION"]]
+ assert forward.names() == backward.names() == ["DEFAULT_TUNE_CORRECTION", "DEFAULT_ORBIT_CORRECTION"]
+
+
+def test_tool_holder_getitem_regex(design):
+ matching = design.tool["re:^DEFAULT_(TUNE|ORBIT)_CORRECTION$"]
+ assert sorted(matching.names()) == ["DEFAULT_ORBIT_CORRECTION", "DEFAULT_TUNE_CORRECTION"]
diff --git a/tests/tuning_tools/test_transfer_line.py b/tests/tuning_tools/test_transfer_line.py
new file mode 100644
index 000000000..7c5b422c2
--- /dev/null
+++ b/tests/tuning_tools/test_transfer_line.py
@@ -0,0 +1,47 @@
+import numpy
+import pytest
+
+from pyaml.accelerator import Accelerator
+
+
+def test_transfer_line():
+ tl2 = Accelerator.load("tests/config/tl2/tl2.yml")
+ tl2.design.tool.orm.measure()
+ orm_data = tl2.design.tool.orm.get()
+ mat = numpy.array(orm_data["matrix"])
+
+ orm_hv = mat[:9, 8:]
+ orm_vh = mat[9:, :8]
+ assert numpy.allclose(orm_hv, 0)
+ assert numpy.allclose(orm_vh, 0)
+
+ orm_h = mat[:9, :8]
+ orm_v = mat[9:, 8:]
+
+ assert numpy.allclose(
+ orm_h[8, :], [1.49217029, 3.11318219, 10.60494678, -0.82242986, -19.2814236, -14.92682822, 1.28503979, 1.60584401]
+ )
+ assert numpy.allclose(
+ orm_v[8, :], [10.95203344, 10.56524176, 16.43659334, 32.50321299, 12.72373742, 10.3122307, 10.47365958, 2.61214668]
+ )
+
+ tl2.design.tool.orm.save("tl2.json")
+ tl2.design.tool.orbit.load("tl2.json")
+
+ # Mangle the orbit
+ hcorr = tl2.design.magnets.get("HCORR")
+ vcorr = tl2.design.magnets.get("VCORR")
+ numpy.random.seed(1)
+ std_kick = 1e-6 # rad
+ hcorr.strengths.set(hcorr.strengths.get() + std_kick * numpy.random.normal(size=len(hcorr)))
+ vcorr.strengths.set(vcorr.strengths.get() + std_kick * numpy.random.normal(size=len(vcorr)))
+
+ orbit = tl2.design.diagnostic.bpms.get("BPMS").positions
+ assert numpy.allclose(numpy.std(orbit.get(), axis=0), [1.78288459e-05, 3.57986943e-05])
+
+ tl2.design.tool.orbit.correct()
+ tl2.design.tool.orbit.correct()
+
+ assert numpy.allclose(numpy.std(orbit.get(), axis=0), [7.51291713e-07, 7.24545959e-07])
+
+ assert numpy.allclose(orbit.get()[2], tl2.design.diagnostic.bpm.get("BPM_QD5").positions.get())
diff --git a/tests/tuning_tools/test_tune.py b/tests/tuning_tools/test_tune.py
index a114230cf..fe23a48e1 100644
--- a/tests/tuning_tools/test_tune.py
+++ b/tests/tuning_tools/test_tune.py
@@ -14,7 +14,7 @@ def test_tune():
sr.design.get_lattice().disable_6d()
quadForTuneDesign = sr.design.magnets.get("QForTune")
- tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE")
# Build tune response matrix
tune = tune_monitor.tune.get()
print(tune)
diff --git a/tests/tuning_tools/test_tune_hardware.py b/tests/tuning_tools/test_tune_hardware.py
index 8e83197df..e48ce2657 100644
--- a/tests/tuning_tools/test_tune_hardware.py
+++ b/tests/tuning_tools/test_tune_hardware.py
@@ -12,7 +12,7 @@ def test_tune():
# Build tune response matrix (hardware units)
- tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE")
tune = tune_monitor.tune.get()
print(tune)
tunemat = np.zeros((len(quadForTuneDesign), 2))
diff --git a/tests/tuning_tools/test_tune_monitor.py b/tests/tuning_tools/test_tune_monitor.py
index 893f096ec..66694c370 100644
--- a/tests/tuning_tools/test_tune_monitor.py
+++ b/tests/tuning_tools/test_tune_monitor.py
@@ -11,7 +11,7 @@ def test_simulator_tune_monitor(
ignore_external=True,
)
sr.design.get_lattice().disable_6d()
- tune_monitor = sr.design.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = sr.design.diagnostic.get("BETATRON_TUNE")
assert tune_monitor.tune.get()[0] == sr.design.get_lattice().get_tune()[0]
assert tune_monitor.tune.get()[1] == sr.design.get_lattice().get_tune()[1]
assert np.abs(tune_monitor.frequency.get()[0] - 56834.22592393) < 1e-6
@@ -31,6 +31,6 @@ def test_controlsystem_tune_monitor(
sr = accelerator_from_fragments(
*tune_monitor_configuration_fragments,
)
- tune_monitor = sr.live.get_betatron_tune_monitor("BETATRON_TUNE")
+ tune_monitor = sr.live.diagnostic.get("BETATRON_TUNE")
assert tune_monitor.tune.get()[0] == 0.0
assert tune_monitor.tune.get()[1] == 0.0
diff --git a/tests/tuning_tools/test_tuning_dispersion.py b/tests/tuning_tools/test_tuning_dispersion.py
index 16d2cd397..a2abcc430 100644
--- a/tests/tuning_tools/test_tuning_dispersion.py
+++ b/tests/tuning_tools/test_tuning_dispersion.py
@@ -12,12 +12,12 @@ def test_tuning_orm():
sr = Accelerator.load(config_path)
element_holder = sr.design
- dispersion = element_holder.dispersion
+ dispersion = element_holder.tool.dispersion
dispersion.measure()
dispersion_data = dispersion.get()
- bpms = element_holder.bpms.get("BPM")
+ bpms = element_holder.diagnostic.bpms.get("BPM")
assert len(dispersion_data["frequency_response_x"]) == len(bpms)
assert len(dispersion_data["frequency_response_y"]) == len(bpms)
diff --git a/tests/tuning_tools/test_tuning_orbit_correction.py b/tests/tuning_tools/test_tuning_orbit_correction.py
index 4bf3b6a66..930d59e93 100644
--- a/tests/tuning_tools/test_tuning_orbit_correction.py
+++ b/tests/tuning_tools/test_tuning_orbit_correction.py
@@ -22,12 +22,12 @@ def test_tuning_orbit_correction():
std_kick = 1e-6
hcorr = element_holder.magnets.get("HCorr")
vcorr = element_holder.magnets.get("VCorr")
- bpms = element_holder.bpms.get("BPM")
+ bpms = element_holder.diagnostic.bpms.get("BPM")
x, y = bpms.positions.get().T # get reference orbit
reference = np.concat((x, y))
# there should be nothing to correct, but still work
- element_holder.orbit.correct(reference=reference)
+ element_holder.tool.orbit.correct(reference=reference)
h_strengths = hcorr.strengths.get() + std_kick * np.random.normal(size=len(hcorr))
v_strengths = vcorr.strengths.get() + std_kick * np.random.normal(size=len(vcorr))
@@ -43,7 +43,7 @@ def test_tuning_orbit_correction():
assert np.isclose(std_bc[0], original_H, rtol=0, atol=1e-14)
assert np.isclose(std_bc[1], original_V, rtol=0, atol=1e-14)
- element_holder.orbit.correct(reference=None)
+ element_holder.tool.orbit.correct(reference=None)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -53,7 +53,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test gain_h/gain_v
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(gain_h=0.5, gain_v=0.1)
+ element_holder.tool.orbit.correct(gain_h=0.5, gain_v=0.1)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -63,7 +63,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test gain/gain_v
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(gain=1, gain_v=0.1)
+ element_holder.tool.orbit.correct(gain=1, gain_v=0.1)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -73,7 +73,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test singular_values_h
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(singular_values_h=100)
+ element_holder.tool.orbit.correct(singular_values_h=100)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -83,7 +83,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test singular_values_v
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(singular_values_v=50)
+ element_holder.tool.orbit.correct(singular_values_v=50)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -93,7 +93,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test plane=H
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(plane="H")
+ element_holder.tool.orbit.correct(plane="H")
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -104,7 +104,7 @@ def test_tuning_orbit_correction():
# mangle orbit again, test plane=V
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.correct(plane="V")
+ element_holder.tool.orbit.correct(plane="V")
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
@@ -116,65 +116,65 @@ def test_tuning_orbit_correction():
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.set_weight("SJ2A-C04-H", 2)
- element_holder.orbit.correct()
+ element_holder.tool.orbit.set_weight("SJ2A-C04-H", 2)
+ element_holder.tool.orbit.correct()
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
assert np.isclose(std_ac[0], 5.057265926153962e-07, rtol=0, atol=1e-14)
assert np.isclose(std_ac[1], 4.78927471675123e-07, rtol=0, atol=1e-14)
- element_holder.orbit.set_weight("SJ2A-C04-H", 1)
+ element_holder.tool.orbit.set_weight("SJ2A-C04-H", 1)
# mangle orbit again, test bpm weight
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.set_weight("BPM_C04-05", 2)
- element_holder.orbit.correct()
+ element_holder.tool.orbit.set_weight("BPM_C04-05", 2)
+ element_holder.tool.orbit.correct()
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
assert np.isclose(std_ac[0], 5.056719006414065e-07, rtol=0, atol=1e-14)
assert np.isclose(std_ac[1], 4.790610352466602e-07, rtol=0, atol=1e-14)
- element_holder.orbit.set_weight("BPM_C04-05", 1)
+ element_holder.tool.orbit.set_weight("BPM_C04-05", 1)
# mangle orbit again, test virtual weight
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
- element_holder.orbit.set_virtual_weight(2)
- element_holder.orbit.correct()
+ element_holder.tool.orbit.set_virtual_weight(2)
+ element_holder.tool.orbit.correct()
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
assert np.isclose(std_ac[0], 5.05398857685373e-07, rtol=0, atol=1e-14)
assert np.isclose(std_ac[1], 4.789270969888965e-07, rtol=0, atol=1e-14)
- element_holder.orbit.set_virtual_weight(1000)
+ element_holder.tool.orbit.set_virtual_weight(1000)
# mangle orbit again, test virtual target
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
virtual_target = 1e-8
- element_holder.orbit.correct(virtual_target=virtual_target)
+ element_holder.tool.orbit.correct(virtual_target=virtual_target)
delta_h_strengths = hcorr.strengths.get() - h_strengths
delta_h_strengths_sum = -np.sum(delta_h_strengths)
assert np.isclose(delta_h_strengths_sum - virtual_target, 0, rtol=0, atol=1e-13)
- element_holder.orbit.set_virtual_weight(1)
+ element_holder.tool.orbit.set_virtual_weight(1)
# mangle orbit again, test reference
hcorr.strengths.set(h_strengths)
vcorr.strengths.set(v_strengths)
reference = np.concatenate((positions_bc[:, 0], positions_bc[:, 1]))
- element_holder.orbit.correct(reference=reference)
+ element_holder.tool.orbit.correct(reference=reference)
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
assert np.isclose(std_ac[0], original_H, rtol=0, atol=1e-14)
assert np.isclose(std_ac[1], original_V, rtol=0, atol=1e-14)
# no need to mangle orbit again, test reference/plane=H
- element_holder.orbit.correct(reference=reference / 2, plane="H")
+ element_holder.tool.orbit.correct(reference=reference / 2, plane="H")
positions_ac = bpms.positions.get()
std_ac = np.std(positions_ac, axis=0)
assert np.isclose(std_ac[0], 3.360429728849497e-05, rtol=0, atol=1e-14)
@@ -187,7 +187,7 @@ def test_tuning_orbit_correction():
frf = element_holder.rf.frequency.get()
element_holder.rf.frequency.set(frf + 100)
for _ in range(3):
- element_holder.orbit.correct(
+ element_holder.tool.orbit.correct(
reference=reference_before_rf,
plane="H",
rf=True,
@@ -202,12 +202,12 @@ def test_tuning_orbit_correction():
x, y = bpms.positions.get().T # get reference orbit
reference_before_rf = np.concat((x, y))
- rf_weight = element_holder.orbit.get_rf_weight()
- element_holder.orbit.set_rf_weight(1.1 * rf_weight)
+ rf_weight = element_holder.tool.orbit.get_rf_weight()
+ element_holder.tool.orbit.set_rf_weight(1.1 * rf_weight)
frf = element_holder.rf.frequency.get()
element_holder.rf.frequency.set(frf + 100)
for _ in range(8):
- element_holder.orbit.correct(
+ element_holder.tool.orbit.correct(
reference=reference_before_rf,
plane="H",
rf=True,
@@ -217,12 +217,12 @@ def test_tuning_orbit_correction():
frf_after = element_holder.rf.frequency.get()
assert np.isclose(frf, frf_after, rtol=0, atol=1e-16)
- element_holder.orbit.set_rf_weight(rf_weight)
+ element_holder.tool.orbit.set_rf_weight(rf_weight)
# test getters of weights
- assert np.isclose(element_holder.orbit.get_weight("BPM_C04-05", plane="H"), 1, rtol=0, atol=1e-16)
- assert np.isclose(element_holder.orbit.get_virtual_weight(), 1, rtol=0, atol=1e-16)
- assert np.isclose(element_holder.orbit.get_rf_weight(), rf_weight, rtol=0, atol=1e-16)
+ assert np.isclose(element_holder.tool.orbit.get_weight("BPM_C04-05", plane="H"), 1, rtol=0, atol=1e-16)
+ assert np.isclose(element_holder.tool.orbit.get_virtual_weight(), 1, rtol=0, atol=1e-16)
+ assert np.isclose(element_holder.tool.orbit.get_rf_weight(), rf_weight, rtol=0, atol=1e-16)
def test_tuning_orbit_correction_config():
diff --git a/tests/tuning_tools/test_tuning_orm.py b/tests/tuning_tools/test_tuning_orm.py
index 553bce161..3ea994f05 100644
--- a/tests/tuning_tools/test_tuning_orm.py
+++ b/tests/tuning_tools/test_tuning_orm.py
@@ -15,9 +15,9 @@ def test_tuning_orm():
sr = Accelerator.load(config_path)
element_holder = sr.design
- orm = element_holder.orm
+ orm = element_holder.tool.orm
- bpms = element_holder.bpms.get("BPM")
+ bpms = element_holder.diagnostic.bpms.get("BPM")
hcorr_names = element_holder.magnets.get("HCorr").names()[:4]
vcorr_names = element_holder.magnets.get("VCorr").names()[:4]
orm.measure(corrector_names=hcorr_names + vcorr_names)
@@ -31,4 +31,4 @@ def test_tuning_orm():
orm.save(save_path=f.name)
# load saved file
- element_holder.orbit.load(f.name)
+ element_holder.tool.orbit.load(f.name)
diff --git a/tests/tuning_tools/test_tuning_tools.py b/tests/tuning_tools/test_tuning_tools.py
index 5c748b003..635142a2c 100644
--- a/tests/tuning_tools/test_tuning_tools.py
+++ b/tests/tuning_tools/test_tuning_tools.py
@@ -12,11 +12,11 @@ def callback(action: Action, data: dict):
def test_tune_tool():
sr = Accelerator.load("tests/config/EBSTune.yaml", include_locations=False)
sr.design.get_lattice().disable_6d()
- sr.design.trm.measure(callback=callback)
- sr.design.trm.save("tunemat.json")
- sr.design.tune.load("tunemat.json")
- sr.design.tune.set([0.17, 0.32], iter=2)
- tune = sr.design.tune.readback()
+ sr.design.tool.trm.measure(callback=callback)
+ sr.design.tool.trm.save("tunemat.json")
+ sr.design.tool.tune.load("tunemat.json")
+ sr.design.tool.tune.set([0.17, 0.32], iter=2)
+ tune = sr.design.tool.tune.readback()
assert np.abs(tune[0] - 0.17) < 1e-5
assert np.abs(tune[1] - 0.32) < 1e-5
@@ -24,20 +24,20 @@ def test_tune_tool():
def test_tune_add():
sr = Accelerator.load("tests/config/EBSTune.yaml", include_locations=False)
sr.design.get_lattice().disable_6d()
- sr.design.tune.load("tunemat.json")
- tune_initial = sr.design.tune.readback()
+ sr.design.tool.tune.load("tunemat.json")
+ tune_initial = sr.design.tool.tune.readback()
dtune = np.array([0.01, -0.01])
- sr.design.tune.add(dtune)
- tune = sr.design.tune.readback()
+ sr.design.tool.tune.add(dtune)
+ tune = sr.design.tool.tune.readback()
np.testing.assert_allclose(tune - tune_initial, dtune, atol=1e-5)
def test_chroma_tool():
sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False)
sr.design.get_lattice().enable_6d()
- sr.design.chromaticity.set([8.0, 5.0], iter=2)
+ sr.design.tool.chromaticity.set([8.0, 5.0], iter=2)
QpAT = sr.design.get_lattice().get_chrom()[:-1]
- Qp = sr.design.chromaticity.readback()
+ Qp = sr.design.tool.chromaticity.readback()
assert np.abs(Qp[0] - 8.0) < 1e-3
assert np.abs(Qp[1] - 5.0) < 1e-3
assert np.abs(QpAT[0] - 8.0) < 1e-2
@@ -48,7 +48,7 @@ def test_chroma_add():
sr: Accelerator = Accelerator.load("tests/config/EBSOrbit.yaml", include_locations=False)
sr.design.get_lattice().enable_6d()
chromaAT = sr.design.get_lattice().get_chrom()[:-1]
- sr.design.chromaticity.add([0.5, 0.4])
+ sr.design.tool.chromaticity.add([0.5, 0.4])
chromaAT2 = sr.design.get_lattice().get_chrom()[:-1]
chromaDiff = chromaAT2 - chromaAT
assert np.abs(chromaDiff[0] - 0.5) < 5e-2