JsonFile.byId()   A
last analyzed

Complexity

Conditions 3

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 4
rs 10
c 0
b 0
f 0
1
import os
2
from operator import itemgetter
3
from niprov.dependencies import Dependencies
4
5
6
class JsonFile(object):
7
    """Stores provenance in a local text file encoded as json.
8
    """
9
10
    def __init__(self, dependencies=Dependencies()):
11
        self.filesys = dependencies.getFilesystem()
12
        self.json = dependencies.getSerializer()
13
        self.factory = dependencies.getFileFactory()
14
        self.pictureCache = dependencies.getPictureCache()
15
        url = dependencies.getConfiguration().database_url
16
        self.datafile = os.path.expanduser(url)
17
18
    def serializeAndWrite(self, images):
19
        jsonstr = self.json.serializeList(images)
20
        self.filesys.write(self.datafile, jsonstr)
21
22
    def add(self, image):
23
        """Add the provenance for one file to storage.
24
25
        Args:
26
            image (:class:`.BaseFile`): Image file to store.
27
        """
28
        current = self.all()
29
        current.append(image)
30
        self.serializeAndWrite(current)
31
        self.pictureCache.saveToDisk(for_=image)
32
33
    def update(self, image):
34
        """Save changed provenance for this file..
35
36
        Args:
37
            image (:class:`.BaseFile`): Image file that has changed.
38
        """
39
        current = self.all()
40
        for r in range(len(current)):
41
            if current[r].location.toString() == image.location.toString():
42
                current[r] = image
43
        self.serializeAndWrite(current)
44
45
    def all(self):
46
        """Retrieve all known provenance from storage.
47
48
        Returns:
49
            list: List of provenance for known files.
50
        """
51
        try:
52
            jsonstr = self.filesys.read(self.datafile)
53
        except IOError:
54
            return []
55
        return self.json.deserializeList(jsonstr)
56
57
    def byLocation(self, locationString):
58
        """Get the provenance for a file at the given location. 
59
60
        In the case of a dicom series, this returns the provenance for the 
61
        series.
62
63
        Args:
64
            locationString (str): Location of the image file.
65
66
        Returns:
67
            dict: Provenance for one image file.
68
        """
69
        for image in self.all():
70
            if image.location.toString() == locationString:
71
                return image
72
73
    def byLocations(self, listOfLocations):
74
        return [f for f in self.all() if f.location.toString() in listOfLocations]
75
76
    def getSeries(self, image):
77
        """Get the object that carries provenance for the series that the image 
78
        passed is in. 
79
80
        Args:
81
            image (:class:`.DicomFile`): File that is part of a series.
82
83
        Returns:
84
            :class:`.DicomFile`: Image object that caries provenance for the series.
85
        """
86
        seriesId = image.getSeriesId()
87
        if seriesId is None:
88
            return None
89
        for image in self.all():
90
            if 'seriesuid' in image.provenance and (
91
                image.provenance['seriesuid'] == seriesId):
92
                return image
93
94
    def updateApproval(self, fpath, approvalStatus):
95
        img = self.byLocation(fpath)
96
        img.provenance['approval'] = approvalStatus
97
        self.update(img)
98
99
    def latest(self, n=20):
100
        def dateTimeAdded(img):
101
            return img.provenance.get('added')
102
        sortedImages = sorted(self.all(), key=dateTimeAdded, reverse=True)
103
        return sortedImages[:n]
104
105
    def statistics(self):
106
        stats = {}
107
        images = self.all()
108
        stats['count'] = len(images)
109
        sizes = [img.provenance['size'] for img in images if 'size' in img.provenance]
110
        stats['totalsize'] = sum(sizes)
111
        return stats
112
113
    def byId(self, uid):
114
        for image in self.all():
115
            if image.provenance['id'] == uid:
116
                return image
117
118
    def byParents(self, listOfParentLocations):
119
        return [f for f in self.all() if set(listOfParentLocations).intersection(
120
            f.provenance.get('parents',[]))]
121
122
    def inquire(self, query):
123
        field = query.getFields()[0]
124
        matches = []
125
        for image in self.all():
126
            if field.name in image.provenance:
127
                if field.all:
128
                    if not image.provenance[field.name] in matches:
129
                        matches.append(image.provenance[field.name])
130
                else:
131
                    if image.provenance[field.name] == field.value:
132
                        matches.append(image)
133
        return matches
134
135
    def search(self, text):
136
        fields = ['location','user','subject','project','protocol',
137
                  'transformation','technique','modality']
138
        matches = []
139
        for image in self.all():
140
            score = 0
141
            for word in text.split():
142
                for field in fields:
143
                    if field in image.provenance:
144
                        score += image.provenance[field].count(word)
145
            if score > 0:
146
                matches.append((image, score))
147
        sortedResults = sorted(matches, key=itemgetter(1), reverse=True)
148
        return [i for i, s in sortedResults[:20]]
149
        
150
151