@@ -78,7 +78,11 @@ def test_update_relocated_analysis_dir(self):
7878 self .assertEqual (ap .params .primary_data_dir ,
7979 os .path .join (original_path ,"primary_data" ))
8080 # Update the metadata
81- update (ap )
81+ update (ap ,
82+ update_paths = True ,
83+ update_sync_projects = False ,
84+ update_project_metadata = False ,
85+ update_qc_reports = False )
8286 # Reload and check metadata items post-update
8387 ap = AutoProcess (new_path )
8488 self .assertEqual (ap .analysis_dir ,new_path )
@@ -138,7 +142,11 @@ def test_update_relocated_analysis_dir_with_qc(self):
138142 proj .name ,
139143 "fastqs" ))
140144 # Update the metadata
141- update (ap )
145+ update (ap ,
146+ update_paths = True ,
147+ update_sync_projects = False ,
148+ update_project_metadata = False ,
149+ update_qc_reports = False )
142150 # Reload and check metadata items post-update
143151 ap = AutoProcess (new_path )
144152 self .assertEqual (ap .analysis_dir ,new_path )
@@ -215,7 +223,11 @@ def test_update_project_metadata_changed(self):
215223AB\t AB1,AB2\t Alan Bailey\t RNA-seq\t .\t Mouse\t Archie Ballard\t 1% PhiX spiked in
216224CDE\t CDE3,CDE4\t Charles Edwards\t ChIP-seq\t .\t Mouse\t Christian Eggars\t 1% PhiX spiked in
217225""" )
218- update (ap )
226+ update (ap ,
227+ update_paths = False ,
228+ update_sync_projects = False ,
229+ update_project_metadata = True ,
230+ update_qc_reports = False )
219231 # Reload and confirm the updates in projects.info
220232 ap = AutoProcess (mockdir .dirn )
221233 ap_project_metadata = ap .load_project_metadata ()
@@ -291,7 +303,11 @@ def test_update_sample_list_changed(self):
291303 "CDE" : ["CDE3" ]
292304 }
293305 # Update sample lists in metadata
294- update (ap )
306+ update (ap ,
307+ update_paths = False ,
308+ update_sync_projects = False ,
309+ update_project_metadata = True ,
310+ update_qc_reports = False )
295311 # Reload and check updated sample lists in projects.info
296312 ap = AutoProcess (mockdir .dirn )
297313 ap_project_metadata = ap .load_project_metadata ()
@@ -337,7 +353,11 @@ def test_update_paired_end_changed(self):
337353 os .remove (os .path .join (mockdir .dirn ,fq ))
338354 # Set up AutoProcess instance and update metadata
339355 ap = AutoProcess (mockdir .dirn )
340- update (ap )
356+ update (ap ,
357+ update_paths = False ,
358+ update_sync_projects = False ,
359+ update_project_metadata = True ,
360+ update_qc_reports = False )
341361 # Reload and check update paired-end metadata in projects
342362 ap = AutoProcess (mockdir .dirn )
343363 expected_paired_end = {
@@ -350,6 +370,176 @@ def test_update_paired_end_changed(self):
350370 self .assertEqual (project_metadata .paired_end ,
351371 expected_paired_end [pname ])
352372
373+ def test_update_project_metadata_project_no_longer_exists (self ):
374+ """
375+ update: handle project which no longer exists in analysis dir
376+ """
377+ # Metadata for projects
378+ project_metadata = {
379+ "AB" : {
380+ "User" : "Alan Bailey" ,
381+ "PI" : "Archie Ballard" ,
382+ "Library" : "RNA-seq" ,
383+ "Organism" : "Human"
384+ }
385+ }
386+ # Make an auto-process directory with projects
387+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
388+ '231021_A00879_0087_000000000-AGEW9' ,
389+ 'novaseq' ,
390+ project_metadata = project_metadata ,
391+ metadata = { "run_number" : 87 ,
392+ "source" : "local" },
393+ top_dir = self .dirn )
394+ mockdir .create ()
395+ # Remove CDE project
396+ shutil .rmtree (os .path .join (mockdir .dirn , "CDE" ))
397+ # Remove initial entry for CDE in projects.info
398+ projects_info_contents = []
399+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
400+ for line in fp :
401+ if not line .startswith ("CDE" ):
402+ projects_info_contents .append (line )
403+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
404+ fp .write ("" .join (projects_info_contents ))
405+ # Set up AutoProcess instance
406+ ap = AutoProcess (mockdir .dirn )
407+ # Check metadata items in projects.info pre-update
408+ ap_project_metadata = ap .load_project_metadata ()
409+ for pname in project_metadata :
410+ for item in project_metadata [pname ]:
411+ self .assertEqual (ap_project_metadata .lookup (pname )[item ],
412+ project_metadata [pname ][item ])
413+ # Check metadata items in projects pre-update
414+ for pname in project_metadata :
415+ p = ap .get_analysis_projects (pname )[0 ]
416+ for item in project_metadata [pname ]:
417+ project_item = self .metadata_map [item ]
418+ expected_value = project_metadata [pname ][item ]
419+ self .assertEqual (p .info [project_item ],
420+ expected_value )
421+ # Append info for missing project 'CDE' to projects.info
422+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'at' ) as fp :
423+ fp .write ("""CDE\t CDE3,CDE4\t Charles Edwards\t ChIP-seq\t .\t Mouse\t Christian Eggars\t 1% PhiX spiked in
424+ """ )
425+ # Do the update
426+ update (ap ,
427+ update_paths = False ,
428+ update_sync_projects = True ,
429+ update_project_metadata = False ,
430+ update_qc_reports = False )
431+ # Reload and confirm the updates in projects.info
432+ ap = AutoProcess (mockdir .dirn )
433+ ap_project_metadata = ap .load_project_metadata ()
434+ for pname in ["AB" , "#CDE" ]:
435+ self .assertTrue (pname in [p ["Project" ] for p in ap_project_metadata ],
436+ f"'{ pname } ' not in project metadata" )
437+
438+ def test_update_project_metadata_add_unlisted_projects (self ):
439+ """
440+ update: add unlisted project directories to 'projects.info'
441+ """
442+ # Metadata for projects
443+ project_metadata = {
444+ "AB" : {
445+ "User" : "Alan Bailey" ,
446+ "PI" : "Archie Ballard" ,
447+ "Library" : "RNA-seq" ,
448+ "Organism" : "Human"
449+ },
450+ "CDE" : {
451+ "User" : "Charles Edwards" ,
452+ "PI" : "Christian Eggars" ,
453+ "Library" : "ChIP-seq" ,
454+ "Organism" : "Mouse"
455+ }
456+ }
457+ # Make an auto-process directory with projects
458+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
459+ '231021_A00879_0087_000000000-AGEW9' ,
460+ 'novaseq' ,
461+ project_metadata = project_metadata ,
462+ metadata = { "run_number" : 87 ,
463+ "source" : "local" },
464+ top_dir = self .dirn )
465+ mockdir .create ()
466+ # Remove initial entry for CDE in projects.info
467+ projects_info_contents = []
468+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
469+ for line in fp :
470+ if not line .startswith ("CDE" ):
471+ projects_info_contents .append (line )
472+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
473+ fp .write ("" .join (projects_info_contents ))
474+ # Set up AutoProcess instance and do the update
475+ ap = AutoProcess (mockdir .dirn )
476+ update (ap ,
477+ update_paths = False ,
478+ update_sync_projects = True ,
479+ update_project_metadata = False ,
480+ update_qc_reports = False )
481+ # Check contents of projects.info
482+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
483+ expected_lines = [
484+ "#Project\t Samples\t User\t Library\t SC_Platform\t Organism\t PI\t Comments" ,
485+ "AB\t AB1,AB2\t Alan Bailey\t RNA-seq\t .\t Human\t Archie Ballard\t ." ,
486+ "CDE\t CDE3,CDE4\t Charles Edwards\t ChIP-seq\t .\t Mouse\t Christian Eggars\t ."
487+ ]
488+ for expected , actual in zip (expected_lines , fp .read ().split ("\n " )):
489+ self .assertEqual (expected .strip (), actual .strip ())
490+
491+ def test_update_project_metadata_add_unlisted_projects_ignore_special_names (self ):
492+ """
493+ update: ignore unlisted project directories (don't add to 'projects.info')
494+ """
495+ # Metadata for projects
496+ project_metadata = {
497+ "AB" : {
498+ "User" : "Alan Bailey" ,
499+ "PI" : "Archie Ballard" ,
500+ "Library" : "RNA-seq" ,
501+ "Organism" : "Human"
502+ },
503+ "CDE.bak" : {
504+ "User" : "Charles Edwards" ,
505+ "PI" : "Christian Eggars" ,
506+ "Library" : "ChIP-seq" ,
507+ "Organism" : "Mouse"
508+ }
509+ }
510+ # Make an auto-process directory with projects
511+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
512+ '231021_A00879_0087_000000000-AGEW9' ,
513+ 'novaseq' ,
514+ project_metadata = project_metadata ,
515+ metadata = { "run_number" : 87 ,
516+ "source" : "local" },
517+ top_dir = self .dirn )
518+ mockdir .create ()
519+ # Remove entry for CDE.bak in projects.info
520+ projects_info_contents = []
521+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
522+ for line in fp :
523+ if not line .startswith ("CDE.bak" ):
524+ projects_info_contents .append (line )
525+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
526+ fp .write ("" .join (projects_info_contents ))
527+ # Set up AutoProcess instance and do the update
528+ ap = AutoProcess (mockdir .dirn )
529+ update (ap ,
530+ update_paths = False ,
531+ update_sync_projects = True ,
532+ update_project_metadata = False ,
533+ update_qc_reports = False )
534+ # Check contents of projects.info
535+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
536+ expected_lines = [
537+ "#Project\t Samples\t User\t Library\t SC_Platform\t Organism\t PI\t Comments" ,
538+ "AB\t AB1,AB2\t Alan Bailey\t RNA-seq\t .\t Human\t Archie Ballard\t ."
539+ ]
540+ for expected , actual in zip (expected_lines , fp .read ().split ("\n " )):
541+ self .assertEqual (expected .strip (), actual .strip ())
542+
353543 def test_update_regenerate_qc_reports (self ):
354544 """
355545 update: regenerate QC reports with stale metadata
@@ -400,7 +590,11 @@ def test_update_regenerate_qc_reports(self):
400590 self .assertTrue (metadata_mtime <
401591 os .path .getmtime (metadata_file ))
402592 # Re-do update and check modification times
403- update (ap )
593+ update (ap ,
594+ update_paths = False ,
595+ update_sync_projects = False ,
596+ update_project_metadata = False ,
597+ update_qc_reports = True )
404598 for project_name in project_list :
405599 self .assertTrue (qc_report_mtimes [project_name ] <
406600 os .path .getmtime (
0 commit comments