apsbits 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. apsbits/__init__.py +18 -0
  2. apsbits/_version.py +21 -0
  3. apsbits/core/__init__.py +11 -0
  4. apsbits/core/best_effort_init.py +51 -0
  5. apsbits/core/catalog_init.py +36 -0
  6. apsbits/core/run_engine_init.py +118 -0
  7. apsbits/demo_instrument/README.md +1 -0
  8. apsbits/demo_instrument/__init__.py +22 -0
  9. apsbits/demo_instrument/callbacks/__init__.py +1 -0
  10. apsbits/demo_instrument/callbacks/nexus_data_file_writer.py +58 -0
  11. apsbits/demo_instrument/callbacks/spec_data_file_writer.py +97 -0
  12. apsbits/demo_instrument/configs/__init__.py +1 -0
  13. apsbits/demo_instrument/configs/devices.yml +52 -0
  14. apsbits/demo_instrument/configs/devices_aps_only.yml +6 -0
  15. apsbits/demo_instrument/configs/iconfig.yml +82 -0
  16. apsbits/demo_instrument/configs/logging.yml +41 -0
  17. apsbits/demo_instrument/devices/__init__.py +1 -0
  18. apsbits/demo_instrument/plans/__init__.py +8 -0
  19. apsbits/demo_instrument/plans/dm_plans.py +111 -0
  20. apsbits/demo_instrument/plans/sim_plans.py +69 -0
  21. apsbits/demo_instrument/startup.py +76 -0
  22. apsbits/demo_qserver/qs-config.yml +51 -0
  23. apsbits/demo_qserver/qs_host.sh +231 -0
  24. apsbits/demo_qserver/user_group_permissions.yaml +46 -0
  25. apsbits/tests/__init__.py +1 -0
  26. apsbits/tests/conftest.py +39 -0
  27. apsbits/tests/test_config.py +113 -0
  28. apsbits/tests/test_device_factories.py +44 -0
  29. apsbits/tests/test_general.py +98 -0
  30. apsbits/tests/test_stored_dict.py +139 -0
  31. apsbits/utils/__init__.py +1 -0
  32. apsbits/utils/aps_functions.py +67 -0
  33. apsbits/utils/config_loaders.py +169 -0
  34. apsbits/utils/controls_setup.py +107 -0
  35. apsbits/utils/create_new_instrument.py +129 -0
  36. apsbits/utils/helper_functions.py +123 -0
  37. apsbits/utils/logging_setup.py +211 -0
  38. apsbits/utils/make_devices.py +162 -0
  39. apsbits/utils/metadata.py +96 -0
  40. apsbits/utils/sim_creator.py +202 -0
  41. apsbits/utils/stored_dict.py +174 -0
  42. apsbits-1.0.0.dist-info/METADATA +195 -0
  43. apsbits-1.0.0.dist-info/RECORD +47 -0
  44. apsbits-1.0.0.dist-info/WHEEL +5 -0
  45. apsbits-1.0.0.dist-info/entry_points.txt +2 -0
  46. apsbits-1.0.0.dist-info/licenses/LICENSE +48 -0
  47. apsbits-1.0.0.dist-info/top_level.txt +1 -0
apsbits/__init__.py ADDED
@@ -0,0 +1,18 @@
1
+ # -*- coding: iso-8859-1 -*-
2
+
3
+ """Model Bluesky Data Acquisition Instrument."""
4
+
5
+ from apsbits.utils.logging_setup import configure_logging
6
+
7
+ configure_logging()
8
+
9
+ __package__ = "apsbits"
10
+ try:
11
+ from setuptools_scm import get_version
12
+
13
+ __version__ = get_version(root="..", relative_to=__file__)
14
+ del get_version
15
+ except (LookupError, ModuleNotFoundError):
16
+ from importlib.metadata import version
17
+
18
+ __version__ = version(__package__)
apsbits/_version.py ADDED
@@ -0,0 +1,21 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
6
+ TYPE_CHECKING = False
7
+ if TYPE_CHECKING:
8
+ from typing import Tuple
9
+ from typing import Union
10
+
11
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
12
+ else:
13
+ VERSION_TUPLE = object
14
+
15
+ version: str
16
+ __version__: str
17
+ __version_tuple__: VERSION_TUPLE
18
+ version_tuple: VERSION_TUPLE
19
+
20
+ __version__ = version = '1.0.0'
21
+ __version_tuple__ = version_tuple = (1, 0, 0)
@@ -0,0 +1,11 @@
1
+ """
2
+ Utility support to start bluesky sessions.
3
+
4
+ Also contains setup code that MUST run before other code in this directory.
5
+ """
6
+
7
+ from apsbits.utils.helper_functions import debug_python
8
+ from apsbits.utils.helper_functions import mpl_setup
9
+
10
+ debug_python()
11
+ mpl_setup()
@@ -0,0 +1,51 @@
1
+ """
2
+ BestEffortCallback: simple real-time visualizations, provides ``bec``.
3
+ ======================================================================
4
+
5
+ .. autosummary::
6
+ ~init_bec_peaks
7
+ """
8
+
9
+ import logging
10
+
11
+ from bluesky.callbacks.best_effort import BestEffortCallback
12
+
13
+ from apsbits.utils.helper_functions import running_in_queueserver
14
+
15
+ logger = logging.getLogger(__name__)
16
+ logger.bsdev(__file__)
17
+
18
+
19
+ def init_bec_peaks(iconfig):
20
+ """
21
+ Create and configure a BestEffortCallback object based on the provided iconfig.
22
+
23
+ Parameters:
24
+ iconfig (dict): Configuration dictionary.
25
+
26
+ Returns:
27
+ tuple: A tuple containing the configured BestEffortCallback object (bec)
28
+ and its peaks dictionary.
29
+ """
30
+
31
+ bec = BestEffortCallback()
32
+ """BestEffortCallback object, creates live tables and plots."""
33
+
34
+ bec_config = iconfig.get("BEC", {})
35
+
36
+ if not bec_config.get("BASELINE", True):
37
+ bec.disable_baseline()
38
+
39
+ if not bec_config.get("HEADING", True):
40
+ bec.disable_heading()
41
+
42
+ if not bec_config.get("PLOTS", True) or running_in_queueserver():
43
+ bec.disable_plots()
44
+
45
+ if not bec_config.get("TABLE", True):
46
+ bec.disable_table()
47
+
48
+ peaks = bec.peaks
49
+ """Dictionary with statistical analysis of LivePlots."""
50
+
51
+ return bec, peaks
@@ -0,0 +1,36 @@
1
+ """
2
+ Databroker catalog, provides ``cat``
3
+ ====================================
4
+
5
+ .. autosummary::
6
+ ~cat
7
+ """
8
+
9
+ import logging
10
+
11
+ import databroker
12
+
13
+ logger = logging.getLogger(__name__)
14
+ logger.bsdev(__file__)
15
+
16
+ TEMPORARY_CATALOG_NAME = "temporalcat"
17
+
18
+
19
+ def init_catalog(iconfig):
20
+ """
21
+ Initialize the Databroker catalog using the provided iconfig.
22
+
23
+ Parameters:
24
+ iconfig: Configuration object to retrieve catalog name.
25
+
26
+ Returns:
27
+ Databroker catalog object.
28
+ """
29
+ catalog_name = iconfig.get("DATABROKER_CATALOG", TEMPORARY_CATALOG_NAME)
30
+ try:
31
+ _cat = databroker.catalog[catalog_name].v2
32
+ except KeyError:
33
+ _cat = databroker.temp().v2
34
+
35
+ logger.info("Databroker catalog name: %s", _cat.name)
36
+ return _cat
@@ -0,0 +1,118 @@
1
+ """
2
+ Setup the Bluesky RunEngine, provides ``RE`` and ``sd``.
3
+ ========================================================
4
+
5
+ .. autosummary::
6
+ ~init_RE
7
+ """
8
+
9
+ import logging
10
+
11
+ import bluesky
12
+ from bluesky.utils import ProgressBarManager
13
+
14
+ from apsbits.utils.controls_setup import connect_scan_id_pv
15
+ from apsbits.utils.controls_setup import set_control_layer
16
+ from apsbits.utils.controls_setup import set_timeouts
17
+ from apsbits.utils.metadata import get_md_path
18
+ from apsbits.utils.metadata import re_metadata
19
+ from apsbits.utils.stored_dict import StoredDict
20
+
21
+ logger = logging.getLogger(__name__)
22
+ logger.bsdev(__file__)
23
+
24
+
25
+ def init_RE(iconfig, bec_instance=None, cat_instance=None):
26
+ """
27
+ Initialize and configure a bluesky RunEngine (RE) instance.
28
+
29
+ This function sets up the RunEngine with metadata storage, subscriptions,
30
+ preprocessors, and other configurations based on the provided input
31
+ parameters and configuration dictionary.
32
+
33
+ Args:
34
+ iconfig (dict): Configuration dictionary containing settings for the
35
+ RunEngine. Expected keys include:
36
+ - "RUN_ENGINE": A dictionary with RunEngine-specific settings.
37
+ - "MD_STORAGE_HANDLER": (Optional) The handler for metadata storage
38
+ (default is "StoredDict").
39
+ - "DEFAULT_METADATA": (Optional) Default metadata to be added to
40
+ the RunEngine.
41
+ - "USE_PROGRESS_BAR": (Optional) Boolean to enable/disable the
42
+ progress bar (default is True).
43
+ bec_instance (object, optional): An instance of BestEffortCallback (BEC)
44
+ for subscribing to the RunEngine. Defaults to `bec`.
45
+ cat_instance (object, optional): An instance of a databroker catalog
46
+ for subscribing to the RunEngine. Defaults to `cat`.
47
+
48
+ Returns:
49
+ tuple: A tuple containing the configured RunEngine instance and the
50
+ SupplementalData instance.
51
+
52
+ Raises:
53
+ Exception: If there is an error creating the metadata storage handler.
54
+
55
+ Notes:
56
+ - The function ensures that the RE.md dictionary is saved/restored
57
+ using the specified metadata storage handler.
58
+ - Subscriptions to the catalog and BEC are added if the respective
59
+ instances are provided.
60
+ - Additional configurations such as control layer setup, timeouts,
61
+ and progress bar are applied.
62
+ """
63
+ re_config = iconfig.get("RUN_ENGINE", {})
64
+
65
+ RE = bluesky.RunEngine()
66
+ """The bluesky RunEngine object."""
67
+
68
+ MD_PATH = get_md_path(iconfig)
69
+ # Save/restore RE.md dictionary, in this precise order.
70
+ if MD_PATH is not None:
71
+ handler_name = re_config.get("MD_STORAGE_HANDLER", "StoredDict")
72
+ logger.debug(
73
+ "Select %r to store 'RE.md' dictionary in %s.",
74
+ handler_name,
75
+ MD_PATH,
76
+ )
77
+ try:
78
+ if handler_name == "PersistentDict":
79
+ RE.md = bluesky.utils.PersistentDict(MD_PATH)
80
+ else:
81
+ RE.md = StoredDict(MD_PATH)
82
+ except Exception as error:
83
+ print(
84
+ "\n"
85
+ f"Could not create {handler_name} for RE metadata. Continuing"
86
+ f" without saving metadata to disk. {error=}\n"
87
+ )
88
+ logger.warning("%s('%s') error:%s", handler_name, MD_PATH, error)
89
+
90
+ if cat_instance is not None:
91
+ RE.md.update(re_metadata(iconfig, cat_instance)) # programmatic metadata
92
+ RE.md.update(re_config.get("DEFAULT_METADATA", {}))
93
+
94
+ sd = bluesky.SupplementalData()
95
+ """Baselines & monitors for ``RE``."""
96
+
97
+ if cat_instance is not None:
98
+ RE.subscribe(cat_instance.v1.insert)
99
+ if bec_instance is not None:
100
+ RE.subscribe(bec_instance)
101
+ RE.preprocessors.append(sd)
102
+
103
+ set_control_layer(
104
+ control_layer=iconfig.get("OPHYD", {}).get("CONTROL_LAYER", "PyEpics")
105
+ )
106
+ # MUST happen before ANY EpicsSignalBase (or subclass) is created.
107
+ set_timeouts(timeouts=iconfig.get("OPHYD", {}).get("TIMEOUTS", {}))
108
+ connect_scan_id_pv(
109
+ RE,
110
+ scan_id_pv=iconfig.get("RUN_ENGINE", {}).get("SCAN_ID_PV"),
111
+ ) # need to add the variables I removed from iconfig here as args
112
+
113
+ if re_config.get("USE_PROGRESS_BAR", True):
114
+ # Add a progress bar.
115
+ pbar_manager = ProgressBarManager()
116
+ RE.waiting_hook = pbar_manager
117
+
118
+ return RE, sd
@@ -0,0 +1 @@
1
+ ## Demo Instrument
@@ -0,0 +1,22 @@
1
+ """
2
+ Demo instrument package.
3
+
4
+ This package provides a demo instrument implementation for testing and development.
5
+ """
6
+
7
+ import logging
8
+ from pathlib import Path
9
+
10
+ from apsbits.utils.config_loaders import load_config
11
+
12
+ logger = logging.getLogger(__name__)
13
+ logger.bsdev(__file__)
14
+
15
+ # Get the path to the instrument package
16
+ instrument_path = Path(__file__).parent
17
+
18
+ # Load configuration
19
+ iconfig_path = instrument_path / "configs" / "iconfig.yml"
20
+ load_config(iconfig_path)
21
+
22
+ logger.info("Starting Instrument with iconfig: %s", iconfig_path)
@@ -0,0 +1 @@
1
+ """RunEngine callbacks, mostly."""
@@ -0,0 +1,58 @@
1
+ """
2
+ Nexus data file writer callback.
3
+
4
+ This module provides callbacks for writing data to Nexus data files.
5
+ """
6
+
7
+ import logging
8
+
9
+ from apsbits.utils.aps_functions import host_on_aps_subnet
10
+ from apsbits.utils.config_loaders import get_config
11
+
12
+ logger = logging.getLogger(__name__)
13
+ logger.bsdev(__file__)
14
+
15
+ # Get the configuration
16
+ iconfig = get_config()
17
+
18
+
19
+ if host_on_aps_subnet():
20
+ from apstools.callbacks import NXWriterAPS as NXWriter
21
+ else:
22
+ from apstools.callbacks import NXWriter
23
+
24
+
25
+ class MyNXWriter(NXWriter):
26
+ """Patch to get sample title from metadata, if available."""
27
+
28
+ def get_sample_title(self):
29
+ """
30
+ Get the title from the metadata or modify the default.
31
+
32
+ default title: S{scan_id}-{plan_name}-{short_uid}
33
+ """
34
+ try:
35
+ title = self.metadata["title"]
36
+ except KeyError:
37
+ # title = super().get_sample_title() # the default title
38
+ title = f"S{self.scan_id:05d}-{self.plan_name}-{self.uid[:7]}"
39
+ return title
40
+
41
+
42
+ def nxwriter_init(RE):
43
+ """Initialize the Nexus data file writer callback."""
44
+ nxwriter = MyNXWriter() # create the callback instance
45
+ """The NeXus file writer object."""
46
+
47
+ if iconfig.get("NEXUS_DATA_FILES", {}).get("ENABLE", False):
48
+ RE.subscribe(nxwriter.receiver) # write data to NeXus files
49
+
50
+ nxwriter.file_extension = iconfig.get("NEXUS_DATA_FILES", {}).get(
51
+ "FILE_EXTENSION", "hdf"
52
+ )
53
+
54
+ print(nxwriter.file_extension)
55
+ warn_missing = iconfig.get("NEXUS_DATA_FILES", {}).get("WARN_MISSING", False)
56
+ nxwriter.warn_on_missing_content = warn_missing
57
+
58
+ return nxwriter
@@ -0,0 +1,97 @@
1
+ """
2
+ custom callbacks
3
+ ================
4
+
5
+ .. autosummary::
6
+ :nosignatures:
7
+
8
+ ~newSpecFile
9
+ ~spec_comment
10
+ ~specwriter
11
+ """
12
+
13
+ import datetime
14
+ import logging
15
+ import pathlib
16
+
17
+ import apstools.callbacks
18
+ import apstools.utils
19
+
20
+ from apsbits.utils.config_loaders import get_config
21
+
22
+ logger = logging.getLogger(__name__)
23
+ logger.bsdev(__file__)
24
+
25
+ iconfig = get_config()
26
+ file_extension = iconfig.get("SPEC_DATA_FILES", {}).get("FILE_EXTENSION", "dat")
27
+
28
+
29
+ def spec_comment(comment, doc=None):
30
+ """Make it easy for user to add comments to the data file."""
31
+ apstools.callbacks.spec_comment(comment, doc, specwriter)
32
+
33
+
34
+ def newSpecFile(title, scan_id=None, RE=None):
35
+ """
36
+ User choice of the SPEC file name.
37
+
38
+ Cleans up title, prepends month and day and appends file extension.
39
+ If ``RE`` is passed, then resets ``RE.md["scan_id"] = scan_id``.
40
+
41
+ If the SPEC file already exists, then ``scan_id`` is ignored and
42
+ ``RE.md["scan_id"]`` is set to the last scan number in the file.
43
+ """
44
+ kwargs = {}
45
+ if RE is not None:
46
+ kwargs["RE"] = RE
47
+
48
+ mmdd = str(datetime.datetime.now()).split()[0][5:].replace("-", "_")
49
+ clean = apstools.utils.cleanupText(title)
50
+ fname = pathlib.Path(f"{mmdd}_{clean}.{file_extension}")
51
+ if fname.exists():
52
+ logger.warning(f">>> file already exists: {fname} <<<")
53
+ handled = "appended"
54
+ else:
55
+ kwargs["scan_id"] = scan_id or 1
56
+ handled = "created"
57
+
58
+ specwriter.newfile(fname, **kwargs)
59
+
60
+ logger.info(f"SPEC file name : {specwriter.spec_filename}")
61
+ logger.info(f"File will be {handled} at end of next bluesky scan.")
62
+
63
+
64
+ # Add this function to specwriter.py
65
+ def init_specwriter_with_RE(RE):
66
+ """Initialize specwriter with the run engine."""
67
+
68
+ # make the SPEC file in current working directory (assumes is writable)
69
+ specwriter.newfile(specwriter.spec_filename)
70
+
71
+ if iconfig.get("SPEC_DATA_FILES", {}).get("ENABLE", False):
72
+ RE.subscribe(specwriter.receiver) # write data to SPEC files
73
+ logger.info("SPEC data file: %s", specwriter.spec_filename.resolve())
74
+
75
+ try:
76
+ # feature new in apstools 1.6.14
77
+ from apstools.plans import label_stream_wrapper
78
+
79
+ def motor_start_preprocessor(plan):
80
+ """Record motor positions at start of each run."""
81
+ return label_stream_wrapper(plan, "motor", when="start")
82
+
83
+ RE.preprocessors.append(motor_start_preprocessor)
84
+ except Exception:
85
+ logger.warning("Could load support to log motors positions.")
86
+
87
+
88
+ # write scans to SPEC data file
89
+ try:
90
+ # apstools >=1.6.21
91
+ _specwriter = apstools.callbacks.SpecWriterCallback2()
92
+ except AttributeError:
93
+ # apstools <1.6.21
94
+ _specwriter = apstools.callbacks.SpecWriterCallback()
95
+
96
+ specwriter = _specwriter
97
+ """The SPEC file writer object."""
@@ -0,0 +1 @@
1
+ """Configs required to set up user package"""
@@ -0,0 +1,52 @@
1
+ # Guarneri-style device YAML configuration
2
+
3
+ apsbits.utils.sim_creator.predefined_device:
4
+ - {creator: ophyd.sim.motor, name: sim_motor}
5
+ - {creator: ophyd.sim.noisy_det, name: sim_det}
6
+
7
+ apstools.devices.SimulatedApsPssShutterWithStatus:
8
+ - name: shutter
9
+ labels: ["shutters"]
10
+
11
+ # ophyd.Signal:
12
+ # - name: test
13
+ # value: 50.7
14
+ # - name: t2
15
+ # value: 2
16
+
17
+ # apstools.synApps.Optics2Slit2D_HV:
18
+ # - name: slit1
19
+ # prefix: ioc:Slit1
20
+ # labels: ["slits"]
21
+
22
+ # hkl.SimulatedE4CV:
23
+ # - name: sim4c
24
+ # prefix: ""
25
+ # labels: ["diffractometer"]
26
+
27
+ # ophyd.scaler.ScalerCH:
28
+ # - name: scaler1
29
+ # prefix: vme:scaler1
30
+ # labels: ["scalers", "detectors"]
31
+
32
+ # ophyd.EpicsMotor:
33
+ # - {name: m1, prefix: gp:m1, labels: ["motor"]}
34
+ # - {name: m2, prefix: gp:m2, labels: ["motor"]}
35
+ # - {name: m3, prefix: gp:m3, labels: ["motor"]}
36
+ # - {name: m4, prefix: gp:m4, labels: ["motor"]}
37
+
38
+ # apstools.devices.ad_creator:
39
+ # - name: adsimdet
40
+ # prefix: "ad:"
41
+ # labels: ["area_detector", "detectors"]
42
+ # plugins:
43
+ # - cam:
44
+ # class: apstools.devices.SimDetectorCam_V34
45
+ # - image
46
+ # - pva
47
+ # - hdf1:
48
+ # class: apstools.devices.AD_EpicsFileNameHDF5Plugin
49
+ # read_path_template: "/path/to/bluesky/tmp/"
50
+ # write_path_template: "/path/to/ioc/tmp/"
51
+ # - roi1
52
+ # - stats1
@@ -0,0 +1,6 @@
1
+ # Guarneri-style device YAML configuration
2
+
3
+ # Objects only available at APS
4
+
5
+ apstools.devices.ApsMachineParametersDevice:
6
+ - name: aps
@@ -0,0 +1,82 @@
1
+ # Configuration for the Bluesky instrument package.
2
+
3
+ # identify the version of this iconfig.yml file
4
+ ICONFIG_VERSION: 2.0.0
5
+
6
+ # Add additional configuration for use with your instrument.
7
+
8
+ ### The short name for the databroker catalog.
9
+ DATABROKER_CATALOG: &databroker_catalog temp
10
+
11
+ ### RunEngine configuration
12
+ RUN_ENGINE:
13
+ DEFAULT_METADATA:
14
+ beamline_id: demo_instrument
15
+ instrument_name: Most Glorious Scientific Instrument
16
+ proposal_id: commissioning
17
+ databroker_catalog: *databroker_catalog
18
+
19
+ ### EPICS PV to use for the `scan_id`.
20
+ ### Default: `RE.md["scan_id"]` (not using an EPICS PV)
21
+ # SCAN_ID_PV: "IOC:bluesky_scan_id"
22
+
23
+ ### Where to "autosave" the RE.md dictionary.
24
+ ### Defaults:
25
+ MD_STORAGE_HANDLER: StoredDict
26
+ MD_PATH: .re_md_dict.yml
27
+
28
+ ### The progress bar is nice to see,
29
+ ### except when it clutters the output in Jupyter notebooks.
30
+ ### Default: False
31
+ USE_PROGRESS_BAR: false
32
+
33
+ # Command-line tools, such as %wa, %ct, ...
34
+ USE_BLUESKY_MAGICS: true
35
+
36
+ ### Best Effort Callback Configurations
37
+ ### Defaults: all true
38
+ ### except no plots in queueserver
39
+ BEC:
40
+ BASELINE: true
41
+ HEADING: true
42
+ PLOTS: false
43
+ TABLE: true
44
+
45
+ ### Support for known output file formats.
46
+ ### Uncomment to use. If undefined, will not write that type of file.
47
+ ### Each callback should apply its configuration from here.
48
+ NEXUS_DATA_FILES:
49
+ ENABLE: false
50
+ FILE_EXTENSION: hdf
51
+
52
+ SPEC_DATA_FILES:
53
+ ENABLE: true
54
+ FILE_EXTENSION: dat
55
+
56
+ ### APS Data Management
57
+ ### Use bash shell, deactivate all conda environments, source this file:
58
+ DM_SETUP_FILE: "/home/dm/etc/dm.setup.sh"
59
+
60
+ ### Local OPHYD Device Control Yaml
61
+ DEVICES_FILES:
62
+ - devices.yml
63
+ APS_DEVICES_FILES:
64
+ - devices_aps_only.yml
65
+
66
+ # ----------------------------------
67
+
68
+ OPHYD:
69
+ ### Control layer for ophyd to communicate with EPICS.
70
+ ### Default: PyEpics
71
+ ### Choices: "PyEpics" or "caproto" # caproto is not yet supported
72
+ CONTROL_LAYER: PyEpics
73
+
74
+ ### default timeouts (seconds)
75
+ TIMEOUTS:
76
+ PV_READ: &TIMEOUT 5
77
+ PV_WRITE: *TIMEOUT
78
+ PV_CONNECTION: *TIMEOUT
79
+
80
+ # Control detail of exception traces in IPython (console and notebook).
81
+ # Options are: Minimal, Plain, Verbose
82
+ XMODE_DEBUG_LEVEL: Plain
@@ -0,0 +1,41 @@
1
+ # Bluesky Session Logging Configuration
2
+
3
+ console_logs:
4
+ date_format: "%a-%H:%M:%S"
5
+ log_format: "%(levelname)-.1s %(asctime)s.%(msecs)03d: %(message)s"
6
+ level: info
7
+ root_level: bsdev
8
+
9
+ file_logs:
10
+ date_format: "%Y-%m-%d %H:%M:%S"
11
+ log_directory: .logs
12
+ log_filename_base: logging.log
13
+ log_format: "|\
14
+ %(asctime)s.%(msecs)03d|\
15
+ %(levelname)s|\
16
+ %(process)d|\
17
+ %(name)s|\
18
+ %(module)s|\
19
+ %(lineno)d|\
20
+ %(threadName)s| - \
21
+ %(message)s"
22
+ maxBytes: 1_000_000
23
+ backupCount: 9
24
+ level: info
25
+ rotate_on_startup: true
26
+
27
+ ipython_logs:
28
+ log_directory: .logs
29
+ log_filename_base: ipython_log.py
30
+ log_mode: rotate
31
+ options: -o -t
32
+
33
+ modules:
34
+ apstools: warning
35
+ bluesky-queueserver: warning
36
+ bluesky: warning
37
+ bluesky.RE: warning
38
+ caproto: warning
39
+ databroker: warning
40
+ instrument: bsdev
41
+ ophyd: warning
@@ -0,0 +1 @@
1
+ """Ophyd-style devices."""
@@ -0,0 +1,8 @@
1
+ """Bluesky plans."""
2
+
3
+ from .dm_plans import dm_kickoff_workflow # noqa: F401
4
+ from .dm_plans import dm_list_processing_jobs # noqa: F401
5
+ from .dm_plans import dm_submit_workflow_job # noqa: F401
6
+ from .sim_plans import sim_count_plan # noqa: F401
7
+ from .sim_plans import sim_print_plan # noqa: F401
8
+ from .sim_plans import sim_rel_scan_plan # noqa: F401