@@ -5,74 +5,6 @@ use std::sync::atomic::{AtomicU64, Ordering};
55
66use crate :: align:: transcript:: { CigarOp , Transcript } ;
77use crate :: junction:: encode_motif;
8- use crate :: params:: Parameters ;
9-
10- /// Shared timestamp format used across Log.final.out / Log.out / Log.progress.out.
11- pub const LOG_TIME_FMT : & str = "%b %d %H:%M:%S" ;
12-
13- /// Write a minimal STAR-compatible Log.out alongside Log.final.out.
14- ///
15- /// Carries a parameters dump and per-phase timestamps. Intentionally a stub
16- /// rather than a full STAR-verbose-log reproduction.
17- pub fn write_log_out (
18- path : & Path ,
19- params : & Parameters ,
20- time_start : chrono:: DateTime < chrono:: Local > ,
21- time_map_start : chrono:: DateTime < chrono:: Local > ,
22- time_finish : chrono:: DateTime < chrono:: Local > ,
23- ) -> std:: io:: Result < ( ) > {
24- use std:: io:: Write ;
25-
26- let mut f = std:: fs:: File :: create ( path) ?;
27-
28- writeln ! ( f, "##### Run parameters" ) ?;
29- writeln ! ( f, "{:#?}" , params) ?;
30- writeln ! ( f) ?;
31- writeln ! ( f, "##### Run started" ) ?;
32- writeln ! ( f, "{}" , time_start. format( LOG_TIME_FMT ) ) ?;
33- writeln ! ( f) ?;
34- writeln ! ( f, "##### Mapping started" ) ?;
35- writeln ! ( f, "{}" , time_map_start. format( LOG_TIME_FMT ) ) ?;
36- writeln ! ( f) ?;
37- writeln ! ( f, "##### Mapping finished" ) ?;
38- writeln ! ( f, "{}" , time_finish. format( LOG_TIME_FMT ) ) ?;
39-
40- Ok ( ( ) )
41- }
42-
43- /// Write a minimal STAR-compatible Log.progress.out alongside Log.final.out.
44- ///
45- /// A header line plus a single "done" line with the final timestamp and
46- /// mapping speed (million reads per hour). Intentionally a stub.
47- pub fn write_log_progress (
48- path : & Path ,
49- total_reads : u64 ,
50- time_map_start : chrono:: DateTime < chrono:: Local > ,
51- time_finish : chrono:: DateTime < chrono:: Local > ,
52- ) -> std:: io:: Result < ( ) > {
53- use std:: io:: Write ;
54-
55- let elapsed_hours = {
56- let elapsed = time_finish - time_map_start;
57- elapsed. num_milliseconds ( ) as f64 / 3_600_000.0
58- } ;
59- let mapping_speed = if elapsed_hours > 0.0 {
60- total_reads as f64 / elapsed_hours / 1_000_000.0
61- } else {
62- 0.0
63- } ;
64-
65- let mut f = std:: fs:: File :: create ( path) ?;
66- writeln ! ( f, "# completed\t mapping_speed_M_reads_per_hour" ) ?;
67- writeln ! (
68- f,
69- "{}\t {:.2}" ,
70- time_finish. format( LOG_TIME_FMT ) ,
71- mapping_speed
72- ) ?;
73-
74- Ok ( ( ) )
75- }
768
779/// Reason a read could not be mapped
7810#[ derive( Debug , Clone , Copy , PartialEq , Eq ) ]
@@ -1086,69 +1018,4 @@ mod tests {
10861018 stats. record_half_mapped ( ) ;
10871019 assert_eq ! ( stats. half_mapped_pairs. load( Ordering :: Relaxed ) , 3 ) ;
10881020 }
1089-
1090- #[ test]
1091- fn test_write_log_out_minimal ( ) {
1092- use chrono:: TimeZone ;
1093- use clap:: Parser ;
1094-
1095- let params = Parameters :: parse_from ( [ "rustar-aligner" , "--readFilesIn" , "reads.fq" ] ) ;
1096- let t_start = chrono:: Local
1097- . with_ymd_and_hms ( 2026 , 5 , 12 , 14 , 14 , 23 )
1098- . unwrap ( ) ;
1099- let t_map = chrono:: Local
1100- . with_ymd_and_hms ( 2026 , 5 , 12 , 14 , 14 , 30 )
1101- . unwrap ( ) ;
1102- let t_finish = chrono:: Local
1103- . with_ymd_and_hms ( 2026 , 5 , 12 , 14 , 14 , 58 )
1104- . unwrap ( ) ;
1105-
1106- let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
1107- let path = dir. path ( ) . join ( "Log.out" ) ;
1108- write_log_out ( & path, & params, t_start, t_map, t_finish) . unwrap ( ) ;
1109-
1110- let content = std:: fs:: read_to_string ( & path) . unwrap ( ) ;
1111- assert ! ( !content. is_empty( ) , "Log.out should not be empty" ) ;
1112- assert ! ( content. contains( "##### Run parameters" ) ) ;
1113- assert ! ( content. contains( "##### Run started" ) ) ;
1114- assert ! ( content. contains( "##### Mapping started" ) ) ;
1115- assert ! ( content. contains( "##### Mapping finished" ) ) ;
1116- // Each phase header should be followed by a timestamp shaped like "May 12 14:14:23".
1117- assert ! ( content. contains( "May 12 14:14:23" ) ) ;
1118- assert ! ( content. contains( "May 12 14:14:58" ) ) ;
1119- // The parameters dump should mention at least one familiar field.
1120- assert ! ( content. contains( "read_files_in" ) ) ;
1121- }
1122-
1123- #[ test]
1124- fn test_write_log_progress_minimal ( ) {
1125- use chrono:: TimeZone ;
1126-
1127- let t_map = chrono:: Local
1128- . with_ymd_and_hms ( 2026 , 5 , 12 , 14 , 14 , 30 )
1129- . unwrap ( ) ;
1130- let t_finish = chrono:: Local
1131- . with_ymd_and_hms ( 2026 , 5 , 12 , 14 , 14 , 58 )
1132- . unwrap ( ) ;
1133-
1134- let dir = tempfile:: tempdir ( ) . unwrap ( ) ;
1135- let path = dir. path ( ) . join ( "Log.progress.out" ) ;
1136- write_log_progress ( & path, 10_000 , t_map, t_finish) . unwrap ( ) ;
1137-
1138- let content = std:: fs:: read_to_string ( & path) . unwrap ( ) ;
1139- let lines: Vec < & str > = content. lines ( ) . collect ( ) ;
1140- assert ! ( lines. len( ) >= 2 , "expected header + data line" ) ;
1141- assert ! ( lines[ 0 ] . starts_with( '#' ) , "first line should be a header" ) ;
1142- assert ! (
1143- lines[ 1 ] . contains( "May 12 14:14:58" ) ,
1144- "second line should contain the finish timestamp, got: {}" ,
1145- lines[ 1 ]
1146- ) ;
1147- // Mapping speed column should be a number with two decimals.
1148- let cols: Vec < & str > = lines[ 1 ] . split ( '\t' ) . collect ( ) ;
1149- assert_eq ! ( cols. len( ) , 2 , "expected 2 tab-separated columns" ) ;
1150- cols[ 1 ]
1151- . parse :: < f64 > ( )
1152- . expect ( "second column should parse as a float" ) ;
1153- }
11541021}
0 commit comments