pydicom/filebase.py
def DicomFile(*args, **kwargs):
    return DicomFileLike(open(*args, **kwargs))
pydicom/tag.py
def Tag(arg, arg2=None):
    def __lt__(self, other):
    def __eq__(self, other):
    def __ne__(self, other):
    def __str__(self):
    def group(self):
    def element(self):
    def is_private(self):
def TupleTag(group_elem):
class BaseTag(BaseTag_base_class):
pydicom/util/hexutil.py
def bytes2hex(byte_string):
    s = b2a_hex(byte_string)
    if not in_py2:
        s = s.decode()
    return " ".join(s[i:i + 2] for i in range(0, len(s), 2))
pydicom/datadict.py
def dictionaryVR(tag):
    """Return the dicom value representation for the given dicom tag."""
    return get_entry(tag)[0]
pydicom/valuerep.py
class DA(date):
class DT(datetime):
class TM(time):
class DSfloat(float):
class DSdecimal(Decimal):
class IS(int):
class PersonName3(object):
class PersonNameBase(object):
class PersonName(PersonNameBase, bytes):
class PersonNameUnicode(PersonNameBase, compat.text_type):
    def __getstate__(self):
    def __setstate__(self, state):
    def __reduce__(self):
    def __new__(cls, val):
    def __init__(self, val):
    def __str__(self):
    def __getstate__(self):
    def __setstate__(self, state):
    def __reduce__(self):
    def __new__(cls, val):
    def __init__(self, val):
    def __str__(self):
    def __getstate__(self):
    def __setstate__(self, state):
    def __reduce__(self):
    def __new__(cls, val):
    def __init__(self, val):
    def __str__(self):
    def __getstate__(self):
    def __setstate__(self, state):
    def __init__(self, val):
    def __str__(self):
    def __repr__(self):
    def __getstate__(self):
    def __setstate__(self, state):
    def __new__(cls, val):
    def __init__(self, val):
    def __str__(self):
    def __repr__(self):
def DS(val):
        def __getstate__(self):
        def __setstate__(self, state):
    def __new__(cls, val):
    def __init__(self, val):
    def __repr__(self):
def MultiString(val, valtype=str):
    def __init__(self, val, encodings=default_encoding):
    def parse(self, val):
    def __eq__(self, other):
    def __ne__(self, other):
    def __str__(self):
    def __repr__(self):
    def decode(self, encodings=None):
    def encode(self, encodings=None):
    def family_comma_given(self):
    def formatted(self, format_str):
    def _verify_encodings(self, encodings):
    def __init__(self, val):
    def formatted(self, format_str):
    def parse(self):
    def __new__(cls, val):
    def encode(self, *args):
    def family_comma_given(self):
    def __new__(cls, val, encodings):
    def __init__(self, val, encodings):
    def _verify_encodings(self, encodings):
    def encode(self, encodings):
    def family_comma_given(self):
pydicom/compat.py
def reraise(tp, value, tb):
pydicom/dataelem.py
class DataElement(object):
    """Contain and manipulate a Dicom data element, having a tag, VR, VM and value.

    Most user code will not create data elements using this class directly,
    but rather through DICOM keywords in Dataset objects.
    See the Dataset class for a description of how Datasets, Sequences,
    and DataElements work.

    Class Data
    ----------
    For string display (via __str__), the following are used:

    descripWidth -- maximum width of description field (default 35).
    maxBytesToDisplay -- longer data will display "array of # bytes" (default 16).
    showVR -- True (default) to include the dicom VR just before the value.

    Attributes
    ----------
    is_retired : bool
        For officially registered DICOM Data Elements this will be True if the
        retired status as given in PS3.6 Table 6-1 is 'RET'. For private or
        unknown Elements this will always be False
    keyword : str
        For officially registered DICOM Data Elements this will be the Keyword
        as given in PS3.6 Table 6-1. For private or unknown Elements this will
        return an empty string.
    name : str
        For officially registered DICOM Data Elements this will be the Name
        as given in PS3.6 Table 6-1. For private Elements known to pydicom this
        will be the Name in the format '[name]'. For unknown private Elements
        this will be 'Private Creator'. For unknown Elements this will return
        an empty string.
    tag : pydicom.tag.Tag
        The DICOM Tag for the Data Element
    value
        The Data Element's stored value(s)
    VM : int
        The Value Multiplicity of the Data Element's stored value(s)
    VR : str
        The Data Element's Value Representation value
    """
    descripWidth = 35
    maxBytesToDisplay = 16
    showVR = 1

    # Python 2: Classes which define __eq__ should flag themselves as unhashable
    __hash__ = None

    def __init__(self, tag, VR, value, file_value_tell=None,
                 is_undefined_length=False, already_converted=False):
        """Create a data element instance.

        Most user code should instead use DICOM keywords
        to create data_elements, for which only the value is supplied,
        and the VR and tag are determined from the dicom dictionary.

        tag -- dicom (group, element) tag in any form accepted by Tag().
        VR -- dicom value representation (see DICOM standard part 6)
        value -- the value of the data element. One of the following:
            - a single string value
            - a number
            - a list or tuple with all strings or all numbers
            - a multi-value string with backslash separator
        file_value_tell -- used internally by Dataset, to store the write
            position for ReplaceDataElementValue method
        is_undefined_length -- used internally to store whether the length
            field in this data element was 0xFFFFFFFFL, i.e. "undefined length"

        """
        self.tag = Tag(tag)
        self.VR = VR  # Note!: you must set VR before setting value
        if already_converted:
            self._value = value
        else:
            self.value = value  # calls property setter which will convert
        self.file_tell = file_value_tell
        self.is_undefined_length = is_undefined_length

    @property
    def value(self):
        """The value (possibly multiple values) of this data_element"""
        return self._value

    @value.setter
    def value(self, val):
        """Set method for 'value' property"""
        # Check if is a string with multiple values separated by '\'
        # If so, turn them into a list of separate strings
        if isString(val) and self.VR not in \
                ['UT', 'ST', 'LT', 'FL', 'FD', 'AT', 'OB', 'OW', 'OF', 'SL', 'SQ', 'SS',
                 'UL', 'OB/OW', 'OW/OB', 'OB or OW', 'OW or OB', 'UN'] and 'US' not in self.VR:  # latter covers 'US or SS' etc
            if _backslash in val:
                val = val.split(_backslash)
        self._value = self._convert_value(val)

    @property
    def VM(self):
        """The number of values in the data_element's 'value'"""
        if isMultiValue(self.value):
            return len(self.value)
        else:
            return 1

    def _convert_value(self, val):
        """Convert Dicom string values if possible to e.g. numbers. Handle the case
        of multiple value data_elements"""
        if self.VR == 'SQ':  # a sequence - leave it alone
            from pydicom.sequence import Sequence
            if isinstance(val, Sequence):
                return val
            else:
                return Sequence(val)

        # if the value is a list, convert each element
        try:
            val.append
        except AttributeError:  # not a list
            return self._convert(val)
        else:
            returnvalue = []
            for subval in val:
                returnvalue.append(self._convert(subval))
            return returnvalue

    def _convert(self, val):
        """Take the value and convert to number, etc if possible"""
        if self.VR == 'IS':
            return pydicom.valuerep.IS(val)
        elif self.VR == 'DA' and config.datetime_conversion:
            return pydicom.valuerep.DA(val)
        elif self.VR == 'DS':
            return pydicom.valuerep.DS(val)
        elif self.VR == 'DT' and config.datetime_conversion:
            return pydicom.valuerep.DT(val)
        elif self.VR == 'TM' and config.datetime_conversion:
            return pydicom.valuerep.TM(val)
        elif self.VR == "UI":
            return UID(val)
        elif not in_py2 and self.VR == "PN":
            return PersonName(val)
        # Later may need this for PersonName as for UI,
        #    but needs more thought
        # elif self.VR == "PN":
        #    return PersonName(val)
        else:  # is either a string or a type 2 optionally blank string
            return val  # this means a "numeric" value could be empty string ""
        # except TypeError:
            # print "Could not convert value '%s' to VR '%s' in tag %s" \
            # % (repr(val), self.VR, self.tag)
        # except ValueError:
            # print "Could not convert value '%s' to VR '%s' in tag %s" \
            # % (repr(val), self.VR, self.tag)

    def __eq__(self, other):
        """
        Compare `self` and `other` for equality

        Returns
        -------
        bool
            The result if `self` and `other` are the same class
        NotImplemented
            If `other` is not the same class as `self` then returning
            NotImplemented delegates the result to superclass.__eq__(subclass)
        """
        # Faster result if same object
        if other is self:
            return True

        if isinstance(other, self.__class__):
            return self.__dict__ == other.__dict__

        return NotImplemented

    def __ne__(self, other):
        """ Compare `self` and `other` for inequality """
        return not (self == other)

    def __str__(self):
        """Return str representation of this data_element"""
        repVal = self.repval
        if self.showVR:
            s = "%s %-*s %s: %s" % (str(self.tag), self.descripWidth,
                                    self.description()[:self.descripWidth], self.VR, repVal)
        else:
            s = "%s %-*s %s" % (str(self.tag), self.descripWidth,
                                self.description()[:self.descripWidth], repVal)
        return s

    @property
    def repval(self):
        """Return a str representation of the current value for use in __str__"""
        byte_VRs = ['OB', 'OW', 'OW/OB', 'OW or OB', 'OB or OW', 'US or SS or OW', 'US or SS']
        if (self.VR in byte_VRs and len(self.value) > self.maxBytesToDisplay):
            repVal = "Array of %d bytes" % len(self.value)
        elif hasattr(self, 'original_string'):  # for VR of IS or DS
            repVal = repr(self.original_string)
        elif isinstance(self.value, UID):
            repVal = self.value.name
        else:
            repVal = repr(self.value)  # will tolerate unicode too
        return repVal

    def __unicode__(self):
        """Return unicode representation of this data_element"""
        if isinstance(self.value, compat.text_type):
            # start with the string rep then replace the value part with the unicode
            strVal = str(self)
            uniVal = compat.text_type(strVal.replace(self.repval, "")) + self.value
            return uniVal
        else:
            return compat.text_type(str(self))

    def __getitem__(self, key):
        """Returns the item from my value's Sequence, if it is one."""
        try:
            return self.value[key]
        except TypeError:
            raise TypeError("DataElement value is unscriptable (not a Sequence)")

    @property
    def name(self):
        return self.description()

    def description(self):
        """Return the DICOM dictionary description for this dicom tag."""
        if dictionary_has_tag(self.tag):
            name = dictionary_description(self.tag)
        elif self.tag.is_private:
            name = "Private tag data"  # default
            if hasattr(self, 'private_creator'):
                try:
                    # If have name from private dictionary, use it, but
                    #   but put in square brackets so is differentiated,
                    #   and clear that cannot access it by name
                    name = "[" + private_dictionary_description(self.tag, self.private_creator) + "]"
                except KeyError:
                    pass
            elif self.tag.elem >> 8 == 0:
                name = "Private Creator"
        elif self.tag.element == 0:  # implied Group Length dicom versions < 3
            name = "Group Length"
        else:
            name = ""
        return name

    @property
    def is_retired(self):
        """The data_element's retired status"""
        if dictionary_has_tag(self.tag):
            return dictionary_is_retired(self.tag)
        else:
            return False

    @property
    def keyword(self):
        """The data_element's keyword (if known)"""
        if dictionary_has_tag(self.tag):
            return dictionary_keyword(self.tag)
        else:
            return ''

    def __repr__(self):
        """Handle repr(data_element)"""
        if self.VR == "SQ":
            return repr(self.value)
        else:
            return str(self)
pydicom/charset.py
def clean_escseq(element, encodings):
def convert_encodings(encodings):
def decode(data_element, dicom_character_set):
pydicom/config.py
def reset_data_element_callback():
def DS_decimal(use_Decimal_boolean=True):
def debug(debug_on=True):
pydicom/dataset.py
class Dataset(dict):
    """A collection (dictionary) of Dicom `DataElement` instances.

    Example of two ways to retrieve or set values:

    1. dataset[0x10, 0x10].value --> patient's name
    2. dataset.PatientName --> patient's name

    Example (2) uses DICOM "keywords", defined starting in 2011 standard.
    PatientName is not actually a member of the object, but unknown member
    requests are checked against the DICOM dictionary. If the name matches a
    DicomDictionary descriptive string, the corresponding tag is used
    to look up or set the `DataElement` instance's value.

    :attribute indent_chars: for string display, the characters used to indent
       nested Data Elements (e.g. sequence items). Default is three spaces.

    """
    indent_chars = "   "

    # Python 2: Classes which define __eq__ should flag themselves as unhashable
    __hash__ = None

    def __init__(self, *args, **kwargs):
        self._parent_encoding = kwargs.get('parent_encoding', default_encoding)
        dict.__init__(self, *args)

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_val, exc_tb):
        return False

    def add(self, data_element):
        """Equivalent to dataset[data_element.tag] = data_element."""
        self[data_element.tag] = data_element

    def add_new(self, tag, VR, value):
        """Create a new DataElement instance and add it to this Dataset."""
        data_element = DataElement(tag, VR, value)
        # use data_element.tag since DataElement verified it
        self[data_element.tag] = data_element

    def data_element(self, name):
        """Return the full data_element instance for the given descriptive name.

        Parameters
        ----------
        name: str
            A DICOM keyword

        Returns
        -------
        DataElement instance or None
            Returns a DataElement instance in this dataset with the given name.
            If the tag for that name is not found, returns None.
        """
        tag = tag_for_name(name)
        if tag:
            return self[tag]
        return None

    def __contains__(self, name):
        """Extend dict.__contains__() to handle DICOM keywords.

        This is called for code like: ``if 'SliceLocation' in dataset``.

        """
        if isinstance(name, (str, compat.text_type)):
            tag = tag_for_name(name)
        else:
            try:
                tag = Tag(name)
            except:
                return False
        if tag:
            return dict.__contains__(self, tag)
        else:
            return dict.__contains__(self, name)  # will no doubt raise an exception

    def decode(self):
        """Apply character set decoding to all data elements.

        See DICOM PS3.5-2008 6.1.1.
        """
        # Find specific character set. 'ISO_IR 6' is default
        # May be multi-valued, but let pydicom.charset handle all logic on that
        dicom_character_set = self._character_set

        # Shortcut to the decode function in pydicom.charset
        decode_data_element = pydicom.charset.decode

        # Callback for walk(), to decode the chr strings if necessary
        # This simply calls the pydicom.charset.decode function
        def decode_callback(ds, data_element):
            if data_element.VR == 'SQ':
                [dset.decode() for dset in data_element.value]
            else:
                decode_data_element(data_element, dicom_character_set)

        self.walk(decode_callback, recursive=False)

    def __delattr__(self, name):
        """Intercept requests to delete an attribute by name, e.g. del ds.name

        If name is a DICOM keyword, then delete the corresponding tag
           and data_element. Else, delete an instance (python) attribute
           as any other class would do

        """
        # First check if a valid DICOM keyword and if we have that data element
        tag = tag_for_name(name)
        if tag is not None and tag in self:
            dict.__delitem__(self, tag)  # direct to dict as we know we have key
        # If not a DICOM name in this dataset, check for regular instance name
        #   can't do delete directly, that will call __delattr__ again
        elif name in self.__dict__:
            del self.__dict__[name]
        # Not found, raise an error in same style as python does
        else:
            raise AttributeError(name)

    def __delitem__(self, key):
        """Intercept requests to delete an attribute by key, e.g. del ds[tag]"""
        # Assume is a standard tag (for speed in common case)
        try:
            dict.__delitem__(self, key)
        # If not a standard tag, than convert to Tag and try again
        except KeyError:
            tag = Tag(key)
            dict.__delitem__(self, tag)

    def __dir__(self):
        """Give a list of attributes available in the dataset

        List of attributes is used, for example, in auto-completion in editors
           or command-line environments.
        """
        # Force zip object into a list in case of python3. Also backwards
        # compatible
        meths = set(list(zip(
                    *inspect.getmembers(Dataset, inspect.isroutine)))[0])
        props = set(list(zip(
                    *inspect.getmembers(Dataset, inspect.isdatadescriptor)))[0])
        dicom_names = set(self.dir())
        alldir = sorted(props | meths | dicom_names)
        return alldir

    def dir(self, *filters):
        """Return an alphabetical list of data_element keywords in the dataset.

        Intended mainly for use in interactive Python sessions.

        Parameters
        ----------
        filters : str
            Zero or more string arguments to the function. Used for
            case-insensitive match to any part of the DICOM name.

        Returns
        -------
        All data_element names in this dataset matching the filters.
        If no filters, return all DICOM keywords in the dataset.
        """
        allnames = []
        for tag, data_element in self.items():
            allnames.extend(all_names_for_tag(tag))
        # remove blanks - tags without valid names (e.g. private tags)
        allnames = [x for x in allnames if x]
        # Store found names in a dict, so duplicate names appear only once
        matches = {}
        for filter_ in filters:
            filter_ = filter_.lower()
            match = [x for x in allnames if x.lower().find(filter_) != -1]
            matches.update(dict([(x, 1) for x in match]))
        if filters:
            names = sorted(matches.keys())
            return names
        else:
            return sorted(allnames)
    
    def __eq__(self, other):
        """ 
        Compare `self` and `other` for equality

        Returns
        -------
        bool
            The result if `self` and `other` are the same class
        NotImplemented
            If `other` is not the same class as `self` then returning
            NotImplemented delegates the result to superclass.__eq__(subclass)
        """
        # When comparing against self this will be faster
        if other is self:
            return True

        if isinstance(other, self.__class__):
            # Compare Elements using values() and class variables using __dict__
            # Convert values() to a list for compatibility between python 2 and 3
            return (list(self.values()) == list(other.values())) and (self.__dict__ == other.__dict__)

        return NotImplemented

    def get(self, key, default=None):
        """Extend dict.get() to handle DICOM keywords"""
        if isinstance(key, (str, compat.text_type)):
            try:
                return getattr(self, key)
            except AttributeError:
                return default
        else:
            # is not a string, try to make it into a tag and then hand it
            # off to the underlying dict
            if not isinstance(key, BaseTag):
                try:
                    key = Tag(key)
                except:
                    raise TypeError("Dataset.get key must be a string or tag")
        try:
            return_val = self.__getitem__(key)
        except KeyError:
            return_val = default
        return return_val

    def __getattr__(self, name):
        """Intercept requests for unknown Dataset python-attribute names.

        If the name matches a Dicom keyword,
        return the value for the data_element with the corresponding tag.

        """
        # __getattr__ only called if instance cannot find name in self.__dict__
        # So, if name is not a dicom string, then is an error
        tag = tag_for_name(name)
        if tag is None:
            raise AttributeError("Dataset does not have attribute "
                                 "'{0:s}'.".format(name))
        tag = Tag(tag)
        if tag not in self:
            raise AttributeError("Dataset does not have attribute "
                                 "'{0:s}'.".format(name))
        else:  # do have that dicom data_element
            return self[tag].value

    @property
    def _character_set(self):
        char_set = self.get('SpecificCharacterSet', None)

        if not char_set:
            char_set = self._parent_encoding
        else:
            char_set = convert_encodings(char_set)

        return char_set

    def __getitem__(self, key):
        """Operator for dataset[key] request."""
        tag = Tag(key)
        data_elem = dict.__getitem__(self, tag)

        if isinstance(data_elem, DataElement):
            return data_elem
        elif isinstance(data_elem, tuple):
            # If a deferred read, then go get the value now
            if data_elem.value is None:
                from pydicom.filereader import read_deferred_data_element
                data_elem = read_deferred_data_element(self.fileobj_type,
                                                       self.filename, self.timestamp, data_elem)

            if tag != (0x08, 0x05):
                character_set = self._character_set
            else:
                character_set = default_encoding
            # Not converted from raw form read from file yet; do so now
            self[tag] = DataElement_from_raw(data_elem, character_set)
        return dict.__getitem__(self, tag)

    def get_item(self, key):
        """Return the raw data element if possible.
        It will be raw if the user has never accessed the value,
        or set their own value.
        Note if the data element is a deferred-read element,
        then it is read and converted before being returned
        """
        tag = Tag(key)
        data_elem = dict.__getitem__(self, tag)
        # If a deferred read, return using __getitem__ to read and convert it
        if isinstance(data_elem, tuple) and data_elem.value is None:
            return self[key]
        return data_elem

    def group_dataset(self, group):
        """Return a Dataset containing only data_elements of a certain group.

        Parameters
        ----------
        group : the group part of a dicom (group, element) tag.

        Returns
        -------
        A dataset instance containing data elements of the group specified.
        """
        ds = Dataset()
        ds.update(dict([(tag, data_element) for tag, data_element in self.items()
                        if tag.group == group]))
        return ds

    def __iter__(self):
        """Method to iterate through the dataset, returning data_elements.
        e.g.:
        for data_element in dataset:
            do_something...
        The data_elements are returned in DICOM order,
        i.e. in increasing order by tag value.
        Sequence items are returned as a single data_element; it is up to the
           calling code to recurse into the Sequence items if desired
        """
        # Note this is different than the underlying dict class,
        #        which returns the key of the key:value mapping.
        #   Here the value is returned (but data_element.tag has the key)
        taglist = sorted(self.keys())
        for tag in taglist:
            yield self[tag]

    def _is_uncompressed_transfer_syntax(self):
        # FIXME uses file_meta here, should really only be thus for FileDataset
        return self.file_meta.TransferSyntaxUID in NotCompressedPixelTransferSyntaxes

    def __ne__(self, other):
        """ Compare `self` and `other` for inequality """
        return not (self == other)

    def _pixel_data_numpy(self):
        """Return a NumPy array of the pixel data if NumPy is available.
        Falls back to GDCM in case of unsupported transfer syntaxes.

        Raises
        ------
        TypeError
            If there is no pixel data or not a supported data type
        ImportError
            If NumPy isn't found, or in the case of fallback, if GDCM isn't found.

        Returns
        -------
        NumPy array
        """
        if not self._is_uncompressed_transfer_syntax():
            if not have_gdcm:
                raise NotImplementedError("Pixel Data is compressed in a format pydicom does not yet handle. Cannot return array. Pydicom might be able to convert the pixel data using GDCM if it is installed.")
            elif not self.filename:
                raise NotImplementedError("GDCM is only supported when the dataset has been created with a filename.")
        if not have_numpy:
            msg = "The Numpy package is required to use pixel_array, and numpy could not be imported."
            raise ImportError(msg)
        if 'PixelData' not in self:
            raise TypeError("No pixel data found in this dataset.")

        # There are two cases:
        # 1) uncompressed PixelData -> use numpy
        # 2) compressed PixelData, filename is available and GDCM is available -> use GDCM
        if self._is_uncompressed_transfer_syntax():
            # Make NumPy format code, e.g. "uint16", "int32" etc
            # from two pieces of info:
            #    self.PixelRepresentation -- 0 for unsigned, 1 for signed;
            #    self.BitsAllocated -- 8, 16, or 32
            format_str = '%sint%d' % (('u', '')[self.PixelRepresentation],
                                      self.BitsAllocated)
            try:
                numpy_dtype = numpy.dtype(format_str)
            except TypeError:
                msg = ("Data type not understood by NumPy: "
                       "format='%s', PixelRepresentation=%d, BitsAllocated=%d")
                raise TypeError(msg % (format_str, self.PixelRepresentation,
                                self.BitsAllocated))

            if self.is_little_endian != sys_is_little_endian:
                numpy_dtype = numpy_dtype.newbyteorder('S')

            pixel_bytearray = self.PixelData
        elif have_gdcm and self.filename:
            # read the file using GDCM
            # FIXME this should just use self.PixelData instead of self.filename
            #       but it is unclear how this should be achieved using GDCM
            gdcm_image_reader = gdcm.ImageReader()
            gdcm_image_reader.SetFileName(self.filename)
            if not gdcm_image_reader.Read():
                raise TypeError("GDCM could not read DICOM image")
            gdcm_image = gdcm_image_reader.GetImage()

            # determine the correct numpy datatype
            gdcm_numpy_typemap = {
                gdcm.PixelFormat.INT8:     numpy.int8,
                gdcm.PixelFormat.UINT8:    numpy.uint8,
                gdcm.PixelFormat.UINT16:   numpy.uint16,
                gdcm.PixelFormat.INT16:    numpy.int16,
                gdcm.PixelFormat.UINT32:   numpy.uint32,
                gdcm.PixelFormat.INT32:    numpy.int32,
                gdcm.PixelFormat.FLOAT32:  numpy.float32,
                gdcm.PixelFormat.FLOAT64:  numpy.float64
            }
            gdcm_pixel_format = gdcm_image.GetPixelFormat().GetScalarType()
            if gdcm_pixel_format in gdcm_numpy_typemap:
                numpy_dtype = gdcm_numpy_typemap[gdcm_pixel_format]
            else:
                raise TypeError('{0} is not a GDCM supported pixel format'.format(gdcm_pixel_format))

            # GDCM returns char* as type str. Under Python 2 `str` are
            # byte arrays by default. Python 3 decodes this to
            # unicode strings by default.
            # The SWIG docs mention that they always decode byte streams
            # as utf-8 strings for Python 3, with the `surrogateescape`
            # error handler configured.
            # Therefore, we can encode them back to their original bytearray
            # representation on Python 3 by using the same parameters.
            pixel_bytearray = gdcm_image.GetBuffer()
            if sys.version_info >= (3, 0):
                pixel_bytearray = pixel_bytearray.encode("utf-8", "surrogateescape")

            # if GDCM indicates that a byte swap is in order, make sure to inform numpy as well
            if gdcm_image.GetNeedByteSwap():
                numpy_dtype = numpy_dtype.newbyteorder('S')

            # Here we need to be careful because in some cases, GDCM reads a
            # buffer that is too large, so we need to make sure we only include
            # the first n_rows * n_columns * dtype_size bytes.

            n_bytes = self.Rows * self.Columns * numpy.dtype(numpy_dtype).itemsize

            if len(pixel_bytearray) > n_bytes:

                # We make sure that all the bytes after are in fact zeros
                padding = pixel_bytearray[n_bytes:]
                if numpy.any(numpy.fromstring(padding, numpy.byte)):
                    pixel_bytearray = pixel_bytearray[:n_bytes]
                else:
                    # We revert to the old behavior which should then result in a
                    # Numpy error later on.
                    pass

        pixel_array = numpy.fromstring(pixel_bytearray, dtype=numpy_dtype)

        # Note the following reshape operations return a new *view* onto pixel_array, but don't copy the data
        if 'NumberOfFrames' in self and self.NumberOfFrames > 1:
            if self.SamplesPerPixel > 1:
                # TODO: Handle Planar Configuration attribute
                assert self.PlanarConfiguration == 0
                pixel_array = pixel_array.reshape(self.NumberOfFrames, self.Rows, self.Columns, self.SamplesPerPixel)
            else:
                pixel_array = pixel_array.reshape(self.NumberOfFrames, self.Rows, self.Columns)
        else:
            if self.SamplesPerPixel > 1:
                if self.BitsAllocated == 8:
                    if self.PlanarConfiguration == 0:
                        pixel_array = pixel_array.reshape(self.Rows, self.Columns, self.SamplesPerPixel)
                    else:
                        pixel_array = pixel_array.reshape(self.SamplesPerPixel, self.Rows, self.Columns)
                        pixel_array = pixel_array.transpose(1, 2, 0)
                else:
                    raise NotImplementedError("This code only handles SamplesPerPixel > 1 if Bits Allocated = 8")
            else:
                pixel_array = pixel_array.reshape(self.Rows, self.Columns)
        return pixel_array

    def _compressed_pixel_data_numpy(self):
        """Return a NumPy array of the pixel data.

        NumPy is a numerical package for python. It is used if available.

        :raises TypeError: if no pixel data in this dataset.
        :raises ImportError: if cannot import numpy.

        """
        if 'PixelData' not in self:
            raise TypeError("No pixel data found in this dataset.")

        if not have_numpy:
            msg = "The Numpy package is required to use pixel_array, and numpy could not be imported."
            raise ImportError(msg)

        # determine the type used for the array
        need_byteswap = (self.is_little_endian != sys_is_little_endian)

        # Make NumPy format code, e.g. "uint16", "int32" etc
        # from two pieces of info:
        #    self.PixelRepresentation -- 0 for unsigned, 1 for signed;
        #    self.BitsAllocated -- 8, 16, or 32
        format_str = '%sint%d' % (('u', '')[self.PixelRepresentation],
                                  self.BitsAllocated)
        try:
            numpy_format = numpy.dtype(format_str)
        except TypeError:
            msg = ("Data type not understood by NumPy: "
                   "format='%s', PixelRepresentation=%d, BitsAllocated=%d")
            raise TypeError(msg % (numpy_format, self.PixelRepresentation,
                            self.BitsAllocated))
        if self.file_meta.TransferSyntaxUID in pydicom.uid.PILSupportedCompressedPixelTransferSyntaxes:
            UncompressedPixelData = self._get_PIL_supported_compressed_pixeldata()
        elif self.file_meta.TransferSyntaxUID in pydicom.uid.JPEGLSSupportedCompressedPixelTransferSyntaxes:
            UncompressedPixelData = self._get_jpeg_ls_supported_compressed_pixeldata()
        else:
            msg = "The transfer syntax {0} is not currently supported.".format(self.file_meta.TransferSyntaxUID)
            raise NotImplementedError(msg)

        # Have correct Numpy format, so create the NumPy array
        arr = numpy.fromstring(UncompressedPixelData, numpy_format)

        # XXX byte swap - may later handle this in read_file!!?
        if need_byteswap:
            arr.byteswap(True)  # True means swap in-place, don't make a new copy
        # Note the following reshape operations return a new *view* onto arr, but don't copy the data
        if 'NumberOfFrames' in self and self.NumberOfFrames > 1:
            if self.SamplesPerPixel > 1:
                arr = arr.reshape(self.NumberOfFrames, self.Rows, self.Columns,  self.SamplesPerPixel)
            else:
                arr = arr.reshape(self.NumberOfFrames, self.Rows, self.Columns)
        else:
            if self.SamplesPerPixel > 1:
                if self.BitsAllocated == 8:
                    if self.PlanarConfiguration == 0:
                        arr = arr.reshape(self.Rows, self.Columns, self.SamplesPerPixel)
                    else:
                        arr = arr.reshape(self.SamplesPerPixel, self.Rows, self.Columns)
                        arr = arr.transpose(1, 2, 0)
                else:
                    raise NotImplementedError("This code only handles SamplesPerPixel > 1 if Bits Allocated = 8")
            else:
                arr = arr.reshape(self.Rows, self.Columns)
        if (self.file_meta.TransferSyntaxUID in pydicom.uid.JPEG2000CompressedPixelTransferSyntaxes and self.BitsStored == 16):
            # WHY IS THIS EVEN NECESSARY??
            arr &= 0x7FFF
        return arr

    def _get_PIL_supported_compressed_pixeldata(self):
        if not have_pillow:
            msg = "The pillow package is required to use pixel_array for this transfer syntax {0}, and pillow could not be imported.".format(self.file_meta.TransferSyntaxUID)
            raise ImportError(msg)
        # decompress here
        if self.file_meta.TransferSyntaxUID in pydicom.uid.JPEGLossyCompressedPixelTransferSyntaxes:
            if self.BitsAllocated > 8:
                raise NotImplementedError("JPEG Lossy only supported if Bits Allocated = 8")
            generic_jpeg_file_header = b'\xff\xd8\xff\xe0\x00\x10JFIF\x00\x01\x01\x01\x00\x01\x00\x01\x00\x00'
            frame_start_from = 2
        elif self.file_meta.TransferSyntaxUID in pydicom.uid.JPEG2000CompressedPixelTransferSyntaxes:
            generic_jpeg_file_header = b''
            # generic_jpeg_file_header = b'\x00\x00\x00\x0C\x6A\x50\x20\x20\x0D\x0A\x87\x0A'
            frame_start_from = 0
        else:
            generic_jpeg_file_header = b''
            frame_start_from = 0
        try:
            UncompressedPixelData = ''
            if 'NumberOfFrames' in self and self.NumberOfFrames > 1:
                # multiple compressed frames
                CompressedPixelDataSeq = pydicom.encaps.decode_data_sequence(self.PixelData)
                for frame in CompressedPixelDataSeq:
                    data = generic_jpeg_file_header + frame[frame_start_from:]
                    fio = io.BytesIO(data)
                    try:
                        decompressed_image = PILImg.open(fio)
                    except IOError as e:
                        raise NotImplementedError(e.message)
                    UncompressedPixelData += decompressed_image.tobytes()
            else:
                # single compressed frame
                UncompressedPixelData = pydicom.encaps.defragment_data(self.PixelData)
                UncompressedPixelData = generic_jpeg_file_header + UncompressedPixelData[frame_start_from:]
                try:
                    fio = io.BytesIO(UncompressedPixelData)
                    decompressed_image = PILImg.open(fio)
                except IOError as e:
                    raise NotImplementedError(e.message)
                UncompressedPixelData = decompressed_image.tobytes()
        except:
            raise
        return UncompressedPixelData

    def _get_jpeg_ls_supported_compressed_pixeldata(self):
        if not have_jpeg_ls:
            msg = "The jpeg_ls package is required to use pixel_array for this transfer syntax {0}, and jpeg_ls could not be imported.".format(self.file_meta.TransferSyntaxUID)
            raise ImportError(msg)
        # decompress here
        UncompressedPixelData = ''
        if 'NumberOfFrames' in self and self.NumberOfFrames > 1:
            # multiple compressed frames
            CompressedPixelDataSeq = pydicom.encaps.decode_data_sequence(self.PixelData)
            # print len(CompressedPixelDataSeq)
            for frame in CompressedPixelDataSeq:
                decompressed_image = jpeg_ls.decode(numpy.fromstring(frame, dtype=numpy.uint8))
                UncompressedPixelData += decompressed_image.tobytes()
        else:
            # single compressed frame
            CompressedPixelData = pydicom.encaps.defragment_data(self.PixelData)
            decompressed_image = jpeg_ls.decode(numpy.fromstring(CompressedPixelData, dtype=numpy.uint8))
            UncompressedPixelData = decompressed_image.tobytes()
        return UncompressedPixelData

    # Use by pixel_array property
    def _get_pixel_array(self):
        # Check if already have converted to a NumPy array
        # Also check if self.PixelData has changed. If so, get new NumPy array
        already_have = True
        if not hasattr(self, "_pixel_array"):
            already_have = False
        elif self._pixel_id != id(self.PixelData):
            already_have = False
        if not already_have and not self._is_uncompressed_transfer_syntax():
            try:
                # print("Pixel Data is compressed")
                self._pixel_array = self._compressed_pixel_data_numpy()
                self._pixel_id = id(self.PixelData)  # is this guaranteed to work if memory is re-used??
                return self._pixel_array
            except IOError as I:
                logger.info("Pillow or JPLS did not support this transfer syntax")
        if not already_have:
            self._pixel_array = self._pixel_data_numpy()
            self._pixel_id = id(self.PixelData)  # is this guaranteed to work if memory is re-used??
        return self._pixel_array

    @property
    def pixel_array(self):
        """Return the pixel data as a NumPy array"""
        try:
            return self._get_pixel_array()
        except AttributeError:
            t, e, tb = sys.exc_info()
            val = PropertyError("AttributeError in pixel_array property: " +
                                e.args[0])
            compat.reraise(PropertyError, val, tb)

    # Format strings spec'd according to python string formatting options
    #    See http://docs.python.org/library/stdtypes.html#string-formatting-operations
    default_element_format = "%(tag)s %(name)-35.35s %(VR)s: %(repval)s"
    default_sequence_element_format = "%(tag)s %(name)-35.35s %(VR)s: %(repval)s"

    def formatted_lines(self, element_format=default_element_format,
                        sequence_element_format=default_sequence_element_format,
                        indent_format=None):
        """A generator to give back a formatted string representing each line
        one at a time. Example:
            for line in dataset.formatted_lines("%(name)s=%(repval)s", "SQ:%(name)s=%(repval)s"):
                print(line)
        See the source code for default values which illustrate some of the names that can be used in the
        format strings
        indent_format -- not used in current version. Placeholder for future functionality.
        """
        for data_element in self.iterall():
            # Get all the attributes possible for this data element (e.g.
            #   gets descriptive text name too)
            # This is the dictionary of names that can be used in the format string
            elem_dict = dict([(x, getattr(data_element, x)()
                               if callable(getattr(data_element, x))
                               else getattr(data_element, x))
                              for x in dir(data_element) if not x.startswith("_")])
            if data_element.VR == "SQ":
                yield sequence_element_format % elem_dict
            else:
                yield element_format % elem_dict

    def _pretty_str(self, indent=0, top_level_only=False):
        """Return a string of the data_elements in this dataset, with indented levels.

        This private method is called by the __str__() method
        for handling print statements or str(dataset), and the __repr__() method.
        It is also used by top(), which is the reason for the top_level_only flag.
        This function recurses, with increasing indentation levels.

        """
        strings = []
        indent_str = self.indent_chars * indent
        nextindent_str = self.indent_chars * (indent + 1)
        for data_element in self:
            with tag_in_exception(data_element.tag):
                if data_element.VR == "SQ":   # a sequence
                    strings.append(indent_str + str(data_element.tag) + "  %s   %i item(s) ---- " % (data_element.description(), len(data_element.value)))
                    if not top_level_only:
                        for dataset in data_element.value:
                            strings.append(dataset._pretty_str(indent + 1))
                            strings.append(nextindent_str + "---------")
                else:
                    strings.append(indent_str + repr(data_element))
        return "\n".join(strings)

    def remove_private_tags(self):
        """Remove all Dicom private tags in this dataset and those contained within."""
        def RemoveCallback(dataset, data_element):
            """Internal method to use as callback to walk() method."""
            if data_element.tag.is_private:
                # can't del self[tag] - won't be right dataset on recursion
                del dataset[data_element.tag]
        self.walk(RemoveCallback)

    def save_as(self, filename, write_like_original=True):
        """Write the dataset to a file.

        Parameters
        ----------
        filename : str
            Name of file to save new DICOM file to.
        write_like_original : boolean
            If True (default), preserves the following information from
            the dataset:
            -preamble -- if no preamble in read file, than not used here
            -hasFileMeta -- if writer did not do file meta information,
                then don't write here either
            -seq.is_undefined_length -- if original had delimiters, write them now too,
                instead of the more sensible length characters
            - is_undefined_length_sequence_item -- for datasets that belong to a
                sequence, write the undefined length delimiters if that is
                what the original had.
            If False, produces a "nicer" DICOM file for other readers,
                where all lengths are explicit.

        See Also
        --------
        pydicom.filewriter.write_file
            Write a DICOM file from a FileDataset instance.

        Notes
        -----
        Set dataset.preamble if you want something other than 128 0-bytes.
        If the dataset was read from an existing dicom file, then its preamble
        was stored at read time. It is up to the user to ensure the preamble is still
        correct for its purposes.

        If there is no Transfer Syntax tag in the dataset, then set
        dataset.is_implicit_VR and dataset.is_little_endian
        to determine the transfer syntax used to write the file.
        """
        pydicom.write_file(filename, self, write_like_original)

    def __setattr__(self, name, value):
        """Intercept any attempts to set a value for an instance attribute.

        If name is a dicom descriptive string (cleaned with CleanName),
        then set the corresponding tag and data_element.
        Else, set an instance (python) attribute as any other class would do.

        """
        tag = tag_for_name(name)
        if tag is not None:  # successfully mapped name to a tag
            if tag not in self:  # don't have this tag yet->create the data_element instance
                VR = dictionaryVR(tag)
                data_element = DataElement(tag, VR, value)
            else:  # already have this data_element, just changing its value
                data_element = self[tag]
                data_element.value = value
            # Now have data_element - store it in this dict
            self[tag] = data_element
        else:  # name not in dicom dictionary - setting a non-dicom instance attribute
            # XXX note if user mis-spells a dicom data_element - no error!!!
            self.__dict__[name] = value

    def __setitem__(self, key, value):
        """Operator for dataset[key]=value. Check consistency, and deal with private tags"""
        if not isinstance(value, (DataElement, RawDataElement)):  # ok if is subclass, e.g. DeferredDataElement
            raise TypeError("Dataset contents must be DataElement instances.\n"
                            "To set a data_element value use data_element.value=val")
        tag = Tag(value.tag)
        if key != tag:
            raise ValueError("data_element.tag must match the dictionary key")

        data_element = value
        if tag.is_private:
            # See PS 3.5-2008 section 7.8.1 (p. 44) for how blocks are reserved
            logger.debug("Setting private tag %r" % tag)
            private_block = tag.elem >> 8
            private_creator_tag = Tag(tag.group, private_block)
            if private_creator_tag in self and tag != private_creator_tag:
                if isinstance(data_element, RawDataElement):
                    data_element = DataElement_from_raw(data_element, self._character_set)
                data_element.private_creator = self[private_creator_tag].value
        dict.__setitem__(self, tag, data_element)

    def __str__(self):
        """Handle str(dataset)."""
        return self._pretty_str()

    def top(self):
        """Show the DICOM tags, but only the top level; do not recurse into Sequences"""
        return self._pretty_str(top_level_only=True)

    def trait_names(self):
        """Return a list of valid names for auto-completion code
        Used in IPython, so that data element names can be found
        and offered for autocompletion on the IPython command line
        """
        return dir(self)  # only valid python >=2.6, else use self.__dir__()

    def update(self, dictionary):
        """Extend dict.update() to handle DICOM keywords."""
        for key, value in list(dictionary.items()):
            if isinstance(key, (str, compat.text_type)):
                setattr(self, key, value)
            else:
                self[Tag(key)] = value

    def iterall(self):
        """Iterate through the dataset, yielding all data elements.

        Unlike Dataset.__iter__, this *does* recurse into sequences,
        and so returns all data elements as if the file were "flattened".
        """
        for data_element in self:
            yield data_element
            if data_element.VR == "SQ":
                sequence = data_element.value
                for dataset in sequence:
                    for elem in dataset.iterall():
                        yield elem

    def walk(self, callback, recursive=True):
        """Walk over given function for all dataset data_elements.

        Visit all data_elements, possibly recursing into sequences and their datasets,
        The callback function is called for each data_element
        (including SQ element).
        Can be used to perform an operation on certain types of data_elements.
        E.g., `remove_private_tags`() finds all private tags and deletes them.
        `DataElement`s will come back in DICOM order (by increasing tag number
        within their dataset)

        Parameters
        ----------
        callback: a callable that takes two arguments: a dataset, and
                  a data_element belonging to that dataset.
        recursive : boolean
            Flag to indicate whether to recurse into Sequences
        """
        taglist = sorted(self.keys())
        for tag in taglist:

            with tag_in_exception(tag):
                data_element = self[tag]
                callback(self, data_element)  # self = this Dataset
                # 'tag in self' below needed in case callback deleted data_element
                if recursive and tag in self and data_element.VR == "SQ":
                    sequence = data_element.value
                    for dataset in sequence:
                        dataset.walk(callback)

    __repr__ = __str__
pydicom/errors.py
class InvalidDicomError(Exception):
    """Exception that is raised when the the file does not seem
    to be a valid dicom file, usually when the four characters
    "DICM" are not present at position 128 in the file.
    (According to the dicom specification, each dicom file should
    have this.)

    To force reading the file (because maybe it is a dicom file without
    a header), use read_file(..., force=True).
    """
    def __init__(self, *args):
        if not args:
            args = ('The specified file is not a valid DICOM file.',)
        Exception.__init__(self, *args)
pydicom/dicomdir.py
class DicomDir(FileDataset):
    """Hold a DICOMDIR dataset read from file.

    Derived from FileDataset, but additional methods are available,
    specific to the Directory structure
    """
    def __init__(self, filename_or_obj, dataset, preamble=None, file_meta=None,
                 is_implicit_VR=True, is_little_endian=True):
        """Initialize a DICOMDIR dataset read from a DICOM file
        Carries forward all the initialization from FileDataset class

        :param filename: full path and filename to the file. Use None if is a BytesIO.
        :param dataset: some form of dictionary, usually a Dataset from read_dataset()
        :param preamble: the 128-byte DICOM preamble
        :param file_meta: the file meta info dataset, as returned by _read_file_meta,
                or an empty dataset if no file meta information is in the file
        :param is_implicit_VR: True if implicit VR transfer syntax used; False if explicit VR. Default is True.
        :param is_little_endian: True if little-endian transfer syntax used; False if big-endian. Default is True.
        """
        # Usually this class is created through filereader.read_partial,
        # and it checks class SOP, but in case of direct creation,
        # check here also
        if file_meta:
            class_uid = file_meta.MediaStorageSOPClassUID
            if not class_uid == "Media Storage Directory Storage":
                msg = "SOP Class is not Media Storage Directory (DICOMDIR)"
                raise InvalidDicomError(msg)
        FileDataset.__init__(self, filename_or_obj, dataset,
                             preamble, file_meta,
                             is_implicit_VR=True, is_little_endian=True)
        self.parse_records()

    def parse_records(self):
        """Build the hierarchy of given directory records, and structure
        into Patient, Studies, Series, Images hierarchy.

        This is intended for initial read of file only,
        it will not reorganize correctly if records are changed.

        :return: None
        """
        # Define a helper function for organizing the records
        def get_siblings(record, map_offset_to_record):
            """Return a list of all siblings of the given directory record,
            including itself.
            """
            sibling_list = [record]
            current_record = record
            while current_record.OffsetOfTheNextDirectoryRecord:
                offset_of_next = current_record.OffsetOfTheNextDirectoryRecord
                sibling = map_offset_to_record[offset_of_next]
                sibling_list.append(sibling)
                current_record = sibling
            return sibling_list

        # Build the mapping from file offsets to records
        records = self.DirectoryRecordSequence
        map_offset_to_record = {}
        for record in records:
            offset = record.seq_item_tell
            map_offset_to_record[offset] = record
        # logging.debug("Record offsets: " + map_offset_to_record.keys())

        # Find the children of each record
        for record in records:
            child_offset = record.OffsetOfReferencedLowerLevelDirectoryEntity
            if child_offset:
                child = map_offset_to_record[child_offset]
                record.children = get_siblings(child, map_offset_to_record)
            else:
                record.children = []

        # Find the top-level records : siblings of the first record
        self.patient_records = get_siblings(records[0], map_offset_to_record)
pydicom/tag.py
def TupleTag(group_elem):
    """Fast factory for BaseTag object with known safe (group, element) tuple"""
    long_value = group_elem[0] << 16 | group_elem[1]
    return BaseTag(long_value)
pydicom/fileutil.py
def read_undefined_length_value(fp, is_little_endian, delimiter_tag, defer_size=None,
                                read_size=128):
    """Read until the delimiter tag found and return the value; ignore the delimiter.

    On completion, the file will be set to the first byte after the delimiter and its
    following four zero bytes.

    Parameters
    ----------
    fp : a file-like object
    is_little_endian : boolean
        True if file transfer syntax is little endian, else False.
    read_size : int
        Number of bytes to read at one time.

    Returns
    -------
    delimiter : str, None
        The file delimiter

    Raises
    ------
    EOFError
        If EOF is reached before delimiter found.
    """
    data_start = fp.tell()
    search_rewind = 3

    if is_little_endian:
        bytes_format = b"<HH"
    else:
        bytes_format = b">HH"
    bytes_to_find = pack(bytes_format, delimiter_tag.group, delimiter_tag.elem)

    found = False
    EOF = False
    value_chunks = []
    byte_count = 0  # for defer_size checks
    while not found:
        chunk_start = fp.tell()
        bytes_read = fp.read(read_size)
        if len(bytes_read) < read_size:
            # try again - if still don't get required amount, this is last block
            new_bytes = fp.read(read_size - len(bytes_read))
            bytes_read += new_bytes
            if len(bytes_read) < read_size:
                EOF = True  # but will still check whatever we did get
        index = bytes_read.find(bytes_to_find)
        if index != -1:
            found = True
            new_bytes = bytes_read[:index]
            byte_count += len(new_bytes)
            if defer_size is None or byte_count < defer_size:
                value_chunks.append(bytes_read[:index])
            fp.seek(chunk_start + index + 4)  # rewind to end of delimiter
            length = fp.read(4)
            if length != b"\0\0\0\0":
                msg = "Expected 4 zero bytes after undefined length delimiter at pos {0:04x}"
                logger.error(msg.format(fp.tell() - 4))
        elif EOF:
            fp.seek(data_start)
            raise EOFError("End of file reached before delimiter {0!r} found".format(delimiter_tag))
        else:
            fp.seek(fp.tell() - search_rewind)  # rewind a bit in case delimiter crossed read_size boundary
            # accumulate the bytes read (not including the rewind)
            new_bytes = bytes_read[:-search_rewind]
            byte_count += len(new_bytes)
            if defer_size is None or byte_count < defer_size:
                value_chunks.append(new_bytes)
    # if get here then have found the byte string
    if defer_size is not None and defer_size >= defer_size:
        return None
    else:
        return b"".join(value_chunks)
pydicom/config.py
def reset_data_element_callback():
def DS_decimal(use_Decimal_boolean=True):
def debug(debug_on=True):
pydicom/sequence.py
class Sequence(MultiValue):
    """Class to hold multiple Datasets in a list

    This class is derived from MultiValue and as such enforces that all items
    added to the list are Dataset instances. In order to due this, a validator
    is substituted for type_constructor when constructing the MultiValue super
    class
    """
    def __init__(self, iterable=None):
        """Initialize a list of Datasets

        :param iterable: an iterable (e.g. list, tuple) of Datasets. If no
                        value is provided, an empty Sequence is generated
        """
        # We add this extra check to throw a relevant error. Without it, the
        # error will be simply that a Sequence must contain Datasets (since a
        # Dataset IS iterable). This error, however, doesn't inform the user
        # that the actual issue is that their Dataset needs to be INSIDE an
        # iterable object
        if isinstance(iterable, Dataset):
            raise TypeError('The Sequence constructor requires an iterable')

        # If no inputs are provided, we create an empty Sequence
        if not iterable:
            iterable = list()

        # validate_dataset is used as a pseudo type_constructor
        super(Sequence, self).__init__(validate_dataset, iterable)

    def __str__(self):
        lines = [str(x) for x in self]
        return "[" + "".join(lines) + "]"

    def __repr__(self):
        """Sequence-specific string representation"""
        formatstr = "<%(classname)s, length %(count)d, at %(id)X>"
        return formatstr % {'classname': self.__class__.__name__,
                            'id': id(self), 'count': len(self)}
pydicom/dataset.py
class FileDataset(Dataset):
    def __init__(self, filename_or_obj, dataset, preamble=None, file_meta=None,
                 is_implicit_VR=True, is_little_endian=True):
        """Initialize a dataset read from a DICOM file.

        Parameters
        ----------
        filename_or_obj : str, None
            Full path and filename to the file. Use None if is a BytesIO.
        dataset : Dataset, dict
            Some form of dictionary, usually a Dataset from read_dataset()
        preamble : None, optional
            The 128-byte DICOM preamble
        file_meta : None, optional
            The file meta info dataset, as returned by _read_file_meta,
            or an empty dataset if no file meta information is in the file.
        is_implicit_VR : boolean, optional
            True (default) if implicit VR transfer syntax used; False if explicit VR.
        is_little_endian : boolean
            True (default) if little-endian transfer syntax used; False if big-endian.
        """
        Dataset.__init__(self, dataset)
        self.preamble = preamble
        self.file_meta = file_meta
        self.is_implicit_VR = is_implicit_VR
        self.is_little_endian = is_little_endian
        if isinstance(filename_or_obj, compat.string_types):
            self.filename = filename_or_obj
            self.fileobj_type = open
        elif isinstance(filename_or_obj, io.BufferedReader):
            self.filename = filename_or_obj.name
            # This is the appropriate constructor for io.BufferedReader
            self.fileobj_type = open
        else:
            self.fileobj_type = filename_or_obj.__class__  # use __class__ python <2.7?; http://docs.python.org/reference/datamodel.html
            if getattr(filename_or_obj, "name", False):
                self.filename = filename_or_obj.name
            elif getattr(filename_or_obj, "filename", False):  # gzip python <2.7?
                self.filename = filename_or_obj.filename
            else:
                self.filename = None  # e.g. came from BytesIO or something file-like
        self.timestamp = None
        if stat_available and self.filename and os.path.exists(self.filename):
            statinfo = os.stat(self.filename)
            self.timestamp = statinfo.st_mtime
pydicom/compat.py
def reraise(tp, value, tb):
pydicom/dataelem.py
def isMultiValue(value):
def isString(val):
def isStringOrStringList(val):
    def __init__(self, tag, VR, value, file_value_tell=None,
                 is_undefined_length=False, already_converted=False):
    def value(self):
    def value(self, val):
    def VM(self):
    def _convert_value(self, val):
    def _convert(self, val):
    def __eq__(self, other):
    def __ne__(self, other):
    def __str__(self):
    def repval(self):
    def __unicode__(self):
    def __getitem__(self, key):
    def name(self):
    def description(self):
    def is_retired(self):
    def keyword(self):
    def __repr__(self):
    def __init__(self, tag, VR, fp, file_mtime, data_element_tell, length):
    def repval(self):
    def value(self):
    def value(self, val):
def DataElement_from_raw(raw_data_element, encoding=None):
class DataElement(object):
class DeferredDataElement(DataElement):
    VR = raw.VR
            VR = dictionaryVR(raw.tag)
                VR = 'OB'  # just read the bytes, no way to know what they mean
                VR = 'UL'


Question: import os.path
import warnings
import zlib
import pydicom.uid  # for Implicit/Explicit/Little/Big Endian transfer syntax UIDs
from io import BytesIO
from pydicom.tag import TupleTag
from pydicom.dataelem import RawDataElement
from pydicom.util.hexutil import bytes2hex
from pydicom.valuerep import extra_length_VRs
from pydicom.charset import default_encoding, convert_encodings
from pydicom.compat import in_py2
from pydicom import compat
from pydicom import config  # don't import datetime_conversion directly
from pydicom.config import logger
    from os import stat
from pydicom.errors import InvalidDicomError
from pydicom.filebase import DicomFile
from pydicom.dataset import Dataset, FileDataset
from pydicom.dicomdir import DicomDir
from pydicom.datadict import dictionaryVR
from pydicom.dataelem import DataElement
from pydicom.tag import ItemTag, SequenceDelimiterTag
from pydicom.sequence import Sequence
from pydicom.fileutil import read_undefined_length_value
from struct import Struct, unpack
from sys import byteorder
                from pydicom.values import convert_string
                    from pydicom.values import convert_string
        from pydicom.values import converters
        # and it would be error-prone to read to the correct outer delimiter
        else:
            # Try to look up type to see if is a SQ
            # if private tag, won't be able to look it up in dictionary,
            #   in which case just ignore it and read the bytes unless it is
            #   identified as a Sequence
            if VR is None:
                try:
                    VR = dictionaryVR(tag)
                except KeyError:
                    # Look ahead to see if it consists of items and is thus a SQ
                    next_tag = TupleTag(unpack(endian_chr + "HH", fp_read(4)))
                    # Rewind the file
                    fp.seek(fp_tell() - 4)
                    if next_tag == ItemTag:
                        VR = 'SQ'

            if VR == 'SQ':
                if debugging:
                    msg = "{0:08x}: Reading/parsing undefined length sequence"
                    logger_debug(msg.format(fp_tell()))
                seq = read_sequence(fp, is_implicit_VR,
                                    is_little_endian, length, encoding)
                yield DataElement(tag, VR, seq, value_tell,
                                  is_undefined_length=True)
            else:
                delimiter = SequenceDelimiterTag
                if debugging:
                    logger_debug("Reading undefined length data element")
                value = read_undefined_length_value(fp, is_little_endian,
                                                    delimiter, defer_size)

                # If the tag is (0008,0005) Specific Character Set, then store it
                if tag == (0x08, 0x05):
                    encoding = convert_string(value, is_little_endian, encoding=default_encoding)
                    # Store the encoding value in the generator for use with future elements (SQs)
                    encoding = convert_encodings(encoding)

                yield RawDataElement(tag, VR, length, value, value_tell,
                                     is_implicit_VR, is_little_endian)


def read_dataset(fp, is_implicit_VR, is_little_endian, bytelength=None,
                 stop_when=None, defer_size=None, parent_encoding=default_encoding):
    """Return a Dataset instance containing the next dataset in the file.

    Parameters
    ----------
    fp : an opened file object
    is_implicit_VR : boolean
        True if file transfer syntax is implicit VR.
    is_little_endian : boolean
        True if file has little endian transfer syntax.
    bytelength : int, None, optional
        None to read until end of file or ItemDeliterTag, else
        a fixed number of bytes to read
    stop_when : None, optional
        optional call_back function which can terminate reading.
        See help for data_element_generator for details
    defer_size : int, None, optional
        Size to avoid loading large elements in memory.
        See ``read_file`` for more parameter info.
    parent_encoding :
        optional encoding to use as a default in case
        a Specific Character Set (0008,0005) isn't specified

    Returns
    -------
    a Dataset instance

    See Also
    --------
    pydicom.dataset.Dataset
        A collection (dictionary) of Dicom `DataElement` instances.
    """
    raw_data_elements = dict()
    fpStart = fp.tell()
    de_gen = data_element_generator(fp, is_implicit_VR, is_little_endian,
                                    stop_when, defer_size, parent_encoding)
    try:
        while (bytelength is None) or (fp.tell() - fpStart < bytelength):
            raw_data_element = next(de_gen)
            # Read data elements. Stop on some errors, but return what was read
            tag = raw_data_element.tag
            # Check for ItemDelimiterTag --dataset is an item in a sequence
            if tag == (0xFFFE, 0xE00D):
                break
            raw_data_elements[tag] = raw_data_element
    except StopIteration:
        pass
    except EOFError as details:
        # XXX is this error visible enough to user code with just logging?
        logger.error(str(details) + " in file " +
                     getattr(fp, "name", "<no filename>"))
    except NotImplementedError as details:
        logger.error(details)

    return Dataset(raw_data_elements)


def read_sequence(fp, is_implicit_VR, is_little_endian, bytelength, encoding,
                  offset=0):
    """Read and return a Sequence -- i.e. a list of Datasets"""

    seq = []  # use builtin list to start for speed, convert to Sequence at end
    is_undefined_length = False
    if bytelength != 0:  # SQ of length 0 possible (PS 3.5-2008 7.5.1a (p.40)
        if bytelength == 0xffffffff:
            is_undefined_length = True
            bytelength = None
        fp_tell = fp.tell  # for speed in loop
        fpStart = fp_tell()
        while (not bytelength) or (fp_tell() - fpStart < bytelength):
            file_tell = fp.tell()
            dataset = read_sequence_item(fp, is_implicit_VR, is_little_endian,
                                         encoding, offset)
            if dataset is None:  # None is returned if hit Sequence Delimiter
                break
            dataset.file_tell = file_tell + offset
            seq.append(dataset)

Answer:     seq = Sequence(seq)