18
18
19
19
__version__ = version ("multiqc_ngi" )
20
20
21
- from multiqc import report , config
22
- from multiqc .utils import util_functions
21
+ from multiqc import report , config , utils
23
22
24
23
log = logging .getLogger ('multiqc' )
24
+ log .setLevel (logging .DEBUG )
25
25
26
26
report .ngi = dict ()
27
27
@@ -64,7 +64,7 @@ class ngi_metadata():
64
64
65
65
def __init__ (self ):
66
66
67
- log .debug ("Running MultiQC_NGI v{} (after modules)" . format ( __version__ ) )
67
+ log .debug (f "Running MultiQC_NGI v{ __version__ } (after modules)" )
68
68
69
69
# Global try statement to catch any unhandled exceptions and stop MultiQC from crashing
70
70
try :
@@ -83,7 +83,7 @@ def __init__(self):
83
83
return None
84
84
85
85
# Run WGS Piper specific cleanup
86
- for f in report .searchfiles :
86
+ for f in report .prep_ordered_search_files_list ( 'piper_ngi' )[ 1 ] :
87
87
if 'piper_ngi' in f [1 ].split (os .sep ):
88
88
log .info ("Looks like WGS data - cleaning up report" )
89
89
self .ngi_wgs_cleanup ()
@@ -93,7 +93,7 @@ def __init__(self):
93
93
self .couch = None
94
94
self .test_data = None
95
95
if 'test_database' in config .kwargs and config .kwargs ['test_database' ] is not None :
96
- log .info ("Using test data instead of connecting to StatusDB: {}" . format ( config .kwargs ['test_database' ]) )
96
+ log .info (f "Using test data instead of connecting to StatusDB: { config .kwargs ['test_database' ]} " )
97
97
with open (config .kwargs ['test_database' ], 'r' ) as tdata :
98
98
self .test_data = json .loads (tdata .read ())
99
99
else :
@@ -106,7 +106,7 @@ def __init__(self):
106
106
# Get project ID
107
107
pids = None
108
108
if 'project' in config .kwargs and config .kwargs ['project' ] is not None :
109
- log .info ("Using supplied NGI project id: {}" . format ( config .kwargs ['project' ]) )
109
+ log .info (f "Using supplied NGI project id: { config .kwargs ['project' ]} " )
110
110
pids = config .kwargs ['project' ]
111
111
self .s_names = set ()
112
112
for x in report .general_stats_data :
@@ -116,7 +116,7 @@ def __init__(self):
116
116
117
117
if len (pids ) == 1 :
118
118
pid = list (pids .keys ())[0 ]
119
- log .info ("Found one NGI project id: {}" . format ( pid ) )
119
+ log .info (f "Found one NGI project id: { pid } " )
120
120
121
121
# Get the metadata for the project
122
122
self .get_ngi_project_metadata (pid )
@@ -139,7 +139,7 @@ def __init__(self):
139
139
log .info ("Not pushing results to StatusDB. To do this, use --push or set config push_statusdb: True" )
140
140
141
141
elif len (pids ) > 1 :
142
- log .info ("Found {} NGI project IDs: {}" . format ( len ( pids ), ", " .join (pids )) )
142
+ log .info (f "Found { len ( pids ) } NGI project IDs: { ', ' .join (pids )} " )
143
143
for pid , s_names in pids .items ():
144
144
self .get_ngi_samples_metadata (pid , s_names )
145
145
self .general_stats_sample_meta ()
@@ -148,7 +148,7 @@ def __init__(self):
148
148
149
149
150
150
except Exception as e :
151
- log .error ("MultiQC_NGI v{} crashed! Skipping..." . format ( __version__ ) )
151
+ log .error (f "MultiQC_NGI v{ __version__ } crashed! Skipping..." )
152
152
log .exception (e )
153
153
log .error ("Continuing with base MultiQC execution." )
154
154
@@ -228,20 +228,20 @@ def get_ngi_project_metadata(self, pid):
228
228
try :
229
229
p_summary = p_summary ['value' ]
230
230
except TypeError :
231
- log .error ("statusdb returned no rows when querying {}" . format ( pid ) )
231
+ log .error (f "statusdb returned no rows when querying { pid } " )
232
232
return None
233
- log .debug ("Found metadata for NGI project '{}'" . format ( p_summary ['project_name' ]) )
233
+ log .debug (f "Found metadata for NGI project '{ p_summary ['project_name' ]} '" )
234
234
235
- config .title = '{ }: {}' . format ( pid , p_summary ['project_name' ])
235
+ config .title = f" { pid } : { p_summary ['project_name' ]} "
236
236
config .project_name = p_summary ['project_name' ]
237
237
if config .analysis_dir and ('qc_ngi' in str (config .analysis_dir [0 ]) or 'qc_ngi' in os .listdir ()):
238
238
infix = 'qc'
239
239
else :
240
240
infix = 'pipeline'
241
241
config .output_fn_name = f'{ p_summary ["project_name" ]} _{ infix } _{ config .output_fn_name } '
242
- config .data_dir_name = '{}_{}' . format ( p_summary ['project_name' ], config .data_dir_name )
243
- log .debug ("Renaming report filename to '{}'" . format ( config .output_fn_name ) )
244
- log .debug ("Renaming data directory to '{}'" . format ( config .data_dir_name ) )
242
+ config .data_dir_name = f' { p_summary ['project_name' ]} _ { config .data_dir_name } '
243
+ log .debug (f "Renaming report filename to '{ config .output_fn_name } '" )
244
+ log .debug (f "Renaming data directory to '{ config .data_dir_name } '" )
245
245
246
246
report .ngi ['pid' ] = pid
247
247
report .ngi ['project_name' ] = p_summary ['project_name' ]
@@ -263,13 +263,13 @@ def get_ngi_project_metadata(self, pid):
263
263
report .ngi [i ] = p_summary [j ]
264
264
report .ngi ['ngi_header' ] = True
265
265
except KeyError :
266
- log .warn ("Couldn't find '{}' in project summary" . format ( j ) )
266
+ log .warn (f "Couldn't find '{ j } ' in project summary" )
267
267
for i , j in d_keys .items ():
268
268
try :
269
269
report .ngi [i ] = p_summary ['details' ][j ]
270
270
report .ngi ['ngi_header' ] = True
271
271
except KeyError :
272
- log .warn ("Couldn't find '{}' in project details" . format ( j ) )
272
+ log .warn (f "Couldn't find '{ j } ' in project details" )
273
273
274
274
275
275
def get_ngi_samples_metadata (self , pid , s_names = None ):
@@ -280,7 +280,7 @@ def get_ngi_samples_metadata(self, pid, s_names=None):
280
280
p_view = self .couch ['projects' ].view ('project/samples' )
281
281
p_samples = p_view [pid ]
282
282
if not len (p_samples .rows ) == 1 :
283
- log .error ("statusdb returned {} rows when querying {}" . format ( len ( p_samples . rows ), pid ) )
283
+ log .error (f "statusdb returned { len ( p_samples . rows ) } rows when querying { pid } " )
284
284
else :
285
285
if 'sample_meta' not in report .ngi :
286
286
report .ngi ['sample_meta' ] = dict ()
@@ -310,7 +310,7 @@ def fastqscreen_genome(self):
310
310
}
311
311
if genome in nice_names .keys ():
312
312
genome = nice_names [genome ]
313
- m .intro += '<p style="margin-top:20px;" class="text-info"> <span class="glyphicon glyphicon-piggy-bank"></span> The reference genome in Genomic status is {}</p>' . format ( genome )
313
+ m .intro += f '<p style="margin-top:20px;" class="text-info"> <span class="glyphicon glyphicon-piggy-bank"></span> The reference genome in Genomic status is { genome } </p>'
314
314
315
315
316
316
def general_stats_sample_meta (self ):
@@ -319,7 +319,7 @@ def general_stats_sample_meta(self):
319
319
meta = report .ngi .get ('sample_meta' )
320
320
if meta is not None and len (meta ) > 0 :
321
321
322
- log .info ('Found {} samples in StatusDB' . format ( len ( meta )) )
322
+ log .info (f 'Found { len ( meta ) } samples in StatusDB' )
323
323
324
324
# Write to file
325
325
report .write_data_file (meta , 'ngi_meta' )
@@ -343,7 +343,7 @@ def general_stats_sample_meta(self):
343
343
344
344
# Skip this sample if we don't have any matching data
345
345
if s_name is None :
346
- log .debug ("Skipping StatusDB metadata for sample {} as no bioinfo report logs found." . format ( sid ) )
346
+ log .debug (f "Skipping StatusDB metadata for sample { sid } as no bioinfo report logs found." )
347
347
continue
348
348
349
349
# Make a dict to hold new data for General Stats
@@ -370,7 +370,7 @@ def general_stats_sample_meta(self):
370
370
seq_lp = lp
371
371
else :
372
372
seq_lp = None
373
- log .warn ('Found multiple sequenced lib preps for {} - skipping metadata' . format ( sid ) )
373
+ log .warn (f 'Found multiple sequenced lib preps for { sid } - skipping metadata' )
374
374
break
375
375
except KeyError :
376
376
pass
@@ -387,17 +387,17 @@ def general_stats_sample_meta(self):
387
387
except KeyError :
388
388
pass
389
389
390
- log .info ("Matched meta for {} samples from StatusDB with report sample names" . format ( len ( s_names )) )
390
+ log .info (f "Matched meta for { len ( s_names ) } samples from StatusDB with report sample names" )
391
391
if len (s_names ) == 0 :
392
392
return None
393
393
394
394
# Deal with having more than one initial QC concentration unit
395
395
formats_set = set (formats .values ())
396
396
if len (formats_set ) > 1 :
397
- log .warning ("Mixture of library_validation concentration units! Found: {}" . format ( ", " .join (formats_set )) )
397
+ log .warning (f "Mixture of library_validation concentration units! Found: { ', ' .join (formats_set )} " )
398
398
for s_name in gsdata :
399
399
try :
400
- gsdata [s_name ]['lp_concentration' ] = '{} {}' . format ( gsdata [s_name ]['lp_concentration' ], formats [s_name ])
400
+ gsdata [s_name ]['lp_concentration' ] = f' { gsdata [s_name ]['lp_concentration' ]} { formats [s_name ]} '
401
401
except KeyError :
402
402
pass
403
403
elif len (formats_set ) == 1 :
@@ -443,11 +443,11 @@ def general_stats_sample_meta(self):
443
443
}
444
444
gsheaders ['lp_concentration' ] = {
445
445
'namespace' : 'NGI' ,
446
- 'title' : 'Lib Conc. ({})' . format ( conc_units ) ,
447
- 'description' : 'Library Prep: Concentration ({})' . format ( conc_units ) ,
446
+ 'title' : f 'Lib Conc. ({ conc_units } )' ,
447
+ 'description' : f 'Library Prep: Concentration ({ conc_units } )' ,
448
448
'min' : 0 ,
449
449
'scale' : 'YlGn' ,
450
- 'format' : '{:., 0f}' ,
450
+ 'format' : '{:,. 0f}' ,
451
451
'hidden' : conc_hidden
452
452
}
453
453
gsheaders ['amount_taken' ] = {
@@ -456,7 +456,7 @@ def general_stats_sample_meta(self):
456
456
'description' : 'Library Prep: Amount Taken (ng)' ,
457
457
'min' : 0 ,
458
458
'scale' : 'YlGn' ,
459
- 'format' : '{:., 0f}' ,
459
+ 'format' : '{:,. 0f}' ,
460
460
'hidden' : amounts_hidden
461
461
}
462
462
report .general_stats_data .append (gsdata )
@@ -524,7 +524,17 @@ def push_statusdb_multiqc_data(self):
524
524
doc ['samples' ][sid ][key ] = d [s_name ]
525
525
526
526
# Save object to the database
527
- db .save (doc )
527
+ try :
528
+ db .save (doc )
529
+ except ValueError as e :
530
+ if e .args [0 ] == 'Out of range float values are not JSON compliant' :
531
+ log .debug ('Error saving to StatusDB: Out of range float values are not JSON compliant, might be NaNs, trying again...' )
532
+ doc = json .loads (utils .util_functions .dump_json (doc , filehandle = None ))
533
+ db .save (doc )
534
+ log .debug ('Saved to StatusDB after converting NaNs to nulls' )
535
+ else :
536
+ log .error (f'Error saving to StatusDB: { e } ' )
537
+
528
538
529
539
530
540
def connect_statusdb (self ):
@@ -535,11 +545,11 @@ def connect_statusdb(self):
535
545
sdb_config = yaml .safe_load (f )
536
546
log .debug ("Got MultiQC_NGI statusdb config from the home directory." )
537
547
except IOError :
538
- log .debug ("Could not open the MultiQC_NGI statusdb config file {}" . format ( conf_file ) )
548
+ log .debug ("Could not open the MultiQC_NGI statusdb config file {conf_file}" )
539
549
try :
540
550
with open (os .environ ['STATUS_DB_CONFIG' ], "r" ) as f :
541
551
sdb_config = yaml .safe_load (f )
542
- log .debug ("Got MultiQC_NGI statusdb config from $STATUS_DB_CONFIG: {}" . format ( os .environ ['STATUS_DB_CONFIG' ]) )
552
+ log .debug (f "Got MultiQC_NGI statusdb config from $STATUS_DB_CONFIG: { os .environ ['STATUS_DB_CONFIG' ]} " )
543
553
except (KeyError , IOError ):
544
554
log .debug ("Could not get the MultiQC_NGI statusdb config file from env STATUS_DB_CONFIG" )
545
555
log .warn ("Could not find a statusdb config file" )
@@ -549,10 +559,10 @@ def connect_statusdb(self):
549
559
password = sdb_config ['statusdb' ]['password' ]
550
560
couch_url = sdb_config ['statusdb' ]['url' ]
551
561
except KeyError :
552
- log .error ("Error parsing the config file {}" . format ( conf_file ) )
562
+ log .error (f "Error parsing the config file { conf_file } " )
553
563
return None
554
564
555
- server_url = "https://{}:{}@{}" . format ( couch_user , password , couch_url )
565
+ server_url = f "https://{ couch_user } :{ password } @{ couch_url } "
556
566
557
567
# First, test that we can see the server.
558
568
try :
@@ -569,7 +579,7 @@ def connect_statusdb(self):
569
579
class ngi_after_execution_finish ():
570
580
571
581
def __init__ (self ):
572
- log .debug ("Running MultiQC_NGI v{} (after execution finish)" . format ( __version__ ) )
582
+ log .debug (f "Running MultiQC_NGI v{ __version__ } (after execution finish)" )
573
583
574
584
if config .kwargs .get ('disable_ngi' , False ) is True :
575
585
log .debug ("Skipping MultiQC_NGI (after execution finish) as 'disable_ngi' was specified" )
@@ -586,14 +596,14 @@ def __init__(self):
586
596
if getattr (config , 'remote_port' , None ) is not None :
587
597
scp_command .extend (['-P' , str (config .remote_port )])
588
598
scp_command .extend ([config .output_fn , config .remote_destination ])
589
- log .debug (' Transferring report with command: {}' . format ( ' ' .join (scp_command )) )
599
+ log .debug (f" Transferring report with command: { ' ' .join (scp_command )} " )
590
600
DEVNULL = open (os .devnull , 'wb' )
591
601
p = subprocess .Popen (scp_command , stdout = DEVNULL )
592
602
pid , exit_status = os .waitpid (p .pid , 0 )
593
603
if exit_status != 0 :
594
604
log .error ("Not able to copy report to remote server: Subprocess command failed." )
595
605
596
606
except Exception as e :
597
- log .error ("MultiQC_NGI v{} crashed! Skipping..." . format ( __version__ ) )
607
+ log .error (f "MultiQC_NGI v{ __version__ } crashed! Skipping..." )
598
608
log .exception (e )
599
609
log .error ("Continuing with base MultiQC execution." )
0 commit comments