Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -121,3 +121,6 @@ hutch_python/tests/tst/db.txt

# unit test artifacts
*.sqlite

# ignore _version.py
_version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
409 Add option to skip loading experiment position presets
#################

API Changes
-----------
- N/A

Features
--------
- Added an option (available in conf.yml) to skip loading experiment motor position presets.

Bugfixes
--------
- N/A

Maintenance
-----------
- N/A

Contributors
------------
janeliu-slac
44 changes: 42 additions & 2 deletions docs/source/yaml_files.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ Yaml Files
``hutch-python`` uses a ``conf.yml`` file for basic configuration. This is a
standard yaml file with the following valid keys:
``hutch``, ``db``, ``load``, ``load_level``, ``experiment``, ``obj_config``,
``daq_type``, ``daq_host``, and ``daq_platform``, ``exclude_devices``.
``daq_type``, ``daq_host``, ``daq_platform``, ``exclude_devices``,
``additional_devices``, and ``load_experiment_presets``.


hutch
Expand Down Expand Up @@ -179,7 +180,7 @@ at load time. The list uses the following format:


additional_devices
------------
------------------
The ``additional_devices`` key is optional. This key allows hutch-python to
load additional devices that are on a different beamline or in a different
hutch/area. The first entry below ``additional_devices`` is a search name,
Expand Down Expand Up @@ -212,6 +213,45 @@ In the example below hutch-python will load all devices from "tmo_sqr1_search",
name: crix_*


load_experiment_presets
-----------------------
The ``load_experiment_presets`` key determines whether hutch-python loads
position presets for the active experiment. It takes a boolean value.

Position presets are saved locations that can be called by commands such as
``motor.mv_sample()``. Hutch-python supports two types of position presets.

- Beamline presets are permanent positions shared across experiments.
- Experiment presets are temporary positions associated with the active
experiment.

.. code-block:: YAML

load_experiment_presets: false

When set to ``false``, hutch-python still loads beamline presets. It does not
configure or read the active experiment's preset directory. This can improve
startup performance when the experiment directory contains many preset files.

When set to ``true``, hutch-python makes both beamline and active experiment
presets available.

.. code-block:: YAML

load_experiment_presets: true

The default is ``true``. Existing configurations that omit this key retain
their current behavior.

Use the unquoted YAML values ``true`` and ``false``. Quoted values such as
``"false"`` are strings rather than Boolean values and are invalid for this
setting.

This setting affects only position presets. It does not disable loading the
experiment Python file, questionnaire objects, or other experiment
configuration.


Full File Example
-----------------

Expand Down
3 changes: 2 additions & 1 deletion hutch_python/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
'obj_config',
'session_timer',
'exclude_devices',
'additional_devices'
'additional_devices',
'load_experiment_presets'
)
NO_LOG_EXCEPTIONS = (KeyboardInterrupt, SystemExit)
LOG_DOMAINS = {".pcdsn", ".slac.stanford.edu"}
47 changes: 39 additions & 8 deletions hutch_python/load_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -582,26 +582,57 @@ def load_conf(conf, hutch_dir=None, args=None):
all_objects='Namespace of all loaded objects.',
)

# Install Presets
# Configure saved motor positions. Presets are stored as YAML files under
# the hutch launch directory.
if hutch_dir is not None:
# Log preset setup failures without stopping the entire session.
with safe_load('position presets'):
presets_dir = Path(hutch_dir) / 'presets'

# Beamline presets are permanent and shared by all experiments.
beamline_presets = presets_dir / 'beamline'

# Preserve existing behavior unless the YAML configuration file
# explicitly disables experiment presets.
load_experiment_presets = conf.get('load_experiment_presets', True)
if not isinstance(load_experiment_presets, bool):
logger.error(
'Invalid load_experiment_presets value %r; expected "true" '
'or "false". Experiment presets will be loaded.',
load_experiment_presets,
)
load_experiment_presets = True

# Preset root and permanent beamline directory are required.
preset_paths = [presets_dir, beamline_presets]
if experiment is not None:

# Experiment presets are motor positions associated with the active
# experiment. Configure them only when an experiment is available
# and experiment preset loading is enabled.
if experiment is not None and load_experiment_presets:
experiment_presets = presets_dir / raw_expname
preset_paths.append(experiment_presets)

# Create any missing preset directories.
for path in preset_paths:
if not path.exists():
path.mkdir()
path.chmod(0o777)
if experiment is None:
setup_preset_paths(hutch=beamline_presets,
defer_loading=True)

# Make both permanent beamline presets and active experiment
# presets available.
if experiment is not None and load_experiment_presets:
setup_preset_paths(
hutch=beamline_presets,
exp=experiment_presets,
defer_loading=True,
)
else:
setup_preset_paths(hutch=beamline_presets,
exp=experiment_presets,
defer_loading=True)
# Make only permanent beamline presets available.
setup_preset_paths(
hutch=beamline_presets,
defer_loading=True,
)

# configure objects
if obj_config is not None:
Expand Down
57 changes: 57 additions & 0 deletions hutch_python/tests/test_load_conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,63 @@ def test_file_load():
assert len(Presets._paths) == 2


def test_experiment_presets_disabled(monkeypatch, tmp_path):
# Check that an active experiment doesn't allow experiment presets to
# be configured when the setting is disabled.
setup_calls = []

def mock_setup_preset_paths(**kwargs):
setup_calls.append(kwargs)
monkeypatch.setattr(
'hutch_python.load_conf.setup_preset_paths',
mock_setup_preset_paths,
)
monkeypatch.setattr(
'hutch_python.load_conf.get_qs_objs',
lambda expname: {},
)
monkeypatch.setattr(
'hutch_python.load_conf.get_exp_objs',
lambda expname: SimpleNamespace(),
)
load_conf(
{
'hutch': 'tst',
'experiment': 'tstx010',
'load_experiment_presets': False,
'daq_type': 'nodaq',
},
hutch_dir=tmp_path,
)
beamline_path = tmp_path / 'presets' / 'beamline'
experiment_path = tmp_path / 'presets' / 'x010'
assert setup_calls == [{
'hutch': beamline_path,
'defer_loading': True,
}]
assert beamline_path.is_dir()
assert not experiment_path.exists()


def test_presets_without_experiment(monkeypatch, tmp_path):
setup_calls = []
monkeypatch.setattr(
'hutch_python.load_conf.setup_preset_paths',
lambda **kwargs: setup_calls.append(kwargs),
)
load_conf(
{
'load_experiment_presets': True,
'daq_type': 'nodaq',
},
hutch_dir=tmp_path,
)
assert setup_calls == [{
'hutch': tmp_path / 'presets' / 'beamline',
'defer_loading': True,
}]


def test_exp_override():
logger.debug('test_exp_override')
set_sim_mode(True)
Expand Down
Loading