3.0.0#
The major breaking changes with the version 3.0 release are:
The value for
JPEGLosslesshas changed to1.2.840.10008.1.2.4.57.The encoding used when saving datasets defaults to the set Transfer Syntax UID.
Dataset.pixel_arraywill convert YCbCr Pixel Data to RGB by default when possible.
read_fileandwrite_filehave been removed.
Changes#
Removed support for Python <= 3.9.
All tag formats changed to upper case, no space e.g. “(7FE0,0010)” rather than “(7fe0, 0010)”.
Values with VR AE with an incorrect value length are now handled gracefully (extra bytes are ignored with a warning).
A value of 0 for Number of Frames is now handled as 1 frame, with a user warning issued on reading the pixel data (#1844).
The value for
JPEGLosslesshas changed from 1.2.840.10008.1.2.4.70 to 1.2.840.10008.1.2.4.57 to match its UID keyword. UseJPEGLosslessSV1instead for 1.2.840.10008.1.2.4.70.The theoretical maximum number of instances supported by
FileSethas been reduced to 1838265625 to ensure support for 32-bit systems (#1743).The characters used by
generate_filename()when alphanumeric isTruehas been reduced to [0-9][A-I,K-Z].get_testdata_file()andget_testdata_files()now raiseValueErrorif called with an absolute path or pattern.generate_uid()has been changed to use a random suffix generated usingrandbelow()when entropy_srcs isn’t used, and the maximum allowed length of the prefix has been changed to 54 characters (#1773).DataElement.VMalways returns1for SQ elements (#1481).DICOM dictionary updated to 2024c.
Concepts dictionaries updated to 2024c.
validate_file_meta()now checks to ensure required Type 1 elements aren’t empty.implicit_vr and little_endian optional arguments added to
Dataset.save_as(). In addition, this method will now raise an exception if the user tries to convert between little and big endian datasets. If this is something you need, usedcmwrite()instead.Added the overwrite argument to
Dataset.save_as()anddcmwrite()to allow raising aFileExistsErrorif trying to write to a file that already exists (#2104).implicit_vr, little_endian and force_encoding optional arguments added to
dcmwrite().The priority used to decide which encoding to use with
Dataset.save_as()anddcmwrite()has been changed to:The set Transfer Syntax UID,
The implicit_vr and little_endian arguments,
Datasets containing Command Set (0000,eeee) elements can no longer be written using
Dataset.save_as()ordcmwrite(), usewrite_dataset()instead.A dataset’s
file_metaelements are no longer modified when writing.DicomIOnow requires a readable or writeable buffer during initialisation andDicomBytesIOdirectly inherits from it.The
pydicom.encodersmodule has been moved topydicom.pixels.encoders, the original import path will be removed in v4.0.Using GDCM v3.0.23 or lower to decode JPEG-LS datasets with a Bits Stored of 6 or 7 produces incorrect results, so attempting to do so now raises an exception.
pyjpeglsorpylibjpegwithpylibjpeg-libjpegcan be used instead (#2008).Using Pillow with JPEG 2000 encoded > 8-bit multi-sample data (such as RGB) now raises an exception as Pillow cannot decode such data correctly (#2006).
An exception will now be raised if an
ndarrayis used to set Pixel Data (#50).Logging of errors when converting elements using
Dataset.to_json_dict()have been made more verbose and now uselogging.WARNING(#1909).Added
FileDataset.bufferand changedFileDataset.filenameto only be the filename the dataset was read from (if any) (#1937).
Removals#
The
compatmodule has been removed.The
dicomdirmodule andDicomDirclass have been removed and reading a DICOMDIR dataset now returns a normalFileDatasetinstance. For handling DICOM File-sets and DICOMDIR datasets use theFileSetclass instead.The
read_fileandwrite_filefunctions have been removed, usedcmread()anddcmwrite()instead.The following UID constants have been removed:
JPEGBaseline(useJPEGBaseline8Bitinstead)JPEGExtended(useJPEGExtended12Bitinstead)JPEGLSLossy(useJPEGLSNearLosslessinstead)JPEG2000MultiComponentLossless(useJPEG2000MCLosslessinstead)JPEG2000MultiComponent(useJPEG2000MCinstead)
The following UID lists have been removed:
JPEGLossyCompressedPixelTransferSyntaxes: useJPEGTransferSyntaxesJPEGLSSupportedCompressedPixelTransferSyntaxes: useJPEGLSTransferSyntaxesJPEG2000CompressedPixelTransferSyntaxes: useJPEG2000TransferSyntaxesRLECompressedLosslessSyntaxes: useRLETransferSyntaxesUncompressedPixelTransferSyntaxes: useUncompressedTransferSyntaxesPILSupportedCompressedPixelTransferSyntaxes
The
PersonNameUnicodeclass has been removed, usePersonNameinstead.The
DataElement.descriptionattribute has been removed, useDataElement.nameinstead.The
pixel_data_handlers.rle_handler.rle_encode_framefunction has been removed, useDataset.compress()orRLELosslessEncoderinstead.The
_storage_sopclass_uidsmodule has been removed, import UIDs from theuidmodule instead.The following properties have been removed:
Dataset.parentandDataset.parent_seqSequence.parentandSequence.parent_datasetDataElement.parent
The
overlay_data_handlersmodule has been removed, use theoverlaysmodule instead.config.overlay_data_handlershas been removed.Dataset.fix_meta_info()has been removed as encoding state now follows the transfer syntax instead of the other way around.
Enhancements#
Added details of missing required tag information when adding a dataset to a File-set (#1752).
The following UID constants have been added:
Added convenience method
add_new_private()to add a private tag.Added the examples module to make it easier and less confusing for users to work with the example datasets used by the documentation.
Added the ability to set the corresponding dataset encoding for private transfer syntaxes to
UIDvia theset_private_encoding()method.Added the ability to register private transfer syntaxes with
register_transfer_syntax()so they can be used when reading datasets withdcmread().Warning messages are also sent to the pydicom logger (#1529).
Added the following to the
encapsmodule:parse_basic_offsets()for parsing the Basic Offset Table.parse_fragments()for determining the number of encapsulated fragments and their byte offsets.generate_fragments()for yielding encapsulated fragments.generate_fragmented_frames()for yielding encapsulated frame fragments.generate_frames()for yielding whole encapsulated frames.get_frame()for returning the specific encapsulated frame at index without necessarily having to read the preceding frames into memory.
These new functions support reading encapsulated data from both
bytesor any Python object withread(),seek()andtell()methods such asio.BytesIO,BinaryIOormmap.mmap. They also support using the Extended Offset Table for determining frame boundaries.Added the keep_deferred keyword argument to
Dataset.get_item()to allow accessing the file offset and element length without having to read the element value. (#1873).Added the
pixelsmodule and a new more flexible backend for decoding pixel data viaDecoderfactory class instances. The new decoding backend adds support for the following:Returning a view over the original pixel data buffer (#746).
Returning RGB pixel data by default for JPEG (#1781, #1133 and many others).
Returning excess frames for JPEG when there is no Basic or Extended Offset Table and the Number of Frames is incorrect (#1666).
Returning excess frames for native encoding when the Number of Frames is incorrect (#2035)
Returning the decoded pixel data as either a NumPy
ndarrayor buffer-like object.Iterating through either all or specific frames.
Added support for decoding HTJ2K transfer syntaxes (#1848).
Added two functions for returning pixel data as a NumPy
ndarrayfrom a path to a dataset while minimizing memory-usage:pixel_array()anditer_pixels().Added two functions for compressing and decompressing datasets using the new decoding backend:
compress()anddecompress().Added support for the following transfer syntaxes to
Dataset.compress()(#1997):JPEG-LS Lossless with
JPEGLSLosslessEncoderJPEG-LS Near Lossless with
JPEGLSNearLosslessEncoderJPEG 2000 Lossless with
JPEG2000LosslessEncoderJPEG 2000 with
JPEG2000Encoder
See the JPEG-LS and JPEG 2000 encoding guides for more information.
Added
Dataset.pixel_array_options()for controlling pixel data decoding when usingDataset.pixel_arraywith the newpixelsbackend.Improve support for reading and resolving inline binary data with VR=UN from Json (#2062).
get_j2k_parameters()now takes into account the JP2 header (if present, although it’s non-conformant for it to be) (#2073).Added support for NumPy v2.0 (#2075).
Added
pydicom.__concepts_version__attribute with the DICOM Standard version used to create the concepts dictionaries inpydicom.sr(#1021).Refactored the interface for the concepts in
pydicom.srto simplify the access types (#1454).Added the
Dataset.set_pixel_data()method andset_pixel_data()function for automatically setting a dataset’s Pixel Data and related Image Pixel module elements using anndarray(#50).Added typing support for
Datasetelement access using the types-pydicom package. (#1485).Added
apply_presentation_lut()for applying a Presentation LUT to anndarray(#1265).Added
apply_icc_profile()andcreate_icc_transform()for applying ICC profiles to anndarray(#1244).Added
Dataset.update_raw_element()to make it easier to modify aRawDataElement’s VR or value prior to conversion to aDataElement(#1739).Added support for using
io.BufferedIOBasesubclasses to set the value for elements with O* VRs such as OB and OW (#1913).Added
encapsulate_buffer()andencapsulate_extended_buffer()for encapsulating buffered compressed Pixel Data viaEncapsulatedBufferinstances.Added elements with OB, OD, OF, OL, OW, OV VRs to the type validation checking when setting
DataElementvalues (#1414).Added
convert_raw_data_element()for converting raw element data toDataElementinstances.Added the
hooksmodule which contains an interface for adding callback functions via theHookssingleton, as well as default and alternative convenience callbacks forconvert_raw_data_element()(#1556).
Fixes#
Fixed the GDCM and pylibjpeg handlers changing the Pixel Representation value to 0 when the J2K stream disagrees with the dataset and
APPLY_J2K_CORRECTIONSisTrue(#1689).Fixed pydicom codify error when relative path did not exist.
Fixed the VR enum sometimes returning invalid values for Python 3.11+ (#1874).
Fixed pixel data handler for Pillow 10.1 raising an AttributeError (#1907).
Fixed a possible security issue with
FileInstanceinstances being able to escape the temporary directory when being added to aFileSet(#1922).Fixed an
AttributeErrorwhen runningdeepcopy()afterDataset.update(#1816).Fixed
encapsulate_extended()not returning the correct values for odd-length frames (#1968).Fixed using the incorrect encoding when writing datasets converted between explicit and implicit VR when only the Transfer Syntax UID was changed (#1943).
Fixed the
jpeg_ls,pillowandrlepixel data handlers not working correctly when a frame is spread across multiple fragments (#1774).Added mitigation for a rare case where clearing the pixel data value prior to updating it may sometimes result in
pixel_arrayreturning the previous array instead of creating a new one (#1983).Fixed a
KeyErrorwhen comparing codes with one of the codes havingscheme_designatorset toSRTbut not being included in theSRTtoSCTcode mapping (#1994).Fixed JPEG-LS datasets with a Pixel Representation of 1 returning incorrect image data when Bits Stored is less than Bits Allocated (#2009).
Fixed decoding failures for JPEG-LS datasets with Bits Allocated of 16 and Bits Stored <= 8 (#2010).
Fixed the Pixel Data VR not being set correctly with
Dataset.compress()(#2013).Fixed
Dataset.decompress()not updating the Pixel Data element value until after saving (#2024).Fixed a rare issue with converting pixel data to an
ndarraywhen Bits Stored is less than Bits Allocated and the unused bits haven’t been set to an appropriate value for correct interpretation of the data.Fixed a
RecursionErrorwhen usingcopy.deepcopy()with a dataset containing a private block (#2025).Fixed non-unique keywords for the concept codes in
pydicom.sr(#1388).Fixed keywords using Python identifiers in
pydicom.sr(#1273).Fixed being unable to write LUT Descriptor when the VR is SS and the first value is greater than 32767 (#2081).
Fixed Deflated Explicit VR Little Endian datasets not working correctly with
codify(#1937).
Deprecations#
Dataset.is_little_endianandDataset.is_implicit_VRwill be removed in v4.0.Dataset.read_little_endianandDataset.read_implicit_vrwill be removed in v4.0, useDataset.original_encodinginstead.Dataset.read_encodingwill be removed in v4.0, useDataset.original_character_setinstead.The write_like_original optional argument to
Dataset.save_asanddcmwrite()will be removed in v4.0, use enforce_file_format instead.The following
encapsmodule functions will be removed in v4.0:get_frame_offsets(), useparse_basic_offsets()instead.generate_pixel_data_fragment(), usegenerate_fragments()instead.generate_pixel_data_frame(), usegenerate_fragmented_frames()instead.generate_pixel_data(), usegenerate_frames()instead.decode_data_sequence(), usegenerate_fragments()instead.defragment_data(), usegenerate_frames()instead.read_item(), usegenerate_fragments()instead.
The
pydicom.pixel_data_handlersmodule will be removed in v4.0. All pixel data processing will use thepydicom.pixelsmodule instead starting with v3.0.The following functions from
pydicom.pixel_data_handlers.utilhave been moved topydicom.pixels.processing:The following functions from
pydicom.pixel_data_handlers.utilhave been moved topydicom.pixels.utils:pydicom.pixel_data_handlers.util.dtype_corrected_for_endianness()will be removed in v4.0.
Dataset.convert_pixel_data()will be removed in v4.0, useDataset.pixel_array_options()instead.DataElement_from_raw()will be removed in v4.0, please useconvert_raw_data_element()instead.config.data_element_callbackandconfig.data_element_callback_kwargswill be removed in v4.0, please use the hooks forconvert_raw_data_element()instead.The
pydicom.utils.fixerssubmodule will be removed in v4.0, please use the alternative callbacks forconvert_raw_data_element()in thehooksmodule instead.
Pydicom Internals#
Repository folder structure refactored.
Renamed top level
sourcefolder toutil.New CI tools - dependabot, and pre-commit using black and ruff.