|
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 _updateNfilesDependentFields(self): |
|
79
|
|
|
if (not self.provenance['multiframeDicom']) and 'dimensions' in self.provenance: |
|
80
|
|
|
nfiles = len(self.provenance['filesInSeries']) |
|
81
|
|
|
self.provenance['dimensions'][2] = nfiles |
|
82
|
|
|
|
|
83
|
|
|
|
|
84
|
|
|
|