Coverage for nexusLIMS/__init__.py: 100%
18 statements
« prev ^ index » next coverage.py v7.11.3, created at 2026-03-24 05:23 +0000
« prev ^ index » next coverage.py v7.11.3, created at 2026-03-24 05:23 +0000
1r"""The NexusLIMS back-end software.
3This module contains the software required to monitor a database for sessions
4logged by users on electron microscopy instruments. Based off this information,
5records representing individual experiments are automatically generated and
6uploaded to the front-end NexusLIMS CDCS instance for users to browse, query,
7and edit.
9Example
10-------
11In most cases, the only code that needs to be run directly is initiating the
12record builder to look for new sessions, which can be done by running the
13:py:mod:`~nexusLIMS.builder.record_builder` module directly:
15```bash
16$ python -m nexusLIMS.builder.record_builder
17```
19Refer to :ref:`record-building` for more details.
21**Configuration variables**
23The following variables should be defined as environment variables in your
24session, or in the ``.env`` file in the root of this package's repository.
25See the ``.env.example`` file for more documentation and examples.
27(NexusLIMS-file-strategy)=
29`NX_FILE_STRATEGY`
30 Defines the strategy used to find files associated with experimental records.
31 A value of ``exclusive`` will `only` add files for which NexusLIMS knows how
32 to generate preview images and extract metadata. A value of ``inclusive``
33 will include all files found, even if preview generation/detailed metadata
34 extraction is not possible.
36(NexusLIMS-ignore-patterns)=
38`NX_IGNORE_PATTERNS`
39 The patterns defined in this variable (which should be provided as a
40 JSON-formatted string) will be ignored when finding files. A default value
41 is provided in the ``.env.example`` file that should work for most users,
42 but this setting allows for further customization of the file-finding routine.
44(nexuslims-cdcs-token)=
46`NX_CDCS_TOKEN`
47 API token used to authenticate to CDCS API
49(nexuslims-cdcs-url)=
51`NX_CDCS_URL`
52 The root URL of the NexusLIMS CDCS front-end. This will be the target for
53 record uploads that are authenticated using the CDCS token.
55(nexuslims-instrument-data-path)=
57`NX_INSTRUMENT_DATA_PATH`
58 The path (should be already mounted) to the root folder containing data
59 from the Electron Microscopy Nexus. This folder is accessible read-only,
60 and it is where data is written to by instruments in the Electron
61 Microscopy Nexus. The file paths for specific instruments (specified in
62 the NexusLIMS database) are relative to this root.
64(nexuslims-data-path)=
66`NX_DATA_PATH`
67 The root path used by NexusLIMS for various needs. This folder is used to
68 store the NexusLIMS database, generated records, individual file metadata
69 dumps and preview images, and anything else that is needed by the back-end
70 system.
72(nexuslims-db-path)=
74`NX_DB_PATH`
75 The direct path to the NexusLIMS SQLite database file that contains
76 information about the instruments in the Nexus Facility, as well as logs
77 for the sessions created by users using the Session Logger Application.
79(nexuslims-log-path)=
81`NX_LOG_PATH`
82 Directory for application logs. If not specified, defaults to
83 ``${NX_DATA_PATH}/logs/``. Logs are organized by date: ``logs/YYYY/MM/DD/``
85(nexuslims-records-path)=
87`NX_RECORDS_PATH`
88 Directory for generated XML records. If not specified, defaults to
89 ``${NX_DATA_PATH}/records/``. Successfully uploaded records are moved to
90 an 'uploaded' subdirectory upon upload.
92(nexuslims-cert-bundle-file)=
94`NX_CERT_BUNDLE_FILE`
95 If needed, a custom SSL certificate CA bundle can be used to verify
96 requests to the CDCS or NEMO APIs. Provide this value with the full
97 path to a certificate bundle and any certificates provided in the
98 bundle will be appended to the existing system for all requests made
99 by NexusLIMS.
101(nexuslims-cert-bundle)=
103`NX_CERT_BUNDLE`
104 As an alternative to ``NX_CERT_BUNDLE_FILE``, you can provide the entire
105 certificate bundle as a single string (this can be useful for CI/CD
106 pipelines). Lines should be separated by a single ``\n`` character. If
107 defined, this value will take precedence over ``NX_CERT_BUNDLE_FILE``.
109(nexuslims-file-delay-days)=
111`NX_FILE_DELAY_DAYS`
112 Controls the maximum delay between observing a session ending and when
113 the files are expected to be present. For the number of days set (can be
114 a fraction of a day, if desired), record building will not fail if no
115 files are found, and the builder will search again until the delay has
116 passed. For example, if the value is ``2``, and a session ended Monday
117 at 5PM, the record builder will continue to try looking for files until
118 Wednesday at 5PM. Default is ``2.0`` days.
120(nexuslims-local-profiles-path)=
122`NX_LOCAL_PROFILES_PATH`
123 Directory for site-specific instrument profiles. These profiles customize
124 metadata extraction for instruments unique to your deployment without
125 modifying the core NexusLIMS codebase. Profile files should be Python
126 modules that register ``InstrumentProfile`` objects. If not specified,
127 only built-in profiles will be loaded.
129(nemo-address)=
131`NX_NEMO_ADDRESS_X`
132 The path to a NEMO instance's API endpoint. Should be something like
133 ``https://www.nemo.com/api/`` (make sure to include the trailing slash).
134 The value ``_X`` can be replaced with any value (such as
135 ``NX_NEMO_ADDRESS_1``). NexusLIMS supports having multiple NEMO reservation
136 systems enabled at once (useful if your instruments are split over a few
137 different management systems). To enable this behavior, create multiple
138 pairs of environment variables for each instance, where the suffix ``_X``
139 changes for each pair (`e.g.` you could have ``NX_NEMO_ADDRESS_1`` paired with
140 ``NX_NEMO_TOKEN_1``, ``NX_NEMO_ADDRESS_2`` paired with ``NX_NEMO_TOKEN_2``, etc.).
142(nemo-token)=
144`NX_NEMO_TOKEN_X`
145 An API authentication token from the corresponding NEMO installation
146 (specified in ``NX_NEMO_ADDRESS_X``) that
147 will be used to authorize requests to the NEMO API. This token can be
148 obtained by visiting the "Detailed Administration" page in the NEMO
149 instance, and then creating a new token under the "Tokens" menu. Note that
150 this token will authenticate as a particular user, so you may wish to set
151 up a "dummy" or "functional" user account in the NEMO instance for these
152 operations.
154(nemo-strftime-fmt)=
155(nemo-strptime-fmt)=
157`NX_NEMO_STRFTIME_FMT_X` and `NX_NEMO_STRPTIME_FMT_X`
158 These options are optional, and control how dates/times are sent to
159 (`strftime`) and interpreted from (`strptime`) the API. If "`strftime_fmt`"
160 and/or "`strptime_fmt`" are not provided, the standard ISO 8601 format
161 for datetime representation will be used (which should work with the
162 default NEMO settings). These options are configurable to allow for
163 support of non-default date format settings on a NEMO server. The formats
164 should be provided using the standard datetime library syntax for
165 encoding date and time information (see :ref:`strftime-strptime-behavior`
166 for details).
168(nemo-tz)=
170`NX_NEMO_TZ_X`
171 Also optional; If the "`tz`" option is provided, the datetime
172 strings received from the NEMO API will be coerced into the given timezone.
173 The timezone should be specified using the IANA "tz database" name (see
174 https://en.wikipedia.org/wiki/List_of_tz_database_time_zones). This option
175 should not be supplied for NEMO servers that return time zone information in
176 their API response, since it will override the timezone of the returned
177 data. It is mostly useful for servers that return reservation/usage event
178 times without any timezone information. Providing it helps properly map
179 file creation times to usage event times.
181(email-smtp-host)=
183`NX_EMAIL_SMTP_HOST`
184 SMTP server hostname for sending email notifications from the
185 ``nexuslims build-records`` script (e.g., ``smtp.gmail.com``).
186 Required for email notifications.
188(email-smtp-port)=
190`NX_EMAIL_SMTP_PORT`
191 SMTP server port. Default is ``587`` for STARTTLS.
193(email-smtp-username)=
195`NX_EMAIL_SMTP_USERNAME`
196 SMTP username for authentication (if required by your SMTP server).
198(email-smtp-password)=
200`NX_EMAIL_SMTP_PASSWORD`
201 SMTP password for authentication (if required by your SMTP server).
203(email-use-tls)=
205`NX_EMAIL_USE_TLS`
206 Use TLS encryption for SMTP connection. Default is ``true``.
208(email-sender)=
210`NX_EMAIL_SENDER`
211 Email address to send notifications from. Required for email notifications.
213(email-recipients)=
215`NX_EMAIL_RECIPIENTS`
216 Comma-separated list of recipient email addresses for error notifications
217 (e.g., ``admin@example.com,team@example.com``). Required for email notifications.
218"""
220# pylint: disable=invalid-name
222import logging
224# Defer heavy imports to reduce CLI startup time
225# These will be imported on-demand when accessing the attributes
226from .version import __version__
229def __getattr__(name):
230 """Lazy import submodules to speed up CLI startup."""
231 if name in ("builder", "db", "extractors", "instruments", "utils"):
232 import importlib # noqa: PLC0415
234 module = importlib.import_module(f".{name}", __package__)
235 globals()[name] = module
236 return module
237 msg = f"module {__name__!r} has no attribute {name!r}"
238 raise AttributeError(msg)
241def __dir__():
242 """Support for dir() to show lazy-loaded attributes."""
243 return ["__version__", "builder", "db", "extractors", "instruments", "utils"]
246def _filter_hyperspy_messages(record): # pragma: no cover
247 """Filter HyperSpy API import warnings within the NexusLIMS codebase."""
248 # this only triggers if the hs.preferences.GUIs.warn_if_guis_are_missing
249 # preference is set to True
250 return not (
251 record.msg.startswith("The ipywidgets GUI")
252 or record.msg.startswith(
253 "The traitsui GUI",
254 )
255 )
258# connect the filter function to the HyperSpy logger
259logging.getLogger("hyperspy.api").addFilter(_filter_hyperspy_messages)
261# tweak some logger levels
262logging.getLogger("matplotlib.font_manager").disabled = True
263logging.getLogger("matplotlib").setLevel(logging.WARNING)
264logging.getLogger("PIL.PngImagePlugin").setLevel(logging.WARNING)
266# set log message format
267logging.basicConfig(format="%(asctime)s %(name)s %(levelname)s: %(message)s")
269__all__ = ["__version__", "builder", "db", "extractors", "instruments", "utils"]