Skip to content

Commit 6953d62

Browse files
authored
Use modifiers for knobs madx (#441)
* remove hardcoded knobs.madx * zip response output * save config-files for model creation, response creation * acc-models-path replacement and code cleanup
1 parent ac2f489 commit 6953d62

File tree

14 files changed

+328
-201
lines changed

14 files changed

+328
-201
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# OMC3 Changelog
22

3+
#### 2024-07-08 - v0.15.0 - _jdilly_
4+
5+
- PINNING NUMPY TO < 2.0.0
6+
7+
- Changed:
8+
- Model creation:
9+
- removed hard-coded `knobs.madx` from `lhc`
10+
- removed `corrections.madx` from `lhc` best-knowledge model
11+
- zip up log-output files in `response_madx.py`
12+
- keep 0th output file in `response_madx.py` for reference of the model setup
13+
- Sequence and modifiers use the acc-models symlink in madx-jobs where applicable.
14+
315
#### 2024-06-05 - v0.14.1 - _jdilly_
416

517
- Fixed:

omc3/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
__title__ = "omc3"
1212
__description__ = "An accelerator physics tools package for the OMC team at CERN."
1313
__url__ = "https://github.com/pylhc/omc3"
14-
__version__ = "0.14.1"
14+
__version__ = "0.15.0"
1515
__author__ = "pylhc"
1616
__author_email__ = "[email protected]"
1717
__license__ = "MIT"

omc3/correction/response_madx.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
from typing import Dict, Sequence, Tuple, List
1919

2020
import numpy as np
21+
import zipfile
2122
import pandas as pd
2223
import tfs
2324
from optics_functions.coupling import coupling_via_cmatrix
@@ -139,9 +140,16 @@ def _clean_up(temp_dir: Path, num_proc: int) -> None:
139140
log_path = job_path.with_name(f"{job_path.name}.log")
140141
full_log += log_path.read_text()
141142
log_path.unlink()
142-
job_path.unlink()
143-
full_log_path = temp_dir / "response_madx_full.log"
144-
full_log_path.write_text(full_log)
143+
if index: # keep 0th for reference
144+
job_path.unlink()
145+
146+
# write compressed full log file
147+
full_log_name = "response_madx_full.log"
148+
zipfile.ZipFile(
149+
temp_dir / f"{full_log_name}.zip",
150+
mode="w",
151+
compression=zipfile.ZIP_DEFLATED
152+
).writestr(full_log_name, full_log)
145153

146154

147155
def _load_madx_results(

omc3/knob_extractor.py

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
Specify user-defined output path. This should probably be
3434
`model_dir/knobs.madx`
3535
36-
default: ``knobs.madx``
37-
3836
3937
- **state**:
4038
@@ -461,16 +459,16 @@ def _write_knobsfile(output: Union[Path, str], collected_knobs: tfs.TfsDataFrame
461459
def _get_knobs_def_file(user_defined: Optional[Union[Path, str]] = None) -> Path:
462460
""" Check which knobs-definition file is appropriate to take. """
463461
if user_defined is not None:
464-
LOGGER.info(f"Using user defined knobs.txt: '{user_defined}")
462+
LOGGER.info(f"Using user knobs-definition file: '{user_defined}")
465463
return Path(user_defined)
466464

467465
if KNOBS_FILE_ACC_MODELS.is_file():
468-
LOGGER.info(f"Using model folder's knobs.txt: '{KNOBS_FILE_ACC_MODELS}")
466+
LOGGER.info(f"Using given acc-models folder's knobs.txt as knobsdefinition file: '{KNOBS_FILE_ACC_MODELS}")
469467
return KNOBS_FILE_ACC_MODELS
470468

471469
if KNOBS_FILE_AFS.is_file():
472470
# if all fails, fall back to lhc acc-models
473-
LOGGER.info(f"Using fallback knobs.txt: '{KNOBS_FILE_AFS}'")
471+
LOGGER.info(f"Using afs-fallback acc-models folder's knobs.txt as knobs-definition file: '{KNOBS_FILE_AFS}'")
474472
return KNOBS_FILE_AFS
475473

476474
raise FileNotFoundError("None of the knobs-definition files are available.")

omc3/model/accelerators/lhc.py

Lines changed: 55 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -311,29 +311,6 @@ def log_status(self) -> None:
311311
LOGGER.info(f"> Driven Tune X [{self.drv_tunes[0]:10.3f}]")
312312
LOGGER.info(f"> Driven Tune Y [{self.drv_tunes[1]:10.3f}]")
313313

314-
def load_main_seq_madx(self) -> str:
315-
if self.acc_model_path is not None:
316-
main_call = f'call, file = \'{self.acc_model_path / "lhc.seq"}\';'
317-
if self.year.startswith('hl'):
318-
main_call += f'\ncall, file = \'{self.acc_model_path / "hllhc_sequence.madx"}\';'
319-
return main_call
320-
try:
321-
return _get_call_main_for_year(self.year)
322-
except AttributeError:
323-
raise AcceleratorDefinitionError(
324-
"The accelerator definition is incomplete, mode "
325-
"has to be specified (--lhcmode option missing?)."
326-
)
327-
328-
# Private Methods ##########################################################
329-
330-
def _get_triplet_correctors_file(self) -> Path:
331-
correctors_dir = LHC_DIR / self.correctors_dir / "correctors"
332-
return correctors_dir / "triplet_correctors.json"
333-
334-
def _get_corrector_elems(self) -> Path:
335-
correctors_dir = LHC_DIR / self.correctors_dir / "correctors"
336-
return correctors_dir / f"corrector_elems_b{self.beam}.tfs"
337314

338315
def get_exciter_bpm(self, plane: str, commonbpms: List[str]):
339316
beam = self.beam
@@ -384,30 +361,11 @@ def get_synch_BPMs(self, index):
384361
elif self.beam == 2:
385362
return [i in index for i in self.model.loc["BPMSW.33R8.B2":].index]
386363

387-
def _get_madx_script_info_comments(self) -> str:
388-
info_comments = (
389-
f'title, "LHC Model created by omc3";\n'
390-
f"! Model directory: {Path(self.model_dir).absolute()}\n"
391-
f"! Natural Tune X [{self.nat_tunes[0]:10.3f}]\n"
392-
f"! Natural Tune Y [{self.nat_tunes[1]:10.3f}]\n"
393-
f"! Best Knowledge: [{'NO' if self.model_best_knowledge is None else 'OK':>10s}]\n"
394-
)
395-
if self.excitation == AccExcitationMode.FREE:
396-
info_comments += f"! Excitation [{'NO':>10s}]\n\n"
397-
return info_comments
398-
else:
399-
info_comments += (
400-
f"! Excitation [{'ACD' if self.excitation == AccExcitationMode.ACD else 'ADT':>10s}]\n"
401-
f"! > Driven Tune X [{self.drv_tunes[0]:10.3f}]\n"
402-
f"! > Driven Tune Y [{self.drv_tunes[1]:10.3f}]\n\n"
403-
)
404-
return info_comments
364+
# MAD-X Methods ############################################################
405365

406-
def get_base_madx_script(self, best_knowledge: bool = False) -> str:
407-
ats_md = False
408-
high_beta = False
366+
def get_base_madx_script(self, best_knowledge: bool = False, ats_md: bool = False, high_beta: bool = False) -> str:
409367
madx_script = (
410-
f"{self._get_madx_script_info_comments()}"
368+
f"{self._get_madx_script_info_comments()}\n\n"
411369
f"call, file = '{self.model_dir / MACROS_DIR / GENERAL_MACROS}';\n"
412370
f"call, file = '{self.model_dir / MACROS_DIR / LHC_MACROS}';\n"
413371
)
@@ -421,10 +379,12 @@ def get_base_madx_script(self, best_knowledge: bool = False) -> str:
421379
f"call, file = '{self.model_dir / MACROS_DIR / LHC_MACROS_RUN3}';\n"
422380
)
423381

424-
madx_script += "! ----- Calling Sequence and Optics -----\n"
382+
madx_script += "\n! ----- Calling Sequence -----\n"
425383
madx_script += "option, -echo; ! suppress output from base sequence loading to keep the log small\n"
426-
madx_script += self.load_main_seq_madx()
427-
madx_script += "\n\n"
384+
madx_script += self._get_madx_main_sequence_loading()
385+
madx_script += "\noption, echo; ! re-enable output to see the optics settings\n"
386+
387+
madx_script += "\n! ---- Call optics and other modifiers ----\n"
428388

429389
if self.modifiers is not None:
430390
madx_script += "".join(
@@ -434,6 +394,7 @@ def get_base_madx_script(self, best_knowledge: bool = False) -> str:
434394

435395
if self.year in ['2012', '2015', '2016', '2017', '2018', '2021', 'hllhc1.3']:
436396
# backwards compatibility with pre acc-models optics
397+
# WARNING: This might override values extracted via the knob-extractor.
437398
madx_script += (
438399
f"\n! ----- Defining Configuration Specifics -----\n"
439400
f"xing_angles = {'1' if self.xing else '0'};\n"
@@ -443,14 +404,13 @@ def get_base_madx_script(self, best_knowledge: bool = False) -> str:
443404
f" exec, set_default_crossing_scheme();\n"
444405
f"}}\n"
445406
)
446-
else:
447-
madx_script += 'call, file="knobs.madx";\n\n'
448407

449408
madx_script += (
409+
"\n! ----- Finalize Sequence -----\n"
450410
"exec, cycle_sequences();\n"
451411
f"use, sequence = LHCB{self.beam};\n"
452-
f"option, echo;\n"
453412
)
413+
454414
if best_knowledge:
455415
# madx_script += f"exec, load_average_error_table({self.energy}, {self.beam});\n"
456416
madx_script += (
@@ -459,6 +419,7 @@ def get_base_madx_script(self, best_knowledge: bool = False) -> str:
459419
f"seterr, table=errtab;\n"
460420
f"call, file = '{self.model_dir / B2_SETTINGS_MADX}';\n"
461421
)
422+
462423
if high_beta:
463424
madx_script += "exec, high_beta_matcher();\n"
464425

@@ -480,6 +441,39 @@ def get_base_madx_script(self, best_knowledge: bool = False) -> str:
480441
madx_script += "exec, full_response_ats();\n"
481442

482443
return madx_script
444+
445+
def _get_madx_script_info_comments(self) -> str:
446+
info_comments = (
447+
f'title, "LHC Model created by omc3";\n'
448+
f"! Model directory: {Path(self.model_dir).absolute()}\n"
449+
f"! Natural Tune X [{self.nat_tunes[0]:10.3f}]\n"
450+
f"! Natural Tune Y [{self.nat_tunes[1]:10.3f}]\n"
451+
f"! Best Knowledge: [{'NO' if self.model_best_knowledge is None else 'YES':>10s}]\n"
452+
)
453+
if self.excitation == AccExcitationMode.FREE:
454+
info_comments += f"! Excitation [{'NO':>10s}]\n"
455+
else:
456+
info_comments += (
457+
f"! Excitation [{'ACD' if self.excitation == AccExcitationMode.ACD else 'ADT':>10s}]\n"
458+
f"! > Driven Tune X [{self.drv_tunes[0]:10.3f}]\n"
459+
f"! > Driven Tune Y [{self.drv_tunes[1]:10.3f}]\n"
460+
461+
)
462+
return info_comments
463+
464+
def _get_madx_main_sequence_loading(self) -> str:
465+
if self.acc_model_path is not None:
466+
main_call = f'call, file = \'{self.acc_model_path / "lhc.seq"}\';'
467+
if self.year.startswith('hl'):
468+
main_call += f'\ncall, file = \'{self.acc_model_path / "hllhc_sequence.madx"}\';'
469+
return main_call
470+
try:
471+
return _get_call_main_for_year(self.year)
472+
except AttributeError:
473+
raise AcceleratorDefinitionError(
474+
"The accelerator definition is incomplete, mode "
475+
"has to be specified (--lhcmode option missing?)."
476+
)
483477

484478
def get_update_correction_script(self, outpath: Union[Path, str], corr_files: Sequence[Union[Path, str]]) -> str:
485479
madx_script = self.get_base_madx_script()
@@ -488,6 +482,8 @@ def get_update_correction_script(self, outpath: Union[Path, str], corr_files: Se
488482
madx_script += f"exec, do_twiss_elements(LHCB{self.beam}, '{str(outpath)}', {self.dpp});\n"
489483
return madx_script
490484

485+
# Private Methods ##########################################################
486+
491487
def _uses_ats_knobs(self) -> bool:
492488
"""
493489
Returns wether the ATS knobs and macros should be used, based on the instance's year.
@@ -507,6 +503,14 @@ def _uses_run3_macros(self) -> bool:
507503
except ValueError: # if a "hllhc1.x" year is given
508504
return False
509505

506+
def _get_triplet_correctors_file(self) -> Path:
507+
correctors_dir = LHC_DIR / self.correctors_dir / "correctors"
508+
return correctors_dir / "triplet_correctors.json"
509+
510+
def _get_corrector_elems(self) -> Path:
511+
correctors_dir = LHC_DIR / self.correctors_dir / "correctors"
512+
return correctors_dir / f"corrector_elems_b{self.beam}.tfs"
513+
510514

511515
# General functions ##########################################################
512516

omc3/model/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,6 @@
3838
PLANE_TO_HV = dict(X="H", Y="V")
3939

4040
AFS_ACCELERATOR_MODEL_REPOSITORY = Path("/afs/cern.ch/eng/acc-models")
41-
MODIFIER_SUBDIR = "operation/optics"
41+
OPTICS_SUBDIR = "operation/optics"
4242

4343
AFS_B2_ERRORS_ROOT = Path("/afs/cern.ch/eng/sl/lintrack/error_tables/")

0 commit comments

Comments
 (0)