Esempio n. 1
0
def correct_ambiguous_vr_element(elem, ds, is_little_endian):
    """Attempt to correct the ambiguous VR element `elem`.

    When it's not possible to correct the VR, the element will be returned
    unchanged. Currently the only ambiguous VR elements not corrected for are
    all retired or part of DICONDE.

    If the VR is corrected and is 'US' or 'SS' then the value will be updated
    using the pydicom.values.convert_numbers() method.

    Parameters
    ----------
    elem : pydicom.dataelem.DataElement
        The element with an ambiguous VR.
    ds : pydicom.dataset.Dataset
        The dataset containing `elem`.
    is_little_endian : bool
        The byte ordering of the values in the dataset.

    Returns
    -------
    elem : pydicom.dataelem.DataElement
        The corrected element
    """
    if 'or' in elem.VR:
        # convert raw data elements before handling them
        if elem.is_raw:
            elem = DataElement_from_raw(elem)
            ds.__setitem__(elem.tag, elem)

        # 'OB or OW': 7fe0,0010 PixelData
        if elem.tag == 0x7fe00010:
            # Compressed Pixel Data
            # PS3.5 Annex A.4
            #   If encapsulated, VR is OB and length is undefined
            if elem.is_undefined_length:
                elem.VR = 'OB'
            # Non-compressed Pixel Data - Implicit Little Endian
            # PS3.5 Annex A1: VR is always OW
            elif ds.is_implicit_VR:
                elem.VR = 'OW'
            else:
                # Non-compressed Pixel Data - Explicit VR
                # PS3.5 Annex A.2:
                # If BitsAllocated is > 8 then VR shall be OW,
                # else may be OB or OW.
                # If we get here, the data has not been written before
                # or has been converted from Implicit Little Endian,
                # so we default to OB for BitsAllocated 1 or 8
                elem.VR = 'OW' if ds.BitsAllocated > 8 else 'OB'

        # 'US or SS' and dependent on PixelRepresentation
        # (0018,9810) Zero Velocity Pixel Value
        # (0022,1452) Mapped Pixel Value
        # (0028,0104)/(0028,0105) Smallest/Largest Valid Pixel Value
        # (0028,0106)/(0028,0107) Smallest/Largest Image Pixel Value
        # (0028,0108)/(0028,0109) Smallest/Largest Pixel Value in Series
        # (0028,0110)/(0028,0111) Smallest/Largest Image Pixel Value in Plane
        # (0028,0120) Pixel Padding Value
        # (0028,0121) Pixel Padding Range Limit
        # (0028,1101-1103) Red/Green/Blue Palette Color Lookup Table Descriptor
        # (0028,3002) LUT Descriptor
        # (0040,9216)/(0040,9211) Real World Value First/Last Value Mapped
        # (0060,3004)/(0060,3006) Histogram First/Last Bin Value
        elif elem.tag in [
                0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106,
                0x00280107, 0x00280108, 0x00280109, 0x00280110, 0x00280111,
                0x00280120, 0x00280121, 0x00281101, 0x00281102, 0x00281103,
                0x00283002, 0x00409211, 0x00409216, 0x00603004, 0x00603006
        ]:
            # US if PixelRepresentation value is 0x0000, else SS
            #   For references, see the list at
            #   https://github.com/darcymason/pydicom/pull/298
            if ds.PixelRepresentation == 0:
                elem.VR = 'US'
                byte_type = 'H'
            else:
                elem.VR = 'SS'
                byte_type = 'h'
            elem.value = convert_numbers(elem.value, is_little_endian,
                                         byte_type)

        # 'OB or OW' and dependent on WaveformBitsAllocated
        # (5400, 0110) Channel Minimum Value
        # (5400, 0112) Channel Maximum Value
        # (5400, 100A) Waveform Padding Data
        # (5400, 1010) Waveform Data
        elif elem.tag in [0x54000110, 0x54000112, 0x5400100A, 0x54001010]:
            # If WaveformBitsAllocated is > 8 then OW, otherwise may be
            #   OB or OW.
            #   See PS3.3 C.10.9.1.
            if ds.is_implicit_VR:
                elem.VR = 'OW'
            else:
                elem.VR = 'OW' if ds.WaveformBitsAllocated > 8 else 'OB'

        # 'US or OW': 0028,3006 LUTData
        elif elem.tag == 0x00283006:
            # First value in LUT Descriptor is how many values in
            #   LUTData, if there's only one value then must be US
            # As per PS3.3 C.11.1.1.1
            if ds.LUTDescriptor[0] == 1:
                elem.VR = 'US'
                elem.value = convert_numbers(elem.value, is_little_endian, 'H')
            else:
                elem.VR = 'OW'

        # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax
        elif (elem.tag.group in range(0x6000, 0x601F, 2)
              and elem.tag.elem == 0x3000):
            # Implicit VR must be OW, explicit VR may be OB or OW
            #   as per PS3.5 Section 8.1.2 and Annex A
            elem.VR = 'OW'

    return elem
Esempio n. 2
0
def correct_ambiguous_vr_element(elem, ds, is_little_endian):
    """Attempt to correct the ambiguous VR element `elem`.

    When it's not possible to correct the VR, the element will be returned
    unchanged. Currently the only ambiguous VR elements not corrected for are
    all retired or part of DICONDE.

    If the VR is corrected and is 'US' or 'SS' then the value will be updated
    using the pydicom.values.convert_numbers() method.

    Parameters
    ----------
    elem : pydicom.dataelem.DataElement
        The element with an ambiguous VR.
    ds : pydicom.dataset.Dataset
        The dataset containing `elem`.
    is_little_endian : bool
        The byte ordering of the values in the dataset.

    Returns
    -------
    elem : pydicom.dataelem.DataElement
        The corrected element
    """
    if 'or' in elem.VR:
        # convert raw data elements before handling them
        if elem.is_raw:
            elem = DataElement_from_raw(elem)
            ds.__setitem__(elem.tag, elem)

        # 'OB or OW': 7fe0,0010 PixelData
        if elem.tag == 0x7fe00010:

            try:
                # Compressed Pixel Data
                # PS3.5 Annex A.4
                #   If encapsulated, VR is OB and length is undefined
                if elem.is_undefined_length:
                    elem.VR = 'OB'
                else:
                    # Non-compressed Pixel Data
                    # If BitsAllocated is > 8 then OW, else may be OB or OW
                    #   as per PS3.5 Annex A.2. For BitsAllocated < 8 test the
                    #    size of each pixel to see if its written in OW or OB
                    if ds.BitsAllocated > 8:
                        elem.VR = 'OW'
                    else:
                        nr_pixels = ds.Rows * ds.Columns
                        if 'SamplesPerPixel' in ds:
                            nr_pixels *= ds.SamplesPerPixel
                        pixel_size = len(ds.PixelData) / nr_pixels
                        if pixel_size == 2:
                            elem.VR = 'OW'
                        elif pixel_size == 1:
                            elem.VR = 'OB'
            except AttributeError:
                pass

        # 'US or SS' and dependent on PixelRepresentation
        elif elem.tag in [
                0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106,
                0x00280107, 0x00280108, 0x00280109, 0x00280110, 0x00280111,
                0x00280120, 0x00280121, 0x00281101, 0x00281102, 0x00281103,
                0x00283002, 0x00409211, 0x00409216, 0x00603004, 0x00603006
        ]:
            # US if PixelRepresenation value is 0x0000, else SS
            #   For references, see the list at
            #   https://github.com/darcymason/pydicom/pull/298
            if 'PixelRepresentation' in ds:
                if ds.PixelRepresentation == 0:
                    elem.VR = 'US'
                    byte_type = 'H'
                else:
                    elem.VR = 'SS'
                    byte_type = 'h'
                elem.value = convert_numbers(elem.value, is_little_endian,
                                             byte_type)

        # 'OB or OW' and dependent on WaveformBitsAllocated
        elif elem.tag in [0x54000100, 0x54000112, 0x5400100A, 0x54001010]:
            # If WaveformBitsAllocated is > 8 then OW, otherwise may be
            #   OB or OW, however not sure how to handle this.
            #   See PS3.3 C.10.9.1.
            if 'WaveformBitsAllocated' in ds:
                if ds.WaveformBitsAllocated > 8:
                    elem.VR = 'OW'

        # 'US or OW': 0028,3006 LUTData
        elif elem.tag in [0x00283006]:
            if 'LUTDescriptor' in ds:
                # First value in LUT Descriptor is how many values in
                #   LUTData, if there's only one value then must be US
                # As per PS3.3 C.11.1.1.1
                if ds.LUTDescriptor[0] == 1:
                    elem.VR = 'US'
                    elem.value = convert_numbers(elem.value, is_little_endian,
                                                 'H')
                else:
                    elem.VR = 'OW'

        # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax
        elif (elem.tag.group in range(0x6000, 0x601F, 2)
              and elem.tag.elem == 0x3000):
            # Implicit VR must be OW, explicit VR may be OB or OW
            #   as per PS3.5 Section 8.1.2 and Annex A
            if ds.is_implicit_VR:
                elem.VR = 'OW'

    return elem
Esempio n. 3
0
def correct_ambiguous_vr_element(elem, ds, is_little_endian):
    """Attempt to correct the ambiguous VR element `elem`.

    When it's not possible to correct the VR, the element will be returned
    unchanged. Currently the only ambiguous VR elements not corrected for are
    all retired or part of DICONDE.

    If the VR is corrected and is 'US' or 'SS' then the value will be updated
    using the pydicom.values.convert_numbers() method.

    Parameters
    ----------
    elem : pydicom.dataelem.DataElement
        The element with an ambiguous VR.
    ds : pydicom.dataset.Dataset
        The dataset containing `elem`.
    is_little_endian : bool
        The byte ordering of the values in the dataset.

    Returns
    -------
    elem : pydicom.dataelem.DataElement
        The corrected element
    """
    if 'or' in elem.VR:
        # convert raw data elements before handling them
        if elem.is_raw:
            elem = DataElement_from_raw(elem)
            ds.__setitem__(elem.tag, elem)

        # 'OB or OW': 7fe0,0010 PixelData
        if elem.tag == 0x7fe00010:

            try:
                # Compressed Pixel Data
                # PS3.5 Annex A.4
                #   If encapsulated, VR is OB and length is undefined
                if elem.is_undefined_length:
                    elem.VR = 'OB'
                else:
                    # Non-compressed Pixel Data
                    # If BitsAllocated is > 8 then OW, else may be OB or OW
                    #   as per PS3.5 Annex A.2. For BitsAllocated < 8 test the
                    #    size of each pixel to see if its written in OW or OB
                    if ds.BitsAllocated > 8:
                        elem.VR = 'OW'
                    else:
                        nr_pixels = ds.Rows * ds.Columns
                        if 'SamplesPerPixel' in ds:
                            nr_pixels *= ds.SamplesPerPixel
                        pixel_size = len(ds.PixelData) / nr_pixels
                        if pixel_size == 2:
                            elem.VR = 'OW'
                        elif pixel_size == 1:
                            elem.VR = 'OB'
            except AttributeError:
                pass

        # 'US or SS' and dependent on PixelRepresentation
        elif elem.tag in [
                0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106,
                0x00280107, 0x00280108, 0x00280109, 0x00280110, 0x00280111,
                0x00280120, 0x00280121, 0x00281101, 0x00281102, 0x00281103,
                0x00283002, 0x00409211, 0x00409216, 0x00603004, 0x00603006
        ]:
            # US if PixelRepresenation value is 0x0000, else SS
            #   For references, see the list at
            #   https://github.com/darcymason/pydicom/pull/298
            if 'PixelRepresentation' in ds:
                if ds.PixelRepresentation == 0:
                    elem.VR = 'US'
                    byte_type = 'H'
                else:
                    elem.VR = 'SS'
                    byte_type = 'h'
                elem.value = convert_numbers(elem.value, is_little_endian,
                                             byte_type)

        # 'OB or OW' and dependent on WaveformBitsAllocated
        elif elem.tag in [0x54000100, 0x54000112, 0x5400100A, 0x54001010]:
            # If WaveformBitsAllocated is > 8 then OW, otherwise may be
            #   OB or OW, however not sure how to handle this.
            #   See PS3.3 C.10.9.1.
            if 'WaveformBitsAllocated' in ds:
                if ds.WaveformBitsAllocated > 8:
                    elem.VR = 'OW'

        # 'US or OW': 0028,3006 LUTData
        elif elem.tag in [0x00283006]:
            if 'LUTDescriptor' in ds:
                # First value in LUT Descriptor is how many values in
                #   LUTData, if there's only one value then must be US
                # As per PS3.3 C.11.1.1.1
                if ds.LUTDescriptor[0] == 1:
                    elem.VR = 'US'
                    elem.value = convert_numbers(elem.value, is_little_endian,
                                                 'H')
                else:
                    elem.VR = 'OW'

        # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax
        elif (elem.tag.group in range(0x6000, 0x601F, 2)
              and elem.tag.elem == 0x3000):
            # Implicit VR must be OW, explicit VR may be OB or OW
            #   as per PS3.5 Section 8.1.2 and Annex A
            if ds.is_implicit_VR:
                elem.VR = 'OW'

    return elem