Completed
Pull Request — master (#147)
by Jasper
01:31
created

MongoRepository.getSeries()   A

Complexity

Conditions 2

Size

Total Lines 16

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
c 0
b 0
f 0
dl 0
loc 16
rs 9.4285
1
import pymongo, copy, bson
2
from datetime import timedelta
3
from niprov.dependencies import Dependencies
4
5
6
class MongoRepository(object):
7
8
    def __init__(self, dependencies=Dependencies()):
9
        self.config = dependencies.getConfiguration()
10
        self.factory = dependencies.getFileFactory()
11
        self.pictures = dependencies.getPictureCache()
12
        client = pymongo.MongoClient(self.config.database_url)
13
        self.db = client.get_default_database()
14
15
    def byLocation(self, locationString):
16
        """Get the provenance for a file at the given location. 
17
18
        In the case of a dicom series, this returns the provenance for the 
19
        series.
20
21
        Args:
22
            locationString (str): Location of the image file.
23
24
        Returns:
25
            dict: Provenance for one image file.
26
        """
27
        record = self.db.provenance.find_one({'location':locationString})
28
        return self.inflate(record)
29
30
    def byLocations(self, listOfLocations):
31
        records = self.db.provenance.find({'location':{'$in':listOfLocations}})
32
        return [self.inflate(record) for record in records]
33
34
    def getSeries(self, image):
35
        """Get the object that carries provenance for the series that the image 
36
        passed is in. 
37
38
        Args:
39
            image (:class:`.DicomFile`): File that is part of a series.
40
41
        Returns:
42
            :class:`.DicomFile`: Image object that caries provenance for 
43
                         the series.
44
        """
45
        seriesUid = image.getSeriesId()
46
        if seriesUid is None:
47
            return None
48
        record = self.db.provenance.find_one({'seriesuid':seriesUid})
49
        return self.inflate(record)
50
51
    def add(self, image):
52
        """Add the provenance for one file to storage.
53
54
        Args:
55
            image (:class:`.BaseFile`): Image file to store.
56
        """
57
        self.db.provenance.insert_one(self.deflate(image))
58
59
    def update(self, image):
60
        """Save changed provenance for this file..
61
62
        Args:
63
            image (:class:`.BaseFile`): Image file that has changed.
64
        """
65
        self.db.provenance.update({'location':image.location.toString()}, 
66
            self.deflate(image))
67
68
    def updateApproval(self, locationString, approvalStatus):
69
        self.db.provenance.update({'location':locationString}, 
70
            {'$set': {'approval': approvalStatus}})
71
72
    def all(self):
73
        """Retrieve all known provenance from storage.
74
75
        Returns:
76
            list: List of provenance for known files.
77
        """
78
        records = self.db.provenance.find()
79
        return [self.inflate(record) for record in records]
80
81
    def latest(self):
82
        records = self.db.provenance.find().sort('added', -1).limit(20)
83
        return [self.inflate(record) for record in records]
84
85
    def statistics(self):
86
        grps = self.db.provenance.aggregate(
87
           [{'$group':
88
                 {
89
                   '_id': None,
90
                   'totalsize': { '$sum': '$size' },
91
                   'count': { '$sum': 1 }
92
                 }
93
            }])
94
        groups = list(grps)
95
        if len(list(groups)) == 0:
96
            return {'count':0}
97
        return list(groups)[0]
98
99
    def byId(self, uid):
100
        record = self.db.provenance.find_one({'id':uid})
101
        return self.inflate(record)
102
103
    def byParents(self, listOfParentLocations):
104
        records = self.db.provenance.find({'parents':{
105
            '$in':listOfParentLocations}})
106
        return [self.inflate(record) for record in records]
107
108
    def inquire(self, query):
109
        field = query.getFields()[0]
110
        if field.all:
111
            records = self.db.provenance.distinct(field.name)
112
            return records
113
        else:
114
            records = self.db.provenance.find({field.name:field.value})
115
            return [self.inflate(record) for record in records]
116
117
    def search(self, text):
118
        searchfields = ['location','user','subject','project','protocol',
119
                  'transformation','technique','modality']
120
        indexspec = [(field, pymongo.TEXT) for field in searchfields]
121
        self.db.provenance.create_index(indexspec, name='textsearch')
122
        records = self.db.provenance.find({'$text':{'$search': text}})
123
        return [self.inflate(record) for record in records]
124
125
    def deflate(self, img):
126
        record = copy.deepcopy(img.provenance)
127
        if 'duration' in record:
128
            record['duration'] = record['duration'].total_seconds()
129
        snapshotData = self.pictures.getBytes(for_=img)
130
        if snapshotData:
131
            record['_snapshot-data'] = bson.Binary(snapshotData)
132
        return record
133
134
    def inflate(self, record):
135
        if record is None:
136
            return None
137
        if 'duration' in record:
138
            record['duration'] = timedelta(seconds=record['duration'])
139
        img = self.factory.fromProvenance(record)
140
        if '_snapshot-data' in record:
141
            self.pictures.keep(record['_snapshot-data'], for_=img)
142
        return img
143
144