source: trunk/grails-app/domain/nl/tno/massSequencing/AssaySample.groovy @ 49

Last change on this file since 49 was 49, checked in by robert@…, 8 years ago
  • Added sequence length histograms
  • Fixed bugs in files that remained on the file system after uploading (while they shouldn't)
  • Added extra options in run- and assay screens
File size: 6.2 KB
Line 
1package nl.tno.massSequencing
2
3/**
4 * Represents a samples that is used in an assay.
5 *
6 * @author Robert Horlings (robert@isdat.nl)
7 *
8 */
9class AssaySample {
10        // To be computed in run time
11        private long _numSequences = -1;
12        private float _averageQuality = -1.0;
13        private long _numQualScores = -1;
14
15        Integer numUniqueSequences      // Number of unique sequences / OTUs. Is only available after preprocessing
16
17        String fwOligo
18        String fwMidName
19        String fwTotalSeq
20        String fwMidSeq
21        String fwPrimerSeq
22       
23        String revOligo
24        String revMidName
25        String revTotalSeq
26        String revMidSeq
27        String revPrimerSeq
28
29        static belongsTo  = [ assay: Assay, sample: Sample, run: Run ]
30        static hasMany    = [ sequenceData: SequenceData ]
31
32        static constraints = {
33                numUniqueSequences(nullable: true)
34                fwOligo(nullable: true)
35                fwMidName(nullable: true)
36                fwTotalSeq(nullable:true)
37                fwMidSeq(nullable:true)
38                fwPrimerSeq(nullable:true)
39                revOligo(nullable: true)
40                revMidName(nullable: true)
41                revTotalSeq(nullable:true)
42                revMidSeq(nullable:true)
43                revPrimerSeq(nullable:true)
44                run(nullable: true);
45        }
46
47        static mapping = {
48                columns {
49                        numSequences index:'numsequences_idx'
50                }
51                sequenceData cascade: "all-delete-orphan"
52        }
53
54        /**
55         * Returns the number of files in the system, belonging to this
56         * assay-sample combination.
57         *
58         * @return
59         */
60        public int numFiles() {
61                if( !sequenceData )
62                        return 0
63
64                int numFiles = 0;
65                sequenceData.each { numFiles += it.numFiles() }
66
67                return numFiles;
68        }
69
70        /**
71         * Returns the number of sequence files in the system, belonging to this
72         * assay-sample combination.
73         *
74         * @return
75         */
76        public int numSequenceFiles() {
77                if( !sequenceData )
78                        return 0
79
80                int numFiles = 0;
81                sequenceData.each {
82                        if( it.sequenceFile )
83                                numFiles++
84                }
85
86                return numFiles;
87        }
88       
89        /**
90         * Returns the number of quality files in the system, belonging to this
91         * assay-sample combination.
92         *
93         * @return
94         */
95        public int numQualityFiles() {
96                if( !sequenceData )
97                        return 0
98
99                int numFiles = 0;
100                sequenceData.each {
101                        if( it.qualityFile )
102                                numFiles++
103                }
104
105                return numFiles;
106        }
107       
108        /**
109         * Returns the number of sequences in the files on the system, belonging to this
110         * assay-sample combination.
111         *
112         * @return
113         */
114        public long numSequences() {
115                if( _numSequences > -1 )
116                        return _numSequences;
117
118                if( !sequenceData )
119                        return 0
120
121                long numSequences = 0;
122                sequenceData.each { numSequences += it.numSequences }
123
124                // Save as cache
125                _numSequences = numSequences;
126
127                return numSequences;
128        }
129       
130        /**
131         * Returns the number of quality scores in the files on the system, belonging to this
132         * assay-sample combination.
133         *
134         * @return
135         */
136        public long numQualScores() {
137                if( _numQualScores > -1 )
138                        return _numQualScores;
139
140                if( !sequenceData )
141                        return 0
142
143                long numQualScores = 0;
144                sequenceData.each { numQualScores += it.numQualScores() }
145
146                // Save as cache
147                _numQualScores = numQualScores;
148
149                return numQualScores;
150        }
151        /**
152         * Returns the average quality of the sequences in the files on the system,
153         * belonging to this assay-sample combination.
154         *
155         * @return
156         */
157        public float averageQuality() {
158                if( _averageQuality > -1 )
159                        return _averageQuality;
160
161                if( !sequenceData )
162                        return 0.0
163
164                int numSequences = 0;
165                float averageQuality = 0.0;
166
167                sequenceData.each {
168                        numSequences += it.numSequences
169                        averageQuality = averageQuality + ( it.averageQuality - averageQuality ) / numSequences * it.numSequences;
170                }
171
172                // Save as cache
173                _averageQuality = averageQuality;
174
175                return averageQuality;
176        }
177       
178        /**
179         * Reset the statistics to their default value, in order to ensure that the values are recomputed next time.
180         */
181        public void resetStats() {
182                _numSequences = -1;
183                _numQualScores = -1;
184                _averageQuality = -1;
185        }
186       
187        /**
188         * Check whether this assay-sample combination contains information that should be saved in trash on a delete
189         * @return
190         */
191        public boolean containsData() {
192                return  fwOligo || fwMidName || fwTotalSeq || fwMidSeq || fwPrimerSeq ||
193                                revOligo || revMidName || revTotalSeq || revMidSeq || revPrimerSeq ||
194                                numFiles() > 0;
195        }
196       
197        /**
198         * Move information that should be kept on delete to another assaySample object.
199         * 
200         * N.B. The sequencedata objects are really moved, so removed from the original object!
201         * 
202         * @param otherAssaySample      Object to move
203         */
204        public void moveValuableDataTo( AssaySample otherAssaySample ) {
205                // Copy properties
206                otherAssaySample.fwOligo                = fwOligo;
207                otherAssaySample.fwMidName              = fwMidName;
208                otherAssaySample.fwTotalSeq     = fwTotalSeq;
209                otherAssaySample.fwMidSeq               = fwMidSeq;
210                otherAssaySample.fwPrimerSeq    = fwPrimerSeq;
211               
212                otherAssaySample.revOligo               = revOligo;
213                otherAssaySample.revMidName             = revMidName;
214                otherAssaySample.revTotalSeq    = revTotalSeq;
215                otherAssaySample.revMidSeq              = revMidSeq;
216                otherAssaySample.revPrimerSeq   = revPrimerSeq;
217
218                // Move attached data
219                def dataList = [] + sequenceData?.toList()
220                def otherAssay = otherAssaySample.assay;
221               
222                if( dataList && dataList.size() > 0 ) {
223                        for( def j = dataList.size() - 1; j >= 0; j-- ) {
224                                // Copy data to a new sequencedata object.
225                                // Just moving the sequencedata object to the other assay sample resulted
226                                // in a 'deleted object would be re-saved by cascade' exception
227                               
228                                if( dataList[ j ] ) {
229                                        // Clone the sequencedata object
230                                        def sd = dataList[ j ]?.clone();
231                                       
232                                        if( sd )
233                                                otherAssaySample.addToSequenceData( sd );
234                                               
235                                        // Remove the old sequencedata object
236                                        this.removeFromSequenceData( dataList[ j ] );
237                                }
238                        }
239                }
240
241                // Copy run properties
242                if( otherAssaySample.run ) {
243                        otherAssaySample.run.removeFromAssaySamples( otherAssaySample );
244                }
245               
246                // Remove this sample from the run.
247                if( run ) {
248                        def copyRun = run;
249                        copyRun.removeFromAssaySamples( this );
250                        copyRun.addToAssaySamples( otherAssaySample );
251                } else {
252                        otherAssaySample.run = null;
253                }
254        }
255       
256       
257        /**
258         * Delete all sequences from a sample
259         * @param assaySample
260         * @return
261         */
262        public int deleteSequenceData() {
263                if( !sequenceData )
264                        return 0;
265               
266                def numFiles = 0;
267                sequenceData.each { sequenceData ->
268                        numFiles += sequenceData.numFiles();
269                 
270                        removeFromSequenceData( sequenceData );
271                        sequenceData.delete(flush:true);
272                }
273
274                resetStats();
275                save();
276               
277                return numFiles;
278        }
279
280}
Note: See TracBrowser for help on using the repository browser.