コード例 #1
0
ファイル: filewriter.py プロジェクト: sarakimmich/pydicom
def correct_ambiguous_vr(ds, is_little_endian):
    """Iterate through `ds` correcting ambiguous VR elements (if possible).

    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, except for (60xx,3000) Overlay Data.

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

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The dataset containing ambiguous VR elements.
    is_little_endian : bool
        The byte ordering of the values in the dataset.

    Returns
    -------
    ds : pydicom.dataset.Dataset
        The corrected dataset
    """
    # Iterate through the elements
    for elem in ds:
        # Iterate the correction through any sequences
        if elem.VR == 'SQ':
            for item in elem:
                item = correct_ambiguous_vr(item, is_little_endian)

        if ' or ' in elem.VR:
            # OB or OW: 7fe0,0010 PixelData
            if elem.tag == 0x7fe00010:
                # 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
                try:
                    if ds.BitsAllocated > 8:
                        elem.VR = 'OW'
                    else:
                        if len(ds.PixelData) / (ds.Rows * ds.Columns) == 2:
                            elem.VR = 'OW'
                        elif len(ds.PixelData) / (ds.Rows * ds.Columns) == 1:
                            elem.VR = 'OB'
                except AttributeError:
                    pass

            # These are all 'US or SS'
            # 0018,9810 ZeroVelocityPixelValue
            # 0022,1452 MappedPixelValue
            # 0028,0104 SmallestValidPixelValue (Retired)
            # 0028,0105 LargestValidPixelValue (Retired)
            # 0028,0106 SmallestImagePixelValue
            # 0028,0107 LargestImagePixelValue
            # 0028,0108 SmallestPixelValueInSeries
            # 0028,0109 LargestPixelValueInSeries
            # 0028,0110 SmallestImagePixelValueInPlane (Retired)
            # 0028,0111 LargestImagePixelValueInPlane (Retired)
            # 0028,0120 PixelPaddingValue
            # 0028,0121 PixelPaddingRangeLimit
            # 0028,1101 RedPaletteColorLookupTableDescriptor
            # 0028,1102 BluePaletteColorLookupTableDescriptor
            # 0028,1103 GreenPaletteColorLookupTableDescriptor
            # 0028,1111 LargeRedPaletteColorLookupTableDescriptor (Retired)
            # 0028,1112 LargeBluePaletteColorLookupTableDescriptor (Retired)
            # 0028,1113 LargeGreenPaletteColorLookupTableDescriptor (Retired)
            # 0028,3002 LUTDescriptor
            # 0040,9211 RealWorldValueLastValueMapped
            # 0040,9216 RealWorldValueFirstValueMapped
            # 0060,3004 HistogramFirstBinValue
            # 0060,3006 HistogramLastBinValue
            elif elem.tag in [
                    0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106,
                    0x00280107, 0x00280108, 0x00280108, 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/scaramallion/pynetdicom3/issues/3
                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: 5400,0110 ChannelMinimumValue
            # OB or OW: 5400,0112 ChannelMaximumValue
            # OB or OW: 5400,100A WaveformPaddingValue
            # OB or OW: 5400,1010 WaveformData
            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'

    return ds
コード例 #2
0
ファイル: filewriter.py プロジェクト: linenlkystr/pydicom
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:
        # '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:
                        if len(ds.PixelData) / (ds.Rows * ds.Columns) == 2:
                            elem.VR = 'OW'
                        elif len(ds.PixelData) / (ds.Rows * ds.Columns) == 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 hasattr(ds, 'is_implicit_VR') and ds.is_implicit_VR:
                elem.VR = 'OW'

    return elem
コード例 #3
0
def _correct_ambiguous_vr_element(elem, ds, is_little_endian):
    """Implementation for `correct_ambiguous_vr_element`.
    See `correct_ambiguous_vr_element` for description.
    """
    # '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
        # PixelRepresentation is usually set in the root dataset
        while 'PixelRepresentation' not in ds and ds.parent and ds.parent():
            ds = ds.parent()
        # if no pixel data is present, none if these tags is used,
        # so we can just ignore a missing PixelRepresentation in this case
        if ('PixelRepresentation' not in ds and 'PixelData' not in ds
                or ds.PixelRepresentation == 0):
            elem.VR = 'US'
            byte_type = 'H'
        else:
            elem.VR = 'SS'
            byte_type = 'h'

        # Need to handle type check for elements with VM > 1
        elem_value = elem.value if elem.VM == 1 else elem.value[0]
        if not isinstance(elem_value, int):
            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 = elem.value if elem.VM == 1 else elem.value[0]
            if not isinstance(elem_value, int):
                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
コード例 #4
0
ファイル: dsutils.py プロジェクト: zylxj/pynetdicom3
def correct_ambiguous_vr(ds, is_little_endian):
    """Iterate through `dataset` correct ambiguous VR elements.

    Also fixes the element.value as pydicom doesn't always handle decoding
    correctly.

    OB, string of bytes and insensitive to byte ordering
    OW, string of 16-bit words, sensitive to byte ordering
    SS, signed binary int, 16 bits in 2's complement. 2 byte fixed length.
    US, unsigned binary int. 2 byte fixed length.

    Elements with Unsolved Ambiguous VRs
    ------------------------------------
    OB or OW        0014,3050 DarkCurrentCounts (DICONDE)
    OB or OW        0014,3070 AirCounts (DICONDE)
    US or SS        0028,0071 PerimeterValue (Retired)
    US or SS        0028,1100 GrayLookupTableDescriptor (Retired)
    US or SS or OW  0028,1200 GrayLookupTableData (Retired)
    OB or OW        50xx,200C AudioSampleData (Retired)
    OB or OW        50xx,3000 CurveData (Retired)
    OB or OW        60xx,3000 OverlayData
    OB or OW        7Fxx,0010 VariablePixelData (Retired)

    Parameters
    ----------
    ds : pydicom.dataset.Dataset
        The dataset containing the elements with ambiguous VRs
    is_little_endian : bool
        Whether the dataset is encoded as little or big endian.

    Returns
    -------
    ds : pydicom.dataset.Dataset
        A dataset with (hopefully) unambiguous VRs.

    Raises
    ------
    ValueError
        If the ambiguous VR requires another element within the dataset to
        determine the VR to use, but this element is absent then ValueError will
        be raised.
    """
    for elem in ds:
        # Iterate the correction through any sequences
        if elem.VR == 'SQ':
            for item in elem:
                item = correct_ambiguous_vr(item, is_little_endian)

        if ' or ' in elem.VR:
            # OB or OW: 7fe0,0010 PixelData
            if elem.tag == 0x7fe00010:
                # If BitsAllocated is > 8 then OW, else may be OB or OW
                #   As per PS3.5 Annex A.2. For <= 8, test the size of each
                #   pixel to see if its written in OW or OB
                try:
                    if ds.BitsAllocated > 8:
                        elem.VR = 'OW'
                    else:
                        if len(ds.PixelData) / (ds.Rows * ds.Columns) == 2:
                            elem.VR = 'OW'
                        elif len(ds.PixelData) / (ds.Rows * ds.Columns) == 1:
                            elem.VR = 'OB'
                except AttributeError:
                    raise ValueError("Cannot set VR for PixelData as a "
                                     "required element is missing. Consider "
                                     "using a implicit VR transfer syntax.")

            # US or SS: 0018,9810 ZeroVelocityPixelValue
            # US or SS: 0022,1452 MappedPixelValue
            # US or SS: 0028,0104 SmallestValidPixelValue (Retired)
            # US or SS: 0028,0105 LargestValidPixelValue (Retired)
            # US or SS: 0028,0106 SmallestImagePixelValue
            # US or SS: 0028,0107 LargestImagePixelValue
            # US or SS: 0028,0108 SmallestPixelValueInSeries
            # US or SS: 0028,0109 LargestPixelValueInSeries
            # US or SS: 0028,0110 SmallestImagePixelValueInPlane (Retired)
            # US or SS: 0028,0111 LargestImagePixelValueInPlane (Retired)
            # US or SS: 0028,0120 PixelPaddingValue
            # US or SS: 0028,0121 PixelPaddingRangeLimit
            # US or SS: 0028,1101 RedPaletteColorLookupTableDescriptor
            # US or SS: 0028,1102 BluePaletteColorLookupTableDescriptor
            # US or SS: 0028,1103 GreenPaletteColorLookupTableDescriptor
            # US or SS: 0028,3002 LUTDescriptor
            # US or SS: 0040,9211 RealWorldValueLastValueMapped
            # US or SS: 0040,9216 RealWorldValueFirstValueMapped
            # US or SS: 0060,3004 HistogramFirstBinValue
            # US or SS: 0060,3006 HistogramLastBinValue
            elif elem.tag in [
                    0x00189810, 0x00221452, 0x00280104, 0x00280105, 0x00280106,
                    0x00280107, 0x00280108, 0x00280108, 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/scaramallion/pynetdicom3/issues/3
                if 'PixelRepresentation' in ds:
                    if ds.PixelRepresentation == 0:
                        elem.VR = 'US'
                        byte_type = 'H'
                    else:
                        elem.VR = 'SS'
                        byte_type = 'h'
                    # Fix for pydicom not handling this correctly
                    elem.value = convert_numbers(elem.value, is_little_endian,
                                                 byte_type)
                else:
                    raise ValueError("Cannot set VR of {} if "
                                     "PixelRepresentation is not in the"
                                     "dataset. Consider a transfer "
                                     "syntax with implicit VR.".format(
                                         elem.keyword))

            # OB or OW: 5400,0110 ChannelMinimumValue
            # OB or OW: 5400,0112 ChannelMaximumValue
            # OB or OW: 5400,100A WaveformPaddingValue
            # OB or OW: 5400,1010 WaveformData
            elif elem.tag in [0x54000100, 0x54000112, 0x5400100A, 0x54001010]:
                # OB if WaveformSampleInterpretation value is
                #   SB/UB/MB/AB, else OW. See the list at
                #   https://github.com/scaramallion/pynetdicom3/issues/3
                if 'WaveformBitsAllocated' in ds:
                    if ds.WaveformBitsAllocated > 8:
                        elem.VR = 'OW'
                    else:
                        raise ValueError("Cannot set VR of {} if "
                                         "WaveformBitsAllocated is <= 8. "
                                         "Consider using an implicit VR "
                                         "transfer syntax.".format(
                                             elem.keyword))

                else:
                    raise ValueError("Cannot set VR of {} if "
                                     "WaveformBitsAllocated is "
                                     "not in the dataset. Consider a transfer "
                                     "syntax with implicit VR.".format(
                                         elem.keyword))

            # 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 ds.LUTDescriptor[0] == 1:
                        elem.VR = 'US'
                        elem.value = convert_numbers(elem.value,
                                                     is_little_endian, 'H')
                    else:
                        elem.VR = 'OW'
                else:
                    raise ValueError("Cannot set VR of LUTData if "
                                     "LUTDescriptor is not in the dataset. "
                                     "Consider using Implicit VR as the "
                                     "transfer syntax.")
            else:
                raise NotImplementedError("Cannot set VR of {} as the"
                                          " correct method for doing "
                                          "\n   so is not known. Consider "
                                          "using a transfer syntax with "
                                          "implicit VR\n   or "
                                          "setting the VR manually prior to "
                                          "sending.".format(elem.keyword))

            LOGGER.debug("Setting VR of (%04x, %04x) %s to "
                         "'%s'.", elem.tag.group, elem.tag.elem, elem.name,
                         elem.VR)
    return ds
コード例 #5
0
ファイル: filewriter.py プロジェクト: jrkerns/pydicom
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:
        # '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:
                        if len(ds.PixelData) / (ds.Rows * ds.Columns) == 2:
                            elem.VR = 'OW'
                        elif len(ds.PixelData) / (ds.Rows * ds.Columns) == 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 hasattr(ds, 'is_implicit_VR') and ds.is_implicit_VR:
                elem.VR = 'OW'

    return elem
コード例 #6
0
ファイル: filewriter.py プロジェクト: pieper/pydicom
def _correct_ambiguous_vr_element(elem, ds, is_little_endian):
    """Implementation for `correct_ambiguous_vr_element`.
    See `correct_ambiguous_vr_element` for description.
    """
    # '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'

        # Need to handle type check for elements with VM > 1
        elem_value = elem.value if elem.VM == 1 else elem.value[0]
        if not isinstance(elem_value, int):
            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 = elem.value if elem.VM == 1 else elem.value[0]
            if not isinstance(elem_value, int):
                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
コード例 #7
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
コード例 #8
0
def _correct_ambiguous_vr_element(elem: DataElement, ds: Dataset,
                                  is_little_endian: bool) -> DataElement:
    """Implementation for `correct_ambiguous_vr_element`.
    See `correct_ambiguous_vr_element` for description.
    """
    # '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 = VR.OB
        elif ds.is_implicit_VR:
            # Non-compressed Pixel Data - Implicit Little Endian
            # PS3.5 Annex A1: VR is always OW
            elem.VR = 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 = VR.OW if cast(int, ds.BitsAllocated) > 8 else VR.OB

    # 'US or SS' and dependent on PixelRepresentation
    elif elem.tag in _us_ss_tags:
        # US if PixelRepresentation value is 0x0000, else SS
        #   For references, see the list at
        #   https://github.com/darcymason/pydicom/pull/298
        # PixelRepresentation is usually set in the root dataset
        while 'PixelRepresentation' not in ds and ds.parent and ds.parent():
            ds = cast(Dataset, ds.parent())
        # if no pixel data is present, none if these tags is used,
        # so we can just ignore a missing PixelRepresentation in this case
        if ('PixelRepresentation' not in ds and 'PixelData' not in ds
                or ds.PixelRepresentation == 0):
            elem.VR = VR.US
            byte_type = 'H'
        else:
            elem.VR = VR.SS
            byte_type = 'h'

        if elem.VM == 0:
            return elem

        # Need to handle type check for elements with VM > 1
        elem_value = (elem.value if elem.VM == 1 else cast(
            Sequence[Any], elem.value)[0])
        if not isinstance(elem_value, int):
            elem.value = convert_numbers(cast(bytes, elem.value),
                                         is_little_endian, byte_type)

    # 'OB or OW' and dependent on WaveformBitsAllocated
    elif elem.tag in _ob_ow_tags:
        # 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 = VR.OW
        else:
            elem.VR = (VR.OW
                       if cast(int, ds.WaveformBitsAllocated) > 8 else VR.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 cast(Sequence[int], ds.LUTDescriptor)[0] == 1:
            elem.VR = VR.US
            if elem.VM == 0:
                return elem

            elem_value = (elem.value if elem.VM == 1 else cast(
                Sequence[Any], elem.value)[0])
            if not isinstance(elem_value, int):
                elem.value = convert_numbers(cast(bytes, elem.value),
                                             is_little_endian, 'H')
        else:
            elem.VR = VR.OW

    # 'OB or OW': 60xx,3000 OverlayData and dependent on Transfer Syntax
    elif elem.tag in _overlay_data_tags:
        # 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 = VR.OW

    return elem