/usr/share/pyshared/dicom/filebase.py is in python-dicom 0.9.6-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | # filebase.py
"""Hold DicomFile class, which does basic I/O for a dicom file."""
# Copyright (c) 2008 Darcy Mason
# This file is part of pydicom, released under a modified MIT license.
# See the file license.txt included with this distribution, also
# available at http://pydicom.googlecode.com
from dicom.tag import Tag
from struct import unpack, pack
from cStringIO import StringIO
import logging
logger = logging.getLogger('pydicom')
class DicomIO(object):
"""File object which holds transfer syntax info and anything else we need."""
max_read_attempts = 3 # number of times to read if don't get requested bytes
defer_size = None # default
def __init__(self, *args, **kwargs):
self._ImplicitVR = True # start with this by default
def __del__(self):
self.close()
def read_le_tag(self):
"""Read and return two unsigned shorts (little endian) from the file."""
bytes = self.read(4)
if len(bytes) < 4:
raise EOFError # needed for reading "next" tag when at end of file
return unpack(bytes, "<HH")
def read_be_tag(self):
"""Read and return two unsigned shorts (little endian) from the file."""
bytes = self.read(4)
if len(bytes) < 4:
raise EOFError # needed for reading "next" tag when at end of file
return unpack(bytes, ">HH")
def write_tag(self, tag):
"""Write a dicom tag (two unsigned shorts) to the file."""
tag = Tag(tag) # make sure is an instance of class, not just a tuple or int
self.write_US(tag.group)
self.write_US(tag.element)
def read_leUS(self):
"""Return an unsigned short from the file with little endian byte order"""
return unpack("<H", self.read(2))[0]
def read_beUS(self):
"""Return an unsigned short from the file with big endian byte order"""
return unpack(">H", self.read(2))[0]
def read_leUL(self):
"""Return an unsigned long read with little endian byte order"""
return unpack("<L", self.read(4))[0]
def read(self, length=None, need_exact_length=True):
"""Reads the required length, returns EOFError if gets less
If length is None, then read all bytes
"""
parent_read = self.parent_read # super(DicomIO, self).read
if length is None:
return parent_read() # get all of it
bytes = parent_read(length)
if len(bytes) < length and need_exact_length:
# Didn't get all the desired bytes. Keep trying to get the rest. If reading across network, might want to add a delay here
attempts = 0
while attempts < self.max_read_attempts and len(bytes) < length:
bytes += parent_read(length-len(bytes))
attempts += 1
if len(bytes) < length:
start_pos = self.tell() - len(bytes)
msg = "Unexpected end of file. "
msg += "Read %d bytes of %d expected starting at position 0x%x" % (len(bytes), length, start_pos)
# logger.error(msg) # don't need this since raising error anyway
raise EOFError, msg
return bytes
def write_leUS(self, val):
"""Write an unsigned short with little endian byte order"""
self.write(pack("<H", val))
def write_leUL(self, val):
"""Write an unsigned long with little endian byte order"""
self.write(pack("<L", val))
def write_beUS(self, val):
"""Write an unsigned short with big endian byte order"""
self.write(pack(">H", val))
def write_beUL(self, val):
"""Write an unsigned long with big endian byte order"""
self.write(pack(">L", val))
write_US = write_leUS # XXX should we default to this?
write_UL = write_leUL # XXX "
def read_beUL(self):
"""Return an unsigned long read with big endian byte order"""
return unpack(">L", self.read(4))[0]
# Set up properties BigEndian, LittleEndian, ImplicitVR, ExplicitVR.
# Big/Little Endian changes functions to read unsigned short or long, e.g. length fields etc
def _setLittleEndian(self, value):
self._LittleEndian = value
if value: # LittleEndian
self.read_US = self.read_leUS
self.read_UL = self.read_leUL
self.write_US = self.write_leUS
self.write_UL = self.write_leUL
self.read_tag = self.read_le_tag
else: # BigEndian
self.read_US = self.read_beUS
self.read_UL = self.read_beUL
self.write_US = self.write_beUS
self.write_UL = self.write_beUL
self.read_tag = self.read_be_tag
def _getLittleEndian(self):
return self._LittleEndian
def _setBigEndian(self, value):
self.is_little_endian = not value # note: must use self.is_little_endian not self._LittleEndian
def _getBigEndian(self):
return not self.is_little_endian
def _getImplicitVR(self):
return self._ImplicitVR
def _setImplicitVR(self, value):
self._ImplicitVR = value
def _setExplicitVR(self, value):
self.is_implicit_VR = not value
def _getExplicitVR(self):
return not self.is_implicit_VR
is_little_endian = property(_getLittleEndian, _setLittleEndian)
is_big_endian = property(_getBigEndian, _setBigEndian)
is_implicit_VR = property(_getImplicitVR, _setImplicitVR)
is_explicit_VR = property(_getExplicitVR, _setExplicitVR)
class DicomFileLike(DicomIO):
def __init__(self, file_like_obj):
self.parent = file_like_obj
self.parent_read = file_like_obj.read
self.write = getattr(file_like_obj, "write", self.no_write)
self.seek = file_like_obj.seek
self.tell = file_like_obj.tell
self.close = file_like_obj.close
self.name = getattr(file_like_obj, 'name', '<no filename>')
def no_write(self, bytes):
"""Used for file-like objects where no write is available"""
raise IOError, "This DicomFileLike object has no write() method"
def DicomFile(*args, **kwargs):
return DicomFileLike(open(*args, **kwargs))
def DicomStringIO(*args, **kwargs):
return DicomFileLike(StringIO(*args, **kwargs))
|