@@ -1167,3 +1167,189 @@ def test_update_paths_relocated_analysis_dir_with_qc(self):
11671167 os .path .join (new_path ,
11681168 proj .name ,
11691169 "fastqs" ))
1170+
1171+
1172+ class TestAutoProcessSyncProjectMetadataFile (unittest .TestCase ):
1173+ """
1174+ Tests for the 'sync_project_metadata_file' method
1175+ """
1176+ def setUp (self ):
1177+ # Project metadata items mapping
1178+ self .metadata_map = {
1179+ "User" : "user" ,
1180+ "PI" : "PI" ,
1181+ "Library" : "library_type" ,
1182+ "SC_Platform" : "single_cell_platform" ,
1183+ "Organism" : "organism" ,
1184+ "Comments" : "comments"
1185+ }
1186+ # Create a temp working dir
1187+ self .dirn = tempfile .mkdtemp (suffix = 'TestAutoProcess' )
1188+ # Store original location
1189+ self .pwd = os .getcwd ()
1190+ # Move to working directory
1191+ os .chdir (self .dirn )
1192+
1193+ def tearDown (self ):
1194+ # Return to original dir
1195+ os .chdir (self .pwd )
1196+ # Remove the temporary test directory
1197+ shutil .rmtree (self .dirn )
1198+
1199+ def test_sync_project_metadata_file_project_no_longer_exists (self ):
1200+ """
1201+ AutoProcess.sync_project_metadata_file: remove non-existent project
1202+ """
1203+ # Metadata for projects
1204+ project_metadata = {
1205+ "AB" : {
1206+ "User" : "Alan Bailey" ,
1207+ "PI" : "Archie Ballard" ,
1208+ "Library" : "RNA-seq" ,
1209+ "Organism" : "Human"
1210+ }
1211+ }
1212+ # Make an auto-process directory with projects
1213+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
1214+ '231021_A00879_0087_000000000-AGEW9' ,
1215+ 'novaseq' ,
1216+ project_metadata = project_metadata ,
1217+ metadata = { "run_number" : 87 ,
1218+ "source" : "local" },
1219+ top_dir = self .dirn )
1220+ mockdir .create ()
1221+ # Remove CDE project
1222+ shutil .rmtree (os .path .join (mockdir .dirn , "CDE" ))
1223+ # Remove initial entry for CDE in projects.info
1224+ projects_info_contents = []
1225+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
1226+ for line in fp :
1227+ if not line .startswith ("CDE" ):
1228+ projects_info_contents .append (line )
1229+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
1230+ fp .write ("" .join (projects_info_contents ))
1231+ # Set up AutoProcess instance
1232+ ap = AutoProcess (mockdir .dirn )
1233+ # Check metadata items in projects.info pre-update
1234+ ap_project_metadata = ap .load_project_metadata ()
1235+ for pname in project_metadata :
1236+ for item in project_metadata [pname ]:
1237+ self .assertEqual (ap_project_metadata .lookup (pname )[item ],
1238+ project_metadata [pname ][item ])
1239+ # Check metadata items in projects pre-update
1240+ for pname in project_metadata :
1241+ p = ap .get_analysis_projects (pname )[0 ]
1242+ for item in project_metadata [pname ]:
1243+ project_item = self .metadata_map [item ]
1244+ expected_value = project_metadata [pname ][item ]
1245+ self .assertEqual (p .info [project_item ],
1246+ expected_value )
1247+ # Append info for missing project 'CDE' to projects.info
1248+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'at' ) as fp :
1249+ fp .write ("""CDE\t CDE3,CDE4\t Charles Edwards\t ChIP-seq\t .\t Mouse\t Christian Eggars\t 1% PhiX spiked in
1250+ """ )
1251+ # Do the update
1252+ ap .sync_project_metadata_file ()
1253+ # Reload and confirm the updates in projects.info
1254+ ap = AutoProcess (mockdir .dirn )
1255+ ap_project_metadata = ap .load_project_metadata ()
1256+ for pname in ["AB" , "#CDE" ]:
1257+ self .assertTrue (pname in [p ["Project" ] for p in ap_project_metadata ],
1258+ f"'{ pname } ' not in project metadata" )
1259+
1260+ def test_sync_project_metadata_file_add_unlisted_projects (self ):
1261+ """
1262+ AutoProcess.sync_project_metadata_file: add unlisted projects
1263+ """
1264+ # Metadata for projects
1265+ project_metadata = {
1266+ "AB" : {
1267+ "User" : "Alan Bailey" ,
1268+ "PI" : "Archie Ballard" ,
1269+ "Library" : "RNA-seq" ,
1270+ "Organism" : "Human"
1271+ },
1272+ "CDE" : {
1273+ "User" : "Charles Edwards" ,
1274+ "PI" : "Christian Eggars" ,
1275+ "Library" : "ChIP-seq" ,
1276+ "Organism" : "Mouse"
1277+ }
1278+ }
1279+ # Make an auto-process directory with projects
1280+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
1281+ '231021_A00879_0087_000000000-AGEW9' ,
1282+ 'novaseq' ,
1283+ project_metadata = project_metadata ,
1284+ metadata = { "run_number" : 87 ,
1285+ "source" : "local" },
1286+ top_dir = self .dirn )
1287+ mockdir .create ()
1288+ # Remove initial entry for CDE in projects.info
1289+ projects_info_contents = []
1290+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
1291+ for line in fp :
1292+ if not line .startswith ("CDE" ):
1293+ projects_info_contents .append (line )
1294+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
1295+ fp .write ("" .join (projects_info_contents ))
1296+ # Set up AutoProcess instance and do the update
1297+ ap = AutoProcess (mockdir .dirn )
1298+ ap .sync_project_metadata_file ()
1299+ # Check contents of projects.info
1300+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
1301+ expected_lines = [
1302+ "#Project\t Samples\t User\t Library\t SC_Platform\t Organism\t PI\t Comments" ,
1303+ "AB\t AB1,AB2\t Alan Bailey\t RNA-seq\t .\t Human\t Archie Ballard\t ." ,
1304+ "CDE\t CDE3,CDE4\t Charles Edwards\t ChIP-seq\t .\t Mouse\t Christian Eggars\t ."
1305+ ]
1306+ for expected , actual in zip (expected_lines , fp .read ().split ("\n " )):
1307+ self .assertEqual (expected .strip (), actual .strip ())
1308+
1309+ def test_sync_project_metadata_file_add_unlisted_projects_ignore_special_names (self ):
1310+ """
1311+ AutoProcess.sync_project_metadata_file: ignore projects with "special" names
1312+ """
1313+ # Metadata for projects
1314+ project_metadata = {
1315+ "AB" : {
1316+ "User" : "Alan Bailey" ,
1317+ "PI" : "Archie Ballard" ,
1318+ "Library" : "RNA-seq" ,
1319+ "Organism" : "Human"
1320+ },
1321+ "CDE.bak" : {
1322+ "User" : "Charles Edwards" ,
1323+ "PI" : "Christian Eggars" ,
1324+ "Library" : "ChIP-seq" ,
1325+ "Organism" : "Mouse"
1326+ }
1327+ }
1328+ # Make an auto-process directory with projects
1329+ mockdir = MockAnalysisDirFactory .bcl2fastq2 (
1330+ '231021_A00879_0087_000000000-AGEW9' ,
1331+ 'novaseq' ,
1332+ project_metadata = project_metadata ,
1333+ metadata = { "run_number" : 87 ,
1334+ "source" : "local" },
1335+ top_dir = self .dirn )
1336+ mockdir .create ()
1337+ # Remove entry for CDE.bak in projects.info
1338+ projects_info_contents = []
1339+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
1340+ for line in fp :
1341+ if not line .startswith ("CDE.bak" ):
1342+ projects_info_contents .append (line )
1343+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'wt' ) as fp :
1344+ fp .write ("" .join (projects_info_contents ))
1345+ # Set up AutoProcess instance and do the update
1346+ ap = AutoProcess (mockdir .dirn )
1347+ ap .sync_project_metadata_file ()
1348+ # Check contents of projects.info
1349+ with open (os .path .join (mockdir .dirn ,"projects.info" ),'rt' ) as fp :
1350+ expected_lines = [
1351+ "#Project\t Samples\t User\t Library\t SC_Platform\t Organism\t PI\t Comments" ,
1352+ "AB\t AB1,AB2\t Alan Bailey\t RNA-seq\t .\t Human\t Archie Ballard\t ."
1353+ ]
1354+ for expected , actual in zip (expected_lines , fp .read ().split ("\n " )):
1355+ self .assertEqual (expected .strip (), actual .strip ())
0 commit comments