1
- use crate :: intersection:: Intersections ;
2
- use crate :: py:: CompiledPython ;
3
- use crate :: report_options:: ReportOptions ;
4
- use std:: sync:: Arc ;
1
+ use crate :: py:: { CompiledPython , PyReportFragment } ;
2
+ use crate :: report:: ReportFragment ;
5
3
#[ derive( Debug , PartialEq ) ]
6
4
pub enum Value {
7
5
Int ( i32 ) ,
@@ -64,18 +62,14 @@ pub trait ColumnReporter: std::fmt::Debug {
64
62
fn description ( & self ) -> & str ;
65
63
fn number ( & self ) -> & Number ;
66
64
67
- fn value (
68
- & self ,
69
- r : & Intersections ,
70
- report_options : Arc < ReportOptions > ,
71
- ) -> Result < Value , ColumnError > ;
65
+ /// Each report fragment is a different line in the output. So we can't pass a report.
66
+ fn value ( & self , r : & ReportFragment ) -> Result < Value , ColumnError > ;
72
67
}
73
68
74
69
pub enum ValueParser {
75
70
PythonExpression ( String ) ,
76
71
LuaExpression ( String ) ,
77
- // bool indicates whether we should use the intersection.report() constraints or just the count of overlaps
78
- Count ( bool ) ,
72
+ Count ,
79
73
Sum ,
80
74
Bases ,
81
75
ChromStartEnd ,
@@ -127,9 +121,7 @@ impl TryFrom<&str> for ValueParser {
127
121
} else if let Some ( rest) = s. strip_prefix ( "lua:" ) {
128
122
Ok ( ValueParser :: LuaExpression ( rest. to_string ( ) ) )
129
123
} else if s == "count" {
130
- Ok ( ValueParser :: Count ( false ) )
131
- } else if s == "report_count" {
132
- Ok ( ValueParser :: Count ( true ) )
124
+ Ok ( ValueParser :: Count )
133
125
} else if s == "sum" {
134
126
Ok ( ValueParser :: Sum )
135
127
} else if s == "bases" {
@@ -149,8 +141,7 @@ impl std::fmt::Display for ValueParser {
149
141
match self {
150
142
ValueParser :: PythonExpression ( s) => write ! ( f, "py:{}" , s) ,
151
143
ValueParser :: LuaExpression ( s) => write ! ( f, "lua:{}" , s) ,
152
- ValueParser :: Count ( false ) => write ! ( f, "count" ) ,
153
- ValueParser :: Count ( true ) => write ! ( f, "report_count" ) ,
144
+ ValueParser :: Count => write ! ( f, "count" ) ,
154
145
ValueParser :: Sum => write ! ( f, "sum" ) ,
155
146
ValueParser :: Bases => write ! ( f, "bases" ) ,
156
147
ValueParser :: ChromStartEnd => write ! ( f, "chrom_start_end" ) ,
@@ -182,21 +173,10 @@ impl ColumnReporter for Column<'_> {
182
173
& self . number
183
174
}
184
175
185
- fn value (
186
- & self ,
187
- r : & Intersections ,
188
- report_options : Arc < ReportOptions > ,
189
- ) -> Result < Value , ColumnError > {
176
+ fn value ( & self , r : & ReportFragment ) -> Result < Value , ColumnError > {
190
177
// TODO: accept writer and write to it directly.
191
178
match & self . value_parser {
192
- Some ( ValueParser :: Count ( false ) ) => {
193
- // Return the count of overlapping intervals
194
- Ok ( Value :: Int ( r. overlapping . len ( ) as i32 ) )
195
- }
196
- Some ( ValueParser :: Count ( true ) ) => {
197
- let report = r. report ( & report_options) ;
198
- Ok ( Value :: Int ( report. len ( ) as i32 ) )
199
- }
179
+ Some ( ValueParser :: Count ) => Ok ( Value :: Int ( r. b . len ( ) as i32 ) ) ,
200
180
Some ( ValueParser :: Sum ) => {
201
181
// Sum the scores of overlapping intervals if they exist
202
182
// This is more complex as we need to extract scores from the intervals
@@ -207,47 +187,40 @@ impl ColumnReporter for Column<'_> {
207
187
// Calculate total number of bases covered by overlapping intervals
208
188
// Use the report functionality to get the base count
209
189
210
- let report = r. report ( & report_options) ;
211
-
212
- let bases = report. count_bases_by_id ( ) ;
213
- let total_bases: i32 = bases. iter ( ) . sum :: < u64 > ( ) as i32 ;
190
+ let bases =
191
+ r. b . iter ( )
192
+ . map ( |b| {
193
+ let b = b. try_lock ( ) . expect ( "failed to lock b interval in Bases" ) ;
194
+ b. stop ( ) - b. start ( )
195
+ } )
196
+ . sum :: < u64 > ( ) as i32 ;
214
197
215
- Ok ( Value :: Int ( total_bases ) )
198
+ Ok ( Value :: Int ( bases ) )
216
199
}
217
200
Some ( ValueParser :: ChromStartEnd ) => {
218
- let base_interval = r
219
- . base_interval
220
- . try_lock ( )
221
- . expect ( "failed to lock base_interval" ) ;
222
- let s = format ! (
223
- "{}\t {}\t {}" ,
224
- base_interval. chrom( ) ,
225
- base_interval. start( ) ,
226
- base_interval. stop( )
227
- ) ;
228
- Ok ( Value :: String ( s) )
201
+ if let Some ( a) = & r. a {
202
+ let a = a
203
+ . try_lock ( )
204
+ . expect ( "failed to lock a interval in ChromStartEnd" ) ;
205
+ let s = format ! ( "{}:{}-{}" , a. chrom( ) , a. start( ) , a. stop( ) ) ;
206
+ Ok ( Value :: String ( s) )
207
+ } else {
208
+ Err ( ColumnError :: InvalidValue ( format ! (
209
+ "No base interval for {}" ,
210
+ r. id
211
+ ) ) )
212
+ }
229
213
}
230
214
Some ( ValueParser :: OriginalInterval ) => {
231
215
// Return the original interval as a string
232
- let base_interval = r
233
- . base_interval
234
- . try_lock ( )
235
- . expect ( "failed to lock base_interval" ) ;
236
- let s = format ! (
237
- "{}\t {}\t {}" ,
238
- base_interval. chrom( ) ,
239
- base_interval. start( ) ,
240
- base_interval. stop( )
241
- ) ;
242
- Ok ( Value :: String ( s) )
216
+ unimplemented ! ( "original_interval" ) ;
243
217
}
244
218
Some ( ValueParser :: PythonExpression ( expr) ) => {
245
219
// For Python expressions, we should use the compiled Python object
246
220
if let Some ( py) = & self . py {
247
221
// Convert intersection to PyIntersections and evaluate
248
- let py_intersection =
249
- crate :: py:: PyIntersections :: new ( r. clone ( ) , report_options) ;
250
- match py. eval ( py_intersection) {
222
+ let py_fragment = PyReportFragment :: new ( r. clone ( ) ) ;
223
+ match py. eval ( py_fragment) {
251
224
Ok ( result) => Ok ( Value :: String ( result) ) ,
252
225
Err ( e) => Err ( ColumnError :: PythonError ( format ! (
253
226
"Python error when evaluating expression: \" {}\" : {}" ,
@@ -269,7 +242,7 @@ impl ColumnReporter for Column<'_> {
269
242
}
270
243
None => {
271
244
// Default behavior when no parser is specified - return count
272
- Ok ( Value :: Int ( r. overlapping . len ( ) as i32 ) )
245
+ Ok ( Value :: Int ( r. b . len ( ) as i32 ) )
273
246
}
274
247
}
275
248
}
@@ -364,7 +337,7 @@ impl TryFrom<&str> for Column<'_> {
364
337
Type :: Integer ,
365
338
"Count" . to_string ( ) ,
366
339
Number :: One ,
367
- Some ( ValueParser :: Count ( false ) ) ,
340
+ Some ( ValueParser :: Count ) ,
368
341
) ,
369
342
"sum" => Column :: new (
370
343
"sum" . to_string ( ) ,
0 commit comments