root/trunk/src/groovy/dbnp/query/SampleSearch.groovy @ 1458

Revision 1458, 6.5 KB (checked in by robert@…, 3 years ago)

- Implemented a cache for module rest calls, to increase performance (see moduleCommunicationService)
- Implemented searching in module data.

  • Property svn:keywords set to Rev Author Date
Line 
1/**
2 * SampleSearch Domain Class
3 *
4 * This class provides querying capabilities for searching for samples
5 *
6 * @author  Robert Horlings (robert@isdat.nl)
7 * @since       20110118
8 * @package     dbnp.query
9 *
10 * Revision information:
11 * $Rev$
12 * $Author$
13 * $Date$
14 */
15package dbnp.query
16
17import dbnp.studycapturing.*
18import org.dbnp.gdt.*
19
20class SampleSearch extends Search {
21       
22        public SampleSearch() {
23                this.entity = "Sample";
24        }
25
26        /**
27         * Searches for samples based on the given criteria. All criteria have to be satisfied and
28         * criteria for the different entities are satisfied as follows:
29         *
30         *              Sample.title = 'abc'           
31         *                              Only samples are returned from studies with title 'abc'
32         *             
33         *              Subject.species = 'human'
34         *                              Only samples are returned from subjects with species = 'human' 
35         *
36         *              Sample.name = 'sample 1'
37         *                              Only samples are returned with name = 'sample 1'
38         *
39         *              Event.startTime = '0s'
40         *                              Only samples are returned from subjects that have had an event with start time = '0s' 
41         *
42         *              SamplingEvent.startTime = '0s'
43         *                              Only samples are returned that have originated from a sampling event with start time = '0s' 
44         *
45         *              Assay.module = 'metagenomics'
46         *                              Only samples are returned that have been processed in an assay with module = metagenomics 
47         *
48         * When searching for more than one criterion per entity, these are taken combined. Searching for
49         *
50         *              Subject.species = 'human'
51         *              Subject.name = 'Jan'
52         *
53         *  will result in all samples from a human subject named 'Jan'. Samples from a mouse subject
54         *  named 'Jan' or a human subject named 'Kees' won't satisfy the criteria.
55         *     
56         */
57        @Override
58        void execute() {
59                // TODO: check for authorization for these studies?
60
61                // If no criteria are found, return all samples
62                if( !criteria || criteria.size() == 0 ) {
63                        results = Sample.list();
64                        return;
65                }
66
67                // We expect the sample criteria to be the most discriminative, and discard
68                // the most samples. (e.g. by searching on sample title of sample type). For
69                // that reason we first look through the list of studies. However, when the
70                // user didn't enter any sample criteria, this will be an extra step, but doesn't
71                // cost much time to process.
72                def samples = []
73                if( getEntityCriteria( 'Study' ).size() > 0 ) {
74                        def studies = Study.findAll();
75                       
76                        studies = filterOnStudyCriteria( studies );
77                       
78                        if( studies.size() == 0 ) {
79                                results = [];
80                                return;
81                        }
82                       
83                        def c = Sample.createCriteria()
84                        samples = c.list {
85                                'in'( 'parent', studies )
86                        }
87                } else {
88                        samples = Sample.findAll()
89                }
90
91                samples = filterOnSubjectCriteria( samples );
92                samples = filterOnSampleCriteria( samples );
93                samples = filterOnEventCriteria( samples );
94                samples = filterOnSamplingEventCriteria( samples );
95                samples = filterOnAssayCriteria( samples );
96               
97                samples = filterOnModuleCriteria( samples );
98               
99                // Save matches
100                results = samples;
101        }
102
103        /**
104         * Filters the given list of samples on the sample criteria
105         * @param samples       Original list of samples
106         * @return                      List with all samples that match the Sample-criteria
107         */
108        protected List filterOnStudyCriteria( List studies ) {
109                return filterOnTemplateEntityCriteria(studies, "Study", { study, criterion -> return criterion.getFieldValue( study ) })
110        }
111
112        /**
113         * Filters the given list of samples on the subject criteria
114         * @param samples       Original list of samples
115         * @return                      List with all samples that match the Subject-criteria
116         */
117        protected List filterOnSubjectCriteria( List samples ) {
118                return filterOnTemplateEntityCriteria(samples, "Subject", { sample, criterion ->
119                        return criterion.getFieldValue( sample.parentSubject );
120                })
121        }
122
123        /**
124         * Filters the given list of samples on the sample criteria
125         * @param samples       Original list of samples
126         * @return                      List with all samples that match the sample-criteria
127         */
128        protected List filterOnSampleCriteria( List samples ) {
129                return filterOnTemplateEntityCriteria(samples, "Sample", { sample, criterion ->
130                        return criterion.getFieldValue( sample );
131                })
132        }
133
134        /**
135         * Filters the given list of samples on the event criteria
136         * @param samples       Original list of samples
137         * @return                      List with all samples that match the event-criteria
138         */
139        protected List filterOnEventCriteria( List samples ) {
140                return filterOnTemplateEntityCriteria(samples, "Event", { sample, criterion ->
141                        if( !sample || !sample.parentEventGroup || !sample.parentEventGroup.events || sample.parentEventGroup.events.size() == 0 )
142                                return null
143
144                        return criterion.getFieldValue( sample.parentEventGroup.events.toList() );
145                })
146        }
147
148        /**
149         * Filters the given list of samples on the sampling event criteria
150         * @param samples       Original list of samples
151         * @return                      List with all samples that match the event-criteria
152         */
153        protected List filterOnSamplingEventCriteria( List samples ) {
154                return filterOnTemplateEntityCriteria(samples, "SamplingEvent", { sample, criterion ->
155                        return criterion.getFieldValue( sample.parentEvent );
156                })
157        }
158
159        /**
160         * Filters the given list of samples on the assay criteria
161         * @param samples       Original list of samples
162         * @return                      List with all samples that match the assay-criteria
163         */
164        protected List filterOnAssayCriteria( List samples ) {
165                if( !samples?.size() )
166                        return [];
167
168                if( getEntityCriteria( 'Assay' ).size() == 0 )
169                        return samples
170                       
171                // There is no sample.assays property, so we have to look for assays another way: just find
172                // all assays that match the criteria
173                def criteria = getEntityCriteria( 'Assay' );
174                def assays = filterEntityList( Assay.list(), criteria, { assay, criterion ->
175                        if( !assay )
176                                return false
177
178                        return criterion.matchOne( assay );
179                });
180               
181                // If no assays match these criteria, then no samples will match either
182                if( assays.size() == 0 )
183                        return [];
184               
185                // Save sample data for later use
186                saveResultFields( samples, criteria, { sample, criterion ->
187                         def sampleAssays = Assay.findByStudy( sample.parent ).findAll { it.samples?.contains( sample ) };
188                         if( sampleAssays && sampleAssays.size() > 0 )
189                                return sampleAssays.collect( criterion.getFieldValue( it ) )
190                        else
191                                return null
192                });
193                       
194                // Now filter the samples on whether they are attached to the filtered assays
195                return samples.findAll { sample ->
196                        if( !sample.parent )
197                                return false;
198                       
199                        def studyAssays = assays.findAll { it.parent.equals( sample.parent ); }
200                       
201                        // See if this sample is present in any of the matching assays. If so,
202                        // this sample matches the criteria
203                        for( def assay in studyAssays ) {
204                                if( assay.samples?.contains( sample ) )
205                                        return true;
206                        }
207                       
208                        return false;
209                }
210        }
211}
Note: See TracBrowser for help on using the browser.