Initial commit
This commit is contained in:
586
dist/dicom2pacs.app/Contents/Resources/lib/python3.13/pydicom/config.py
vendored
Executable file
586
dist/dicom2pacs.app/Contents/Resources/lib/python3.13/pydicom/config.py
vendored
Executable file
@@ -0,0 +1,586 @@
|
||||
# Copyright 2008-2023 pydicom authors. See LICENSE file for details.
|
||||
"""Pydicom configuration options."""
|
||||
|
||||
# doc strings following items are picked up by sphinx for documentation
|
||||
|
||||
import logging
|
||||
import os
|
||||
from contextlib import contextmanager
|
||||
from typing import Optional, Any, TYPE_CHECKING
|
||||
from collections.abc import Generator
|
||||
|
||||
have_numpy = True
|
||||
try:
|
||||
import numpy # noqa: F401
|
||||
except ImportError:
|
||||
have_numpy = False
|
||||
|
||||
if TYPE_CHECKING: # pragma: no cover
|
||||
from pydicom.dataelem import RawDataElement
|
||||
from typing import Protocol
|
||||
|
||||
class ElementCallback(Protocol):
|
||||
def __call__(
|
||||
self,
|
||||
raw_elem: "RawDataElement",
|
||||
**kwargs: Any,
|
||||
) -> "RawDataElement": ...
|
||||
|
||||
|
||||
_use_future = False
|
||||
_use_future_env = os.getenv("PYDICOM_FUTURE")
|
||||
|
||||
|
||||
# Logging system and debug function to change logging level
|
||||
logger = logging.getLogger("pydicom")
|
||||
logger.addHandler(logging.NullHandler())
|
||||
|
||||
debugging: bool
|
||||
|
||||
|
||||
def debug(debug_on: bool = True, default_handler: bool = True) -> None:
|
||||
"""Turn on/off debugging of DICOM file reading and writing.
|
||||
|
||||
When debugging is on, file location and details about the elements read at
|
||||
that location are logged to the 'pydicom' logger using Python's
|
||||
:mod:`logging`
|
||||
module.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
debug_on : bool, optional
|
||||
If ``True`` (default) then turn on debugging, ``False`` to turn off.
|
||||
default_handler : bool, optional
|
||||
If ``True`` (default) then use :class:`logging.StreamHandler` as the
|
||||
handler for log messages.
|
||||
"""
|
||||
global logger, debugging
|
||||
|
||||
if default_handler:
|
||||
handler = logging.StreamHandler()
|
||||
formatter = logging.Formatter("%(message)s")
|
||||
handler.setFormatter(formatter)
|
||||
logger.addHandler(handler)
|
||||
|
||||
if debug_on:
|
||||
logger.setLevel(logging.DEBUG)
|
||||
debugging = True
|
||||
else:
|
||||
logger.setLevel(logging.WARNING)
|
||||
debugging = False
|
||||
|
||||
|
||||
# force level=WARNING, in case logging default is set differently (issue 103)
|
||||
debug(False, False)
|
||||
|
||||
|
||||
# Set the type used to hold DS values
|
||||
# default False; was decimal-based in pydicom 0.9.7
|
||||
use_DS_decimal: bool = False
|
||||
"""Set using :func:`DS_decimal` to control if elements with a
|
||||
VR of **DS** are represented as :class:`~decimal.Decimal`.
|
||||
|
||||
Default ``False``.
|
||||
"""
|
||||
|
||||
data_element_callback: Optional["ElementCallback"] = None
|
||||
"""Set to a callable function to be called from
|
||||
:func:`~pydicom.filereader.dcmread` every time a
|
||||
:class:`~pydicom.dataelem.RawDataElement` has been returned,
|
||||
before it is added to the :class:`~pydicom.dataset.Dataset`.
|
||||
|
||||
Default ``None``.
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
``data_element_callback`` will be removed in v4.0, use
|
||||
:meth:`~pydicom.hooks.Hooks.register_callback` instead.
|
||||
"""
|
||||
|
||||
data_element_callback_kwargs: dict[str, Any] = {}
|
||||
"""Set the keyword arguments passed to :func:`data_element_callback`.
|
||||
|
||||
Default ``{}``.
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
``data_element_callback_kwargs`` will be removed in v4.0, use
|
||||
:meth:`~pydicom.hooks.Hooks.register_kwargs` instead.
|
||||
"""
|
||||
|
||||
|
||||
def reset_data_element_callback() -> None:
|
||||
"""Reset the :func:`data_element_callback` function to the default.
|
||||
|
||||
.. deprecated:: 3.0
|
||||
|
||||
``reset_data_element_callback()`` will be removed in v4.0, use
|
||||
:meth:`pydicom.hooks.Hooks.reset` instead.
|
||||
"""
|
||||
global data_element_callback
|
||||
global data_element_callback_kwargs
|
||||
data_element_callback = None
|
||||
data_element_callback_kwargs = {}
|
||||
|
||||
|
||||
def DS_numpy(use_numpy: bool = True) -> None:
|
||||
"""Set whether multi-valued elements with VR of **DS** will be numpy arrays
|
||||
|
||||
.. versionadded:: 2.0
|
||||
|
||||
Parameters
|
||||
----------
|
||||
use_numpy : bool, optional
|
||||
``True`` (default) to read multi-value **DS** elements
|
||||
as :class:`~numpy.ndarray`, ``False`` to read multi-valued **DS**
|
||||
data elements as type :class:`~python.mulitval.MultiValue`
|
||||
|
||||
Note: once a value has been accessed, changing this setting will
|
||||
no longer change its type
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If :data:`use_DS_decimal` and `use_numpy` are both True.
|
||||
|
||||
"""
|
||||
|
||||
global use_DS_numpy
|
||||
|
||||
if use_DS_decimal and use_numpy:
|
||||
raise ValueError(
|
||||
"Cannot use numpy arrays to read DS elements if `use_DS_decimal` is True"
|
||||
)
|
||||
use_DS_numpy = use_numpy
|
||||
|
||||
|
||||
def DS_decimal(use_Decimal_boolean: bool = True) -> None:
|
||||
"""Set DS class to be derived from :class:`decimal.Decimal` or
|
||||
:class:`float`.
|
||||
|
||||
If this function is never called, the default in *pydicom* >= 0.9.8
|
||||
is for DS to be based on :class:`float`.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
use_Decimal_boolean : bool, optional
|
||||
``True`` (default) to derive :class:`~pydicom.valuerep.DS` from
|
||||
:class:`decimal.Decimal`, ``False`` to derive it from :class:`float`.
|
||||
|
||||
Raises
|
||||
------
|
||||
ValueError
|
||||
If `use_Decimal_boolean` and :data:`use_DS_numpy` are
|
||||
both ``True``.
|
||||
"""
|
||||
global use_DS_decimal
|
||||
|
||||
use_DS_decimal = use_Decimal_boolean
|
||||
|
||||
if use_DS_decimal and use_DS_numpy:
|
||||
raise ValueError("Cannot set use_DS_decimal True if use_DS_numpy is True")
|
||||
|
||||
import pydicom.valuerep
|
||||
|
||||
if use_DS_decimal:
|
||||
pydicom.valuerep.DSclass = pydicom.valuerep.DSdecimal
|
||||
else:
|
||||
pydicom.valuerep.DSclass = pydicom.valuerep.DSfloat
|
||||
|
||||
|
||||
# Configuration flags
|
||||
use_DS_numpy = False
|
||||
"""Set using the function :func:`DS_numpy` to control
|
||||
whether arrays of VR **DS** are returned as numpy arrays.
|
||||
Default: ``False``.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
|
||||
use_IS_numpy = False
|
||||
"""Set to False to avoid IS values being returned as numpy ndarray objects.
|
||||
Default: ``False``.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
|
||||
allow_DS_float = False
|
||||
"""Set to ``True`` to allow :class:`~pydicom.valuerep.DSdecimal`
|
||||
instances to be created using :class:`floats<float>`; otherwise, they must be
|
||||
explicitly converted to :class:`str`, with the user explicitly setting the
|
||||
precision of digits and rounding.
|
||||
|
||||
Default ``False``.
|
||||
"""
|
||||
|
||||
|
||||
enforce_valid_values = False
|
||||
"""Deprecated.
|
||||
Use :attr:`Settings.reading_validation_mode` instead.
|
||||
"""
|
||||
|
||||
|
||||
# Constants used to define how data element values shall be validated
|
||||
IGNORE = 0
|
||||
"""If one of the validation modes is set to this value, no value validation
|
||||
will be performed.
|
||||
"""
|
||||
|
||||
WARN = 1
|
||||
"""If one of the validation modes is set to this value, a warning is issued if
|
||||
a value validation error occurs.
|
||||
"""
|
||||
|
||||
RAISE = 2
|
||||
"""If one of the validation modes is set to this value, an exception is raised
|
||||
if a value validation error occurs.
|
||||
"""
|
||||
|
||||
|
||||
class Settings:
|
||||
"""Collection of several configuration values.
|
||||
Accessed via the singleton :attr:`settings`.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
self._reading_validation_mode: int | None = None
|
||||
# in future version, writing invalid values will raise by default,
|
||||
# currently the default value depends on enforce_valid_values
|
||||
self._writing_validation_mode: int | None = RAISE if _use_future else None
|
||||
self._infer_sq_for_un_vr: bool = True
|
||||
|
||||
# Chunk size to use when reading from buffered DataElement values
|
||||
self._buffered_read_size = 8192
|
||||
|
||||
@property
|
||||
def buffered_read_size(self) -> int:
|
||||
"""Get or set the chunk size when reading from buffered
|
||||
:class:`~pydicom.dataelem.DataElement` values.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
size : int
|
||||
The chunk size to use, must be greater than 0 (default 8192).
|
||||
"""
|
||||
return self._buffered_read_size
|
||||
|
||||
@buffered_read_size.setter
|
||||
def buffered_read_size(self, size: int) -> None:
|
||||
if size <= 0:
|
||||
raise ValueError("The read size must be greater than 0")
|
||||
|
||||
self._buffered_read_size = size
|
||||
|
||||
@property
|
||||
def reading_validation_mode(self) -> int:
|
||||
"""Defines behavior of validation while reading values, compared with
|
||||
the DICOM standard, e.g. that DS strings are not longer than
|
||||
16 characters and contain only allowed characters.
|
||||
|
||||
* :attr:`WARN` will emit a warning in the case of an invalid value (default)
|
||||
* :attr:`RAISE` will raise an error instead
|
||||
* :attr:`IGNORE` will bypass the validation (with the exception of some
|
||||
encoding errors).
|
||||
"""
|
||||
# upwards compatibility
|
||||
if self._reading_validation_mode is None:
|
||||
return RAISE if enforce_valid_values else WARN
|
||||
return self._reading_validation_mode
|
||||
|
||||
@reading_validation_mode.setter
|
||||
def reading_validation_mode(self, value: int) -> None:
|
||||
self._reading_validation_mode = value
|
||||
|
||||
@property
|
||||
def writing_validation_mode(self) -> int:
|
||||
"""Defines behavior for value validation while writing a value.
|
||||
See :attr:`Settings.reading_validation_mode`.
|
||||
"""
|
||||
if self._writing_validation_mode is None:
|
||||
return RAISE if enforce_valid_values else WARN
|
||||
return self._writing_validation_mode
|
||||
|
||||
@writing_validation_mode.setter
|
||||
def writing_validation_mode(self, value: int) -> None:
|
||||
self._writing_validation_mode = value
|
||||
|
||||
@property
|
||||
def infer_sq_for_un_vr(self) -> bool:
|
||||
"""If ``True``, and the VR of a known data element is encoded as
|
||||
**UN** in an explicit encoding for an undefined length data element,
|
||||
the VR is changed to SQ per PS 3.5, section 6.2.2. Can be set to
|
||||
``False`` where the content of the tag shown as **UN** is not DICOM
|
||||
conformant and would lead to a failure if accessing it.
|
||||
"""
|
||||
return self._infer_sq_for_un_vr
|
||||
|
||||
@infer_sq_for_un_vr.setter
|
||||
def infer_sq_for_un_vr(self, value: bool) -> None:
|
||||
self._infer_sq_for_un_vr = value
|
||||
|
||||
|
||||
settings = Settings()
|
||||
"""The global configuration object of type :class:`Settings` to access some
|
||||
of the settings. More settings may move here in later versions.
|
||||
|
||||
.. versionadded:: 2.3
|
||||
"""
|
||||
|
||||
|
||||
@contextmanager
|
||||
def disable_value_validation() -> Generator:
|
||||
"""Context manager to temporarily disable value validation
|
||||
both for reading and writing.
|
||||
Can be used for performance reasons if the values are known to be valid.
|
||||
"""
|
||||
reading_mode = settings._reading_validation_mode
|
||||
writing_mode = settings._writing_validation_mode
|
||||
try:
|
||||
settings.reading_validation_mode = IGNORE
|
||||
settings.writing_validation_mode = IGNORE
|
||||
yield
|
||||
finally:
|
||||
settings._reading_validation_mode = reading_mode
|
||||
settings._writing_validation_mode = writing_mode
|
||||
|
||||
|
||||
@contextmanager
|
||||
def strict_reading() -> Generator:
|
||||
"""Context manager to temporarily enably strict value validation
|
||||
for reading."""
|
||||
original_reading_mode = settings._reading_validation_mode
|
||||
try:
|
||||
settings.reading_validation_mode = RAISE
|
||||
yield
|
||||
finally:
|
||||
settings._reading_validation_mode = original_reading_mode
|
||||
|
||||
|
||||
convert_wrong_length_to_UN = False
|
||||
"""Convert a field VR to "UN" and return bytes if bytes length is invalid.
|
||||
Default ``False``.
|
||||
"""
|
||||
|
||||
datetime_conversion = False
|
||||
"""Set to ``True`` to convert the value(s) of elements with a VR of DA, DT and
|
||||
TM to :class:`datetime.date`, :class:`datetime.datetime` and
|
||||
:class:`datetime.time` respectively.
|
||||
Note that when datetime conversion is enabled then range matching in
|
||||
C-GET/C-FIND/C-MOVE queries is not possible anymore. So if you need range
|
||||
matching we recommend to do the conversion manually.
|
||||
|
||||
Default ``False``
|
||||
|
||||
References
|
||||
----------
|
||||
* :dcm:`Range Matching<part04/sect_C.2.2.2.5.html>`
|
||||
"""
|
||||
|
||||
use_none_as_empty_text_VR_value = False
|
||||
""" If ``True``, the value of a decoded empty data element with
|
||||
a text VR is ``None``, otherwise (the default), it is is an empty string.
|
||||
For all other VRs the behavior does not change - the value is en empty
|
||||
list for VR **SQ** and ``None`` for all other VRs.
|
||||
Note that the default of this value may change to ``True`` in a later version.
|
||||
"""
|
||||
|
||||
replace_un_with_known_vr = True
|
||||
""" If ``True``, and the VR of a known data element is encoded as **UN** in
|
||||
an explicit encoding, the VR is changed to the known value.
|
||||
Can be set to ``False`` where the content of the tag shown as **UN** is
|
||||
not DICOM conformant and would lead to a failure if accessing it.
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
|
||||
show_file_meta = True
|
||||
"""
|
||||
If ``True`` (default), the 'str' and 'repr' methods
|
||||
of :class:`~pydicom.dataset.Dataset` begin with a separate section
|
||||
displaying the file meta information data elements
|
||||
|
||||
.. versionadded:: 2.0
|
||||
"""
|
||||
|
||||
import pydicom.pixel_data_handlers.numpy_handler as np_handler # noqa
|
||||
import pydicom.pixel_data_handlers.rle_handler as rle_handler # noqa
|
||||
import pydicom.pixel_data_handlers.pillow_handler as pillow_handler # noqa
|
||||
import pydicom.pixel_data_handlers.jpeg_ls_handler as jpegls_handler # noqa
|
||||
import pydicom.pixel_data_handlers.gdcm_handler as gdcm_handler # noqa
|
||||
import pydicom.pixel_data_handlers.pylibjpeg_handler as pylibjpeg_handler # noqa
|
||||
|
||||
pixel_data_handlers = [
|
||||
np_handler,
|
||||
gdcm_handler,
|
||||
pillow_handler,
|
||||
jpegls_handler,
|
||||
pylibjpeg_handler,
|
||||
rle_handler,
|
||||
]
|
||||
"""Handlers for converting (7FE0,0010) *Pixel Data*.
|
||||
|
||||
.. currentmodule:: pydicom.dataset
|
||||
|
||||
This is an ordered list of *Pixel Data* handlers that the
|
||||
:meth:`~Dataset.convert_pixel_data` method will use to try to extract a
|
||||
correctly sized numpy array from the *Pixel Data* element.
|
||||
|
||||
Handlers shall have four methods:
|
||||
|
||||
def supports_transfer_syntax(transfer_syntax: UID)
|
||||
Return ``True`` if the handler supports the transfer syntax indicated in
|
||||
:class:`Dataset` `ds`, ``False`` otherwise.
|
||||
|
||||
def is_available():
|
||||
Return ``True`` if the handler's dependencies are installed, ``False``
|
||||
otherwise.
|
||||
|
||||
def get_pixeldata(ds):
|
||||
Return a correctly sized 1D :class:`numpy.ndarray` derived from the
|
||||
*Pixel Data* in :class:`Dataset` `ds` or raise an exception. Reshaping the
|
||||
returned array to the correct dimensions is handled automatically.
|
||||
|
||||
def needs_to_convert_to_RGB(ds):
|
||||
Return ``True`` if the *Pixel Data* in the :class:`Dataset` `ds` needs to
|
||||
be converted to the RGB colourspace, ``False`` otherwise.
|
||||
|
||||
The first handler that both announces that it supports the transfer syntax
|
||||
and does not raise an exception, either in getting the data or when the data
|
||||
is reshaped to the correct dimensions, is the handler that will provide the
|
||||
data.
|
||||
|
||||
If they all fail only the last exception is raised.
|
||||
|
||||
If none raise an exception, but they all refuse to support the transfer
|
||||
syntax, then this fact is announced in a :class:`NotImplementedError`
|
||||
exception.
|
||||
"""
|
||||
|
||||
APPLY_J2K_CORRECTIONS = True
|
||||
"""Use the information within JPEG 2000 data to correct the returned pixel data
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
If ``True`` (default), then for handlers that support JPEG 2000 pixel data,
|
||||
use the component precision and sign to correct the returned ndarray when
|
||||
using the pixel data handlers. If ``False`` then only rely on the element
|
||||
values within the dataset when applying corrections.
|
||||
"""
|
||||
|
||||
assume_implicit_vr_switch = True
|
||||
"""If invalid VR encountered, assume file switched to implicit VR
|
||||
|
||||
.. versionadded:: 2.2
|
||||
|
||||
If ``True`` (default), when reading an explicit VR file,
|
||||
if a VR is encountered that is not a valid two bytes within A-Z,
|
||||
then assume the original writer switched to implicit VR. This has been
|
||||
seen in particular in some sequences. This does not test that
|
||||
the VR is a valid DICOM VR, just that it has valid characters.
|
||||
"""
|
||||
|
||||
|
||||
INVALID_KEYWORD_BEHAVIOR = "WARN"
|
||||
"""Control the behavior when setting a :class:`~pydicom.dataset.Dataset`
|
||||
attribute that's not a known element keyword.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
If ``"WARN"`` (default), then warn when an element value is set using
|
||||
``Dataset.__setattr__()`` and the keyword is camel case but doesn't match a
|
||||
known DICOM element keyword. If ``"RAISE"`` then raise a :class:`ValueError`
|
||||
exception. If ``"IGNORE"`` then neither warn nor raise.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> from pydicom import config
|
||||
>>> config.INVALID_KEYWORD_BEHAVIOR = "WARN"
|
||||
>>> ds = Dataset()
|
||||
>>> ds.PatientName = "Citizen^Jan" # OK
|
||||
>>> ds.PatientsName = "Citizen^Jan"
|
||||
../pydicom/dataset.py:1895: UserWarning: Camel case attribute 'PatientsName'
|
||||
used which is not in the element keyword data dictionary
|
||||
"""
|
||||
|
||||
INVALID_KEY_BEHAVIOR = "WARN"
|
||||
"""Control the behavior when invalid keys are used with
|
||||
:meth:`~pydicom.dataset.Dataset.__contains__` (e.g. ``'invalid' in ds``).
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
Invalid keys are objects that cannot be converted to a
|
||||
:class:`~pydicom.tag.BaseTag`, such as unknown element keywords or invalid
|
||||
element tags like ``0x100100010``.
|
||||
|
||||
If ``"WARN"`` (default), then warn when an invalid key is used, if ``"RAISE"``
|
||||
then raise a :class:`ValueError` exception. If ``"IGNORE"`` then neither warn
|
||||
nor raise.
|
||||
|
||||
Examples
|
||||
--------
|
||||
|
||||
>>> from pydicom import config
|
||||
>>> config.INVALID_KEY_BEHAVIOR = "RAISE"
|
||||
>>> ds = Dataset()
|
||||
>>> 'PatientName' in ds # OK
|
||||
False
|
||||
>>> 'PatientsName' in ds
|
||||
Traceback (most recent call last):
|
||||
File "<stdin>", line 1, in <module>
|
||||
File ".../pydicom/dataset.py", line 494, in __contains__
|
||||
raise ValueError(msg) from exc
|
||||
ValueError: Invalid value used with the 'in' operator: must be an
|
||||
element tag as a 2-tuple or int, or an element keyword
|
||||
"""
|
||||
|
||||
|
||||
if _use_future_env:
|
||||
if _use_future_env.lower() in ["true", "yes", "on", "1"]:
|
||||
_use_future = True
|
||||
elif _use_future_env.lower() in ["false", "no", "off", "0"]:
|
||||
_use_future = False
|
||||
else:
|
||||
raise ValueError(
|
||||
"Unknown setting for environment variable "
|
||||
"PYDICOM_FUTURE. Use True or False."
|
||||
)
|
||||
|
||||
|
||||
def future_behavior(enable_future: bool = True) -> None:
|
||||
"""Imitate the behavior for the next major version of *pydicom*.
|
||||
|
||||
.. versionadded:: 2.1
|
||||
|
||||
This can be used to ensure your code is "future-proof" for known
|
||||
upcoming changes in the next major version of *pydicom*. Typically,
|
||||
deprecations become errors, and default values of config flags may change.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
enable_future: bool
|
||||
Set ``True`` (default) to emulate future pydicom behavior,
|
||||
``False`` to reset to current pydicom behavior.
|
||||
|
||||
See also
|
||||
--------
|
||||
:attr:`INVALID_KEYWORD_BEHAVIOR`
|
||||
:attr:`INVALID_KEY_BEHAVIOR`
|
||||
|
||||
"""
|
||||
global _use_future, INVALID_KEYWORD_BEHAVIOR
|
||||
|
||||
if enable_future:
|
||||
_use_future = True
|
||||
INVALID_KEYWORD_BEHAVIOR = "RAISE"
|
||||
settings._writing_validation_mode = RAISE
|
||||
else:
|
||||
_use_future = False
|
||||
INVALID_KEYWORD_BEHAVIOR = "WARN"
|
||||
settings._writing_validation_mode = None
|
||||
|
||||
|
||||
if _use_future:
|
||||
future_behavior()
|
||||
Reference in New Issue
Block a user