source: trunk/grails-app/domain/nl/tno/metagenomics/AssaySample.groovy @ 24

Last change on this file since 24 was 24, checked in by robert@…, 9 years ago

Improved export of fasta files and added properties to assaysamples

File size: 5.7 KB
Line 
1package nl.tno.metagenomics
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                                // Clone the sequencedata object
229                                def sd = dataList[ j ]?.clone();
230                               
231                                if( sd )
232                                        otherAssaySample.addToSequenceData( sd );
233                                       
234                                // Remove the old sequencedata object
235                                this.removeFromSequenceData( dataList[ j ] );
236                        }
237                }
238
239                // Copy run properties
240                if( otherAssaySample.run ) {
241                        otherAssaySample.run.removeFromAssaySamples( otherAssaySample );
242                }
243               
244                // Remove this sample from the run.
245                if( run ) {
246                        def copyRun = run;
247                        copyRun.removeFromAssaySamples( this );
248                        copyRun.addToAssaySamples( otherAssaySample );
249                } else {
250                        otherAssaySample.run = null;
251                }
252        }
253}
Note: See TracBrowser for help on using the repository browser.