source: trunk/test/unit/nl/tno/metagenomics/integration/TrashServiceTests.groovy @ 9

Last change on this file since 9 was 9, checked in by robert@…, 9 years ago
File size: 18.5 KB
Line 
1package nl.tno.metagenomics.integration
2
3import grails.test.*
4import nl.tno.metagenomics.*
5
6class TrashServiceTests extends GrailsUnitTestCase {
7        def trashService
8    Study trash
9       
10        protected void setUp() {
11        super.setUp()
12                mockDomain( Study );
13                mockDomain( Sample );
14                mockDomain( Assay );
15                mockDomain( AssaySample );
16                mockDomain( Run );
17                mockDomain( SequenceData );
18               
19                mockLogging( TrashService.class, true );
20               
21                trashService = new TrashService();
22
23                setupStudy();
24    }
25
26    protected void tearDown() {
27        super.tearDown()
28    }
29
30        protected void setupStudy() {
31                // Create a study trashcan
32                trash = new Study( name: "Trashcan", studyToken: "trashcan", trashcan: true );
33                trash.save(flush:true);
34               
35                // Setup a study with two assays, 4 samples
36                Study s = new Study( name: "Study 1", studyToken: "study1" );
37
38                s.save(flush:true);
39               
40                // Create two assays
41                Assay a1 = new Assay( id: 1, name: "Assay 1", assayToken: "assay1", study: s );
42                Assay a2 = new Assay( id: 2, name: "Assay 2", assayToken: "assay2", study: s );
43                Assay a3 = new Assay( id: 3, name: "Assay 3", assayToken: "assay3", study: s );
44                def assays = [a1, a2, a3];
45
46                assays.each { s.addToAssays( it ); it.save( flush: true ); }
47               
48                // Create four samples
49                Sample sa1 = new Sample( id: 1, name: "Sample 1a", subject: "S1", event: "event", sampleToken: "sample1a", study: s );
50                Sample sa2 = new Sample( id: 2, name: "Sample 1b", subject: "S2", event: "event", sampleToken: "sample1b", study: s );
51                Sample sa3 = new Sample( id: 3, name: "Sample 2a", subject: "S3", event: "event", sampleToken: "sample2a", study: s );
52                Sample sa4 = new Sample( id: 4, name: "Sample 2b", subject: "S4", event: "event", sampleToken: "sample2b", study: s );
53                Sample sa5 = new Sample( id: 5, name: "Sample 3a", subject: "S5", event: "event", sampleToken: "sample3a", study: s );
54                def samples = [sa1, sa2, sa3, sa4, sa5]
55               
56                samples.each { s.addToSamples( it ); it.save(flush:true); }
57               
58                s.save(flush:true);
59               
60                // Create a single run
61                Run run = new Run( name: "abc" );
62                run.save(flush:true);
63               
64                // Create desired combinations of samples and assays
65                // Such that: assay1 has 2 samples with data, assay2 has 1 sample with data and assay3 has no samples with data
66           AssaySample as1a = new AssaySample( oligoNumber: "123", tagSequence: "abc", tagName: "L391", sample: sa1, assay: a1 );
67           AssaySample as1b = new AssaySample( oligoNumber: "200", tagSequence: "def", tagName: "L397", sample: sa2, assay: a1 );
68           AssaySample as2a = new AssaySample( oligoNumber: "300", tagSequence: "ghi", tagName: "L421", sample: sa3, assay: a2 );
69           AssaySample as2b = new AssaySample( id: 12, sample: sa4, assay: a2);
70           AssaySample as3a = new AssaySample( sample: sa5, assay: a3);
71           def assaySamples= [as1a, as1b, as2a, as2b, as3a]
72
73           a1.addToAssaySamples( as1a ); sa1.addToAssaySamples( as1a ); run.addToAssaySamples( as1a );
74           as1a.save(flush:true);
75           
76           a1.addToAssaySamples( as1b ); sa2.addToAssaySamples( as1b ); run.addToAssaySamples( as1b );
77           as1b.save(flush:true);
78
79           a2.addToAssaySamples( as2a ); sa3.addToAssaySamples( as2a ); run.addToAssaySamples( as2a );
80           as2a.save(flush:true);
81
82           a2.addToAssaySamples( as2b ); sa4.addToAssaySamples( as2b ); run.addToAssaySamples( as2b );
83           as2b.save(flush:true);
84
85           a3.addToAssaySamples( as3a ); sa5.addToAssaySamples( as3a ); run.addToAssaySamples( as3a );
86           as3a.save(flush:true);
87           
88           assert as1a.sample.name == "Sample 1a"
89           
90           // Save samples and assays again
91           assays.each { it.save(flush:true); }
92           samples.each { it.save(flush:true); }
93           run.save(flush:true);
94           
95           // Add sequencedata objects to as1a and as1b
96           SequenceData sd1 = new SequenceData( assaySample: as1a, sequenceFile: "fasta1", qualityFile: "qual1", numSequences: 100, averageQuality: 10.0 );
97           SequenceData sd2 = new SequenceData( assaySample: as1a, sequenceFile: "fasta2", qualityFile: "qual2", numSequences: 30, averageQuality: 14.0 );
98           SequenceData sd3 = new SequenceData( assaySample: as1b, sequenceFile: "fasta3", qualityFile: "qual3", numSequences: 2000, averageQuality: 17.0 );
99           def sequenceData = [sd1, sd2, sd3];
100           
101           as1a.addToSequenceData( sd1 );
102           as1a.addToSequenceData( sd2 );
103           as1b.addToSequenceData( sd3 );
104           
105           as1a.save(flush:true); as1b.save(flush:true);
106           sequenceData.each { it.save(flush:true); }
107        }
108       
109        protected void setupTrash() {
110                // Create a study trashcan
111                trash = Study.findByStudyToken( "trashcan" );
112               
113                // Create a trash assay
114                Assay a1 = new Assay( id: 100, name: "Trash Assay 1", assayToken: "trash_assay1", study: trash );
115                def assays = [a1];
116
117                assays.each { trash.addToAssays( it ); it.save( flush: true ); }
118               
119                // Create three samples, two originally also present in assay 1, the other one isn't
120                Sample sa1 = new Sample( id: 101, name: "Sample 1a", sampleToken: "tsample1a", subject: "fromtrash: S1", event: "fromtrash: event", study: trash );
121                Sample sa2 = new Sample( id: 102, name: "Sample 1b", sampleToken: "tsample1b", subject: "fromtrash: S2", event: "fromtrash: event", study: trash );
122                Sample sa3 = new Sample( id: 103, name: "Sample 2a", sampleToken: "tsample2a", subject: "fromtrash: S3", event: "fromtrash: event", study: trash );
123                def samples = [sa1, sa2, sa3]
124               
125                samples.each { trash.addToSamples( it ); it.save(flush:true); }
126               
127                trash.save(flush:true);
128               
129           // Create a single run in order to be able to save sequencedata
130           Run run = new Run( name: "trashrun" );
131           run.save(flush:true);
132
133                // Create desired combinations of samples and assays
134                // Such that: assay1 has 2 samples with data, assay2 has 1 sample with data and assay3 has no samples with data
135           AssaySample as1a = new AssaySample( id: 102, oligoNumber: "fromtrash: 1", tagSequence: "fromtrash: abc", sample: sa1, assay: a1 );
136           AssaySample as1b = new AssaySample( oligoNumber: "fromtrash: 2", tagSequence: "fromtrash: def", sample: sa2, assay: a1 );
137           AssaySample as2a = new AssaySample( oligoNumber: "fromtrash: 3", tagSequence: "fromtrash: ghi", sample: sa3, assay: a1 );
138           def assaySamples= [as1a, as1b, as2a]
139
140           a1.addToAssaySamples( as1a ); sa1.addToAssaySamples( as1a ); run.addToAssaySamples( as1a );
141           as1a.save(flush:true);
142           
143           a1.addToAssaySamples( as1b ); sa2.addToAssaySamples( as1b ); run.addToAssaySamples( as1b );
144           as1b.save(flush:true);
145
146           a1.addToAssaySamples( as2a ); sa3.addToAssaySamples( as2a ); run.addToAssaySamples( as2a );
147           as2a.save(flush:true);
148
149           // Save samples and assays again
150           assays.each { it.save(flush:true); }
151           samples.each { it.save(flush:true); }
152           run.save( flush:true );
153           
154           // Add sequencedata objects to as1a and as1b
155           SequenceData sd1 = new SequenceData( assaySample: as1a, sequenceFile: "fromtrash: fasta1", qualityFile: "fromtrash: qual1", numSequences: 80, averageQuality: 11.0 );
156           SequenceData sd2 = new SequenceData( assaySample: as1a, sequenceFile: "fromtrash: fasta2", qualityFile: "fromtrash: qual2", numSequences: 520, averageQuality: 14.0 );
157           SequenceData sd3 = new SequenceData( assaySample: as1b, sequenceFile: "fromtrash: fasta3", qualityFile: "fromtrash: qual3", numSequences: 2000, averageQuality: 17.0 );
158           def sequenceData = [sd1, sd2, sd3];
159           
160           as1a.addToSequenceData( sd1 );
161           as1a.addToSequenceData( sd2 );
162           as1b.addToSequenceData( sd3 );
163           
164           as1a.save(flush:true); as1b.save(flush:true);
165           sequenceData.each { it.save(flush:true); }
166        }
167       
168    void testStudyTrash() {
169                def study = Study.findByStudyToken( "study1" );
170               
171                // Check whether the starting condition is correct
172                assert trash instanceof Study
173                assert study instanceof Study
174                assert study.assays?.size() == 3;
175                assert ( !trash.assays || trash.assays.size() == 0 );
176               
177                // Move data to trash and delete study
178                trashService.moveToTrash( study );
179               
180                // Check whether the study is really removed
181                assert null == Study.findByStudyToken( "study1" );
182               
183                // Check whether only the assays were kept that contain data
184                assert trash.assays.size() == 2;
185               
186                // Check whether only the assaysamples were kept that contain data
187                def assaySamples = trash.assays*.assaySamples.flatten().unique();
188                assert assaySamples.size() == 3;
189               
190                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
191                assert assaySample
192                assert assaySample.oligoNumber == "123"
193                assert assaySample.tagSequence == "abc"
194                assert assaySample.sample.subject == "S1"
195                assert assaySample.sample.event == "event"
196                assert assaySample.sequenceData.size() == 2
197
198                assaySample = assaySamples.find { it.sample?.name == "Sample 1b"; }
199                assert assaySample
200                assert assaySample.oligoNumber == "200"
201                assert assaySample.tagSequence == "def"
202                assert assaySample.sample.subject == "S2"
203                assert assaySample.sample.event == "event"
204                assert assaySample.sequenceData.size() == 1
205
206                assaySample = assaySamples.find { it.sample?.name == "Sample 2a"; }
207                assert assaySample
208                assert assaySample.oligoNumber == "300"
209                assert assaySample.tagSequence == "ghi"
210                assert assaySample.sample.subject == "S3"
211                assert assaySample.sample.event == "event"
212                assert !assaySample.sequenceData || assaySample.sequenceData.size() == 0
213
214                // Check whether the assay samples contain the right sequence data
215                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
216               
217                // Filter null values
218                sequenceData = sequenceData.findAll { it != null };
219                assert sequenceData.size() == 3;
220               
221                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
222                assert sd
223                assert sd.qualityFile == "qual1" 
224                assert sd.numSequences == 100 
225                assert sd.averageQuality == 10.0
226                assert sd.sample.assay.name == "Assay 1"
227                assert sd.sample.sample.name == "Sample 1a"
228               
229                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
230                assert sd
231                assert sd.qualityFile == "qual2"
232                assert sd.numSequences == 30
233                assert sd.averageQuality == 14.0
234                assert sd.sample.assay.name == "Assay 1"
235                assert sd.sample.sample.name == "Sample 1a"
236               
237                sd = sequenceData.find { it.sequenceFile == "fasta3"; }
238                assert sd
239                assert sd.qualityFile == "qual3"
240                assert sd.numSequences == 2000
241                assert sd.averageQuality == 17.0
242                assert sd.sample.assay.name == "Assay 1"
243                assert sd.sample.sample.name == "Sample 1b"
244    }
245       
246        void testAssayTrash() {
247                def study = Study.findByStudyToken( "study1" );
248                def assay = study.assays.find { it.assayToken == "assay1" };
249               
250                // Check whether the starting condition is correct
251                assert trash instanceof Study
252                assert assay instanceof Assay
253                assert assay.assaySamples.size() == 2;
254                assert ( !trash.assays || trash.assays.size() == 0 );
255               
256                // Move data to trash and delete study
257                trashService.moveToTrash( assay );
258               
259                // Check whether the study itself still exists
260                study = Study.findByStudyToken( "study1" )
261                assert study
262                assay = study.assays.find { it.assayToken == "assay1" };
263               
264                study.assays.each { 
265                        println it.name + ", " + it.assaySamples?.size()
266                }
267                assert !assay
268                assert study.assays.size() == 2
269               
270                // Check whether the assay is really removed
271                assay = Assay.findByAssayToken( "assay1" );
272                assert !assay
273               
274                // Check whether the assay samples also have been removed
275                // assert AssaySample.list().findAll { it.assay?.study?.studyToken == "study1" && it.assay?.assayToken == "assay1" }.size() == 0
276               
277                // Check whether only the assays were kept that contain data
278                assert trash.assays.size() == 1;
279                assert trash.samples.size() == 2;
280               
281                // Check whether only the assaysamples were kept that contain data
282                def assaySamples = trash.assays*.assaySamples.flatten().unique();
283                assert assaySamples.size() == 2;
284               
285                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
286                assert assaySample
287                assert assaySample.oligoNumber == "123"
288                assert assaySample.tagSequence == "abc"
289                assert assaySample.sample.subject == "S1"
290                assert assaySample.sample.event == "event"
291                assert assaySample.sequenceData.size() == 2
292
293                assaySample = assaySamples.find { it.sample?.name == "Sample 1b"; }
294                assert assaySample
295                assert assaySample.oligoNumber == "200"
296                assert assaySample.tagSequence == "def"
297                assert assaySample.sample.subject == "S2"
298                assert assaySample.sample.event == "event"
299                assert assaySample.sequenceData.size() == 1
300
301                // Check whether the assay samples contain the right sequence data
302                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
303               
304                // Filter null values
305                sequenceData = sequenceData.findAll { it != null };
306                assert sequenceData.size() == 3;
307               
308                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
309                assert sd
310                assert sd.qualityFile == "qual1"
311                assert sd.numSequences == 100
312                assert sd.averageQuality == 10.0
313                assert sd.sample.assay.name == "Assay 1"
314                assert sd.sample.sample.name == "Sample 1a"
315               
316                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
317                assert sd
318                assert sd.qualityFile == "qual2"
319                assert sd.numSequences == 30
320                assert sd.averageQuality == 14.0
321                assert sd.sample.assay.name == "Assay 1"
322                assert sd.sample.sample.name == "Sample 1a"
323               
324                sd = sequenceData.find { it.sequenceFile == "fasta3"; }
325                assert sd
326                assert sd.qualityFile == "qual3"
327                assert sd.numSequences == 2000
328                assert sd.averageQuality == 17.0
329                assert sd.sample.assay.name == "Assay 1"
330                assert sd.sample.sample.name == "Sample 1b"
331        }
332       
333        void testSampleTrash() {
334                def study = Study.findByStudyToken( "study1" );
335                def sample = study.samples.find { it.sampleToken == "sample1a" };
336                def assay
337               
338                // Check whether the starting condition is correct
339                assert trash instanceof Study
340                assert sample instanceof Sample
341                assert sample.assaySamples.size() == 1;
342                assert ( !trash.assays || trash.assays.size() == 0 );
343               
344                // Move data to trash and delete study
345                trashService.moveToTrash( sample );
346               
347                // Check whether the study and the assay itself still exists
348                study = Study.findByStudyToken( "study1" )
349                assert study
350                assay = study.assays.find { it.assayToken == "assay1" };
351                assert assay
352                assert study.assays.size() == 3
353               
354                // Check whether the sample is really removed
355                sample = Sample.findBySampleToken( "sample1a" );
356                assert !sample
357                sample = study.samples.find { it.sampleToken == "sample1a" }
358                assert !sample
359
360                // Check whether the assay samples also have been removed
361                //assert AssaySample.list().findAll { it.sample?.study?.studyToken == "study1" && it.sample?.sampleToken == "assay1" }.size() == 0
362                               
363                // Check whether only the assays were kept that contain data
364                assert trash.assays.size() == 1;
365                assert trash.samples.size() == 1;
366               
367                // Check whether only the assaysamples were kept that contain data and belong to sample 1
368                def assaySamples = trash.assays*.assaySamples.flatten().unique();
369                assert assaySamples.size() == 1;
370               
371                def assaySample = assaySamples.find { it.sample?.name == "Sample 1a"; }
372                assert assaySample
373                assert assaySample.assay?.name == "Assay 1"
374                assert assaySample.oligoNumber == "123"
375                assert assaySample.tagSequence == "abc"
376                assert assaySample.sample.subject == "S1"
377                assert assaySample.sample.event == "event"
378                assert assaySample.sequenceData.size() == 2
379
380                // Check whether the assay samples contain the right sequence data
381                def sequenceData = trash.assays*.assaySamples*.sequenceData.flatten().unique();
382               
383                // Filter null values
384                sequenceData = sequenceData.findAll { it != null };
385               
386                assert sequenceData.size() == 2;
387
388                // Filter null values
389                sequenceData = sequenceData.findAll { it != null };
390                assert sequenceData.size() == 2;
391               
392                def sd = sequenceData.find { it.sequenceFile == "fasta1"; }
393                assert sd
394                assert sd.qualityFile == "qual1"
395                assert sd.numSequences == 100
396                assert sd.averageQuality == 10.0
397                assert sd.sample.assay.name == "Assay 1"
398                assert sd.sample.sample.name == "Sample 1a"
399               
400                sd = sequenceData.find { it.sequenceFile == "fasta2"; }
401                assert sd
402                assert sd.qualityFile == "qual2"
403                assert sd.numSequences == 30
404                assert sd.averageQuality == 14.0
405                assert sd.sample.assay.name == "Assay 1"
406                assert sd.sample.sample.name == "Sample 1a"
407        }
408       
409        void testRestoreAssay() {
410                setupTrash();
411               
412                def study = Study.findByStudyToken( "study1" );
413               
414                def trashAssay = trash.assays.find { it.assayToken == "trash_assay1" };
415                def restoreTo = study.assays.find { it.assayToken == "assay1" };
416               
417                assert trashAssay
418                assert restoreTo
419               
420                assert restoreTo.assaySamples?.size() == 2
421               
422                trashService.restoreAssay( trashAssay, restoreTo );
423               
424                // Check whether the sample data is moved to the other assay
425                def restoredTo = study.assays.find { it.assayToken == "assay1" };
426                assert restoredTo.assaySamples?.size() == 2
427               
428                // Check for the copying of oligoNumber and tagSequence
429                def s = restoredTo.assaySamples.find { it.sample.sampleToken == "sample1a" }
430                assert s
431                assert s.oligoNumber == "fromtrash: 1";
432                assert s.tagSequence == "fromtrash: abc";
433               
434                // Sample data shouldn't be copied, so remains the same
435                assert s.sample.subject == "S1"
436                assert s.sample.event == "event"
437               
438                assert s.sequenceData?.size() == 4
439               
440                assert s.numSequences() == 730
441                def sequenceFiles = s.sequenceData.sequenceFile;
442                assert sequenceFiles.contains( "fromtrash: fasta1" )
443                assert sequenceFiles.contains( "fromtrash: fasta2" )
444               
445                // Also check the second assay sample
446                s = restoredTo.assaySamples.find { it.sample.sampleToken == "sample1b" }
447                assert s
448                assert s.oligoNumber == "fromtrash: 2";
449                assert s.tagSequence == "fromtrash: def";
450                assert s.sequenceData?.size() == 2
451               
452                assert s.numSequences() == 4000
453                sequenceFiles = s.sequenceData.sequenceFile;
454                assert sequenceFiles.contains( "fromtrash: fasta3" )
455        }
456       
457        void testRestoreSample() {
458                setupTrash();
459               
460                def study = Study.findByStudyToken( "study1" );
461
462                def trashAssay = trash.assays.find { it.assayToken == "trash_assay1" };
463                def restoreToAssay = study.assays.find { it.assayToken == "assay2" };
464
465                assert trashAssay
466                assert restoreToAssay
467
468                def trashSample = trashAssay.assaySamples.find { it.id == 102 };
469                def restoreTo = restoreToAssay.assaySamples.find { it.id == 12 };
470
471                assert trashSample
472                assert restoreTo
473               
474                assert restoreTo.sequenceData == null || restoreTo.sequenceData.size() == 0;
475               
476                trashService.restoreSample( trashSample, restoreTo );
477               
478                // Check whether the sample data is moved to the other assay
479                def restoredTo = restoreToAssay.assaySamples.find { it.id == 12 };
480                assert restoredTo
481               
482                // Check for the copying of oligoNumber and tagSequence
483                assert restoredTo.oligoNumber == "fromtrash: 1";
484                assert restoredTo.tagSequence == "fromtrash: abc";
485                assert restoredTo.sequenceData?.size() == 2
486               
487                // Sample data shouldn't be copied, so remains the same
488                assert restoredTo.sample.subject == "S4"
489                assert restoredTo.sample.event == "event"
490               
491                assert restoredTo.numSequences() == 600
492                def sequenceFiles = restoredTo.sequenceData.sequenceFile;
493                assert sequenceFiles.contains( "fromtrash: fasta1" )
494                assert sequenceFiles.contains( "fromtrash: fasta2" )
495
496        }
497}
Note: See TracBrowser for help on using the repository browser.