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

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

Renamed Metagenomics module to MassSequencing? module

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