1
|
|
|
from datetime import datetime |
2
|
|
|
from niprov.basefile import BaseFile |
3
|
|
|
from niprov.libraries import Libraries |
4
|
|
|
|
5
|
|
|
|
6
|
|
|
class DicomFile(BaseFile): |
7
|
|
|
|
8
|
|
|
def __init__(self, location, **kwargs): |
9
|
|
|
super(DicomFile, self).__init__(location, **kwargs) |
10
|
|
|
self.libs = self.dependencies.getLibraries() |
11
|
|
|
|
12
|
|
|
def inspect(self): |
13
|
|
|
""" |
14
|
|
|
Inspect the DICOM file attributes. |
15
|
|
|
|
16
|
|
|
If a general AcquisitionDateTime attribute is not present, the |
17
|
|
|
SeriesDate and SeriesTime will be used to set the :ref:`field-acquired` |
18
|
|
|
provenance field. |
19
|
|
|
|
20
|
|
|
Returns: |
21
|
|
|
dict: Provenance for the inspected file. |
22
|
|
|
""" |
23
|
|
|
super(DicomFile, self).inspect() |
24
|
|
|
img = self.libs.dicom.read_file(self.path) |
25
|
|
|
self.provenance['subject'] = img.PatientID |
26
|
|
|
self.provenance['protocol'] = img.SeriesDescription |
27
|
|
|
self.provenance['seriesuid'] = img.SeriesInstanceUID |
28
|
|
|
self.provenance['filesInSeries'] = [self.path] |
29
|
|
|
self.provenance['duration'] = img.AcquisitionDuration |
30
|
|
|
self.provenance['subject-position'] = img.PatientPosition |
31
|
|
|
self.provenance['water-fat-shift'] = img[0x2001, 0x1022].value |
32
|
|
|
if hasattr(img, 'NumberOfFrames'): |
33
|
|
|
self.provenance['multiframeDicom'] = True |
34
|
|
|
nframes = int(img.NumberOfFrames) |
35
|
|
|
else: |
36
|
|
|
self.provenance['multiframeDicom'] = False |
37
|
|
|
nframes = len(self.provenance['filesInSeries']) |
38
|
|
|
if hasattr(img, 'Rows'): |
39
|
|
|
self.provenance['dimensions'] = [int(img.Rows), int(img.Columns), |
40
|
|
|
nframes] |
41
|
|
|
if hasattr(img, 'AcquisitionDateTime'): |
42
|
|
|
acqstring = img.AcquisitionDateTime.split('.')[0] |
43
|
|
|
dateformat = '%Y%m%d%H%M%S' |
44
|
|
|
self.provenance['acquired'] = datetime.strptime(acqstring,dateformat) |
45
|
|
|
else: |
46
|
|
|
dateformat = '%Y%m%d' |
47
|
|
|
acqdate = datetime.strptime(img.SeriesDate, dateformat) |
48
|
|
|
acqtime = datetime.fromtimestamp(float(img.SeriesTime)).time() |
49
|
|
|
combined = datetime.combine(acqdate, acqtime) |
50
|
|
|
self.provenance['acquired'] = combined.replace(microsecond=0) |
51
|
|
|
self.provenance['modality'] = 'MRI' |
52
|
|
|
return self.provenance |
53
|
|
|
|
54
|
|
|
|
55
|
|
|
def getSeriesId(self): |
56
|
|
|
""" |
57
|
|
|
Return the DICOM "SeriesInstanceUID" that all files in this series |
58
|
|
|
have in common. |
59
|
|
|
|
60
|
|
|
Returns: |
61
|
|
|
str: A string uniquely identifying files belonging to this series. |
62
|
|
|
""" |
63
|
|
|
if not 'seriesuid' in self.provenance: |
64
|
|
|
self.inspect() |
65
|
|
|
return self.provenance['seriesuid'] |
66
|
|
|
|
67
|
|
|
def mergeWith(self, img): |
68
|
|
|
""" |
69
|
|
|
Add a single DICOM file object to this series. |
70
|
|
|
|
71
|
|
|
The file will be stored in provenance in the 'filesInSeries' list. |
72
|
|
|
""" |
73
|
|
|
self.provenance['filesInSeries'].append(img.path) |
74
|
|
|
self._updateNfilesDependentFields() |
75
|
|
|
self.status = 'series-new-file' |
76
|
|
|
return self |
77
|
|
|
|
78
|
|
|
def hasFile(self, other): |
79
|
|
|
return other.path in self.provenance['filesInSeries'] |
80
|
|
|
|
81
|
|
|
def _updateNfilesDependentFields(self): |
82
|
|
|
if (not self.provenance['multiframeDicom']) and 'dimensions' in self.provenance: |
83
|
|
|
nfiles = len(self.provenance['filesInSeries']) |
84
|
|
|
self.provenance['dimensions'][2] = nfiles |
85
|
|
|
|
86
|
|
|
|