@@ -10,6 +10,7 @@ use itertools::Itertools;
10
10
use std:: collections:: { BTreeMap , BTreeSet } ;
11
11
use std:: ops:: { Deref , DerefMut } ;
12
12
13
+ #[ derive( Clone , Debug ) ]
13
14
pub enum MultiColorTimeSeries < ' a , P : PassbandTrait , T : Float > {
14
15
Mapping ( MappedMultiColorTimeSeries < ' a , P , T > ) ,
15
16
Flat ( FlatMultiColorTimeSeries < ' a , P , T > ) ,
40
41
}
41
42
}
42
43
44
+ pub fn passband_count ( & self ) -> usize {
45
+ match self {
46
+ Self :: Mapping ( mapping) => mapping. passband_count ( ) ,
47
+ Self :: Flat ( flat) => flat. passband_count ( ) ,
48
+ // Both flat and mapping have the same number of passbands and should be equally fast
49
+ Self :: MappingFlat { flat, .. } => flat. passband_count ( ) ,
50
+ }
51
+ }
52
+
43
53
pub fn from_map ( map : impl Into < BTreeMap < P , TimeSeries < ' a , T > > > ) -> Self {
44
54
Self :: Mapping ( MappedMultiColorTimeSeries :: new ( map) )
45
55
}
@@ -53,21 +63,43 @@ where
53
63
Self :: Flat ( FlatMultiColorTimeSeries :: new ( t, m, w, passbands) )
54
64
}
55
65
56
- pub fn mapping_mut ( & mut self ) -> & mut MappedMultiColorTimeSeries < ' a , P , T > {
66
+ fn ensure_mapping ( & mut self ) -> & mut Self {
57
67
if matches ! ( self , MultiColorTimeSeries :: Flat ( _) ) {
58
- let dummy_self = Self :: Mapping ( MappedMultiColorTimeSeries :: new ( BTreeMap :: new ( ) ) ) ;
59
- * self = match std:: mem:: replace ( self , dummy_self) {
68
+ take_mut:: take ( self , |slf| match slf {
60
69
Self :: Flat ( mut flat) => {
61
70
let mapping = MappedMultiColorTimeSeries :: from_flat ( & mut flat) ;
62
71
Self :: MappingFlat { mapping, flat }
63
72
}
64
- _ => unreachable ! ( ) ,
65
- }
73
+ _ => unreachable ! ( "We just checked that we are in ::Flat variant" ) ,
74
+ } ) ;
66
75
}
76
+ self
77
+ }
78
+
79
+ fn enforce_mapping ( & mut self ) -> & mut Self {
67
80
match self {
81
+ Self :: Mapping ( _) => { }
82
+ Self :: Flat ( _flat) => take_mut:: take ( self , |slf| match slf {
83
+ Self :: Flat ( flat) => Self :: Mapping ( flat. into ( ) ) ,
84
+ _ => unreachable ! ( "We just checked that we are in ::Flat variant" ) ,
85
+ } ) ,
86
+ Self :: MappingFlat { .. } => {
87
+ take_mut:: take ( self , |slf| match slf {
88
+ Self :: MappingFlat { mapping, .. } => Self :: Mapping ( mapping) ,
89
+ _ => unreachable ! ( "We just checked that we are in ::MappingFlat variant" ) ,
90
+ } ) ;
91
+ }
92
+ }
93
+ self
94
+ }
95
+
96
+ pub fn mapping_mut ( & mut self ) -> & mut MappedMultiColorTimeSeries < ' a , P , T > {
97
+ match self . ensure_mapping ( ) {
68
98
Self :: Mapping ( mapping) => mapping,
69
99
Self :: Flat ( _flat) => {
70
- unreachable ! ( "::Flat variant is already transofrmed to ::MappingFlat" )
100
+ unreachable ! (
101
+ "::Flat variant is already transformed to ::MappingFlat in ensure_mapping"
102
+ )
71
103
}
72
104
Self :: MappingFlat { mapping, .. } => mapping,
73
105
}
@@ -81,20 +113,25 @@ where
81
113
}
82
114
}
83
115
84
- pub fn flat_mut ( & mut self ) -> & mut FlatMultiColorTimeSeries < ' a , P , T > {
116
+ fn ensure_flat ( & mut self ) -> & mut Self {
85
117
if matches ! ( self , MultiColorTimeSeries :: Mapping ( _) ) {
86
- let dummy_self = Self :: Mapping ( MappedMultiColorTimeSeries :: new ( BTreeMap :: new ( ) ) ) ;
87
- * self = match std:: mem:: replace ( self , dummy_self) {
118
+ take_mut:: take ( self , |slf| match slf {
88
119
Self :: Mapping ( mut mapping) => {
89
120
let flat = FlatMultiColorTimeSeries :: from_mapping ( & mut mapping) ;
90
121
Self :: MappingFlat { mapping, flat }
91
122
}
92
- _ => unreachable ! ( ) ,
93
- }
123
+ _ => unreachable ! ( "We just checked that we are in ::Mapping variant" ) ,
124
+ } ) ;
94
125
}
95
- match self {
126
+ self
127
+ }
128
+
129
+ pub fn flat_mut ( & mut self ) -> & mut FlatMultiColorTimeSeries < ' a , P , T > {
130
+ match self . ensure_flat ( ) {
96
131
Self :: Mapping ( _mapping) => {
97
- unreachable ! ( "::Mapping veriant is already transformed to ::MappingFlat" )
132
+ unreachable ! (
133
+ "::Mapping variant is already transformed to ::MappingFlat in ensure_flat"
134
+ )
98
135
}
99
136
Self :: Flat ( flat) => flat,
100
137
Self :: MappingFlat { flat, .. } => flat,
@@ -124,12 +161,45 @@ where
124
161
Self :: MappingFlat { mapping, .. } => Either :: Left ( mapping. passbands ( ) ) ,
125
162
}
126
163
}
164
+
165
+ /// Inserts new pair of passband and time series into the multicolor time series.
166
+ ///
167
+ /// It always converts [MultiColorTimeSeries] to [MultiColorTimeSeries::Mapping] variant.
168
+ /// Also it replaces existing time series if passband is already present, and returns old time
169
+ /// series.
170
+ pub fn insert ( & mut self , passband : P , ts : TimeSeries < ' a , T > ) -> Option < TimeSeries < ' a , T > > {
171
+ match self . enforce_mapping ( ) {
172
+ Self :: Mapping ( mapping) => mapping. 0 . insert ( passband, ts) ,
173
+ _ => unreachable ! ( "We just converted self to ::Mapping variant" ) ,
174
+ }
175
+ }
127
176
}
128
177
178
+ impl < ' a , P , T > Default for MultiColorTimeSeries < ' a , P , T >
179
+ where
180
+ P : PassbandTrait ,
181
+ T : Float ,
182
+ {
183
+ fn default ( ) -> Self {
184
+ Self :: Mapping ( MappedMultiColorTimeSeries :: new ( BTreeMap :: new ( ) ) )
185
+ }
186
+ }
187
+
188
+ #[ derive( Debug , Clone ) ]
129
189
pub struct MappedMultiColorTimeSeries < ' a , P : PassbandTrait , T : Float > (
130
190
BTreeMap < P , TimeSeries < ' a , T > > ,
131
191
) ;
132
192
193
+ impl < ' a , P , T > PartialEq for MappedMultiColorTimeSeries < ' a , P , T >
194
+ where
195
+ P : PassbandTrait ,
196
+ T : Float ,
197
+ {
198
+ fn eq ( & self , other : & Self ) -> bool {
199
+ self . 0 . eq ( & other. 0 )
200
+ }
201
+ }
202
+
133
203
impl < ' a , ' p , P , T > MappedMultiColorTimeSeries < ' a , P , T >
134
204
where
135
205
P : PassbandTrait + ' p ,
@@ -173,6 +243,10 @@ where
173
243
self . total_lenu ( ) . value_as :: < T > ( ) . unwrap ( )
174
244
}
175
245
246
+ pub fn passband_count ( & self ) -> usize {
247
+ self . 0 . len ( )
248
+ }
249
+
176
250
pub fn passbands < ' slf > (
177
251
& ' slf self ,
178
252
) -> std:: collections:: btree_map:: Keys < ' slf , P , TimeSeries < ' a , T > >
@@ -267,6 +341,7 @@ impl<'a, P: PassbandTrait, T: Float> DerefMut for MappedMultiColorTimeSeries<'a,
267
341
}
268
342
}
269
343
344
+ #[ derive( Debug , Clone ) ]
270
345
pub struct FlatMultiColorTimeSeries < ' a , P : PassbandTrait , T : Float > {
271
346
pub t : DataSample < ' a , T > ,
272
347
pub m : DataSample < ' a , T > ,
@@ -275,6 +350,19 @@ pub struct FlatMultiColorTimeSeries<'a, P: PassbandTrait, T: Float> {
275
350
passband_set : BTreeSet < P > ,
276
351
}
277
352
353
+ impl < ' a , P , T > PartialEq for FlatMultiColorTimeSeries < ' a , P , T >
354
+ where
355
+ P : PassbandTrait ,
356
+ T : Float ,
357
+ {
358
+ fn eq ( & self , other : & Self ) -> bool {
359
+ self . t == other. t
360
+ && self . m == other. m
361
+ && self . w == other. w
362
+ && self . passbands == other. passbands
363
+ }
364
+ }
365
+
278
366
impl < ' a , P , T > FlatMultiColorTimeSeries < ' a , P , T >
279
367
where
280
368
P : PassbandTrait ,
@@ -347,4 +435,127 @@ where
347
435
pub fn total_lenf ( & self ) -> T {
348
436
self . t . sample . len ( ) . value_as :: < T > ( ) . unwrap ( )
349
437
}
438
+
439
+ pub fn passband_count ( & self ) -> usize {
440
+ self . passband_set . len ( )
441
+ }
442
+ }
443
+
444
+ impl < ' a , P , T > From < FlatMultiColorTimeSeries < ' a , P , T > > for MappedMultiColorTimeSeries < ' a , P , T >
445
+ where
446
+ P : PassbandTrait ,
447
+ T : Float ,
448
+ {
449
+ fn from ( mut flat : FlatMultiColorTimeSeries < ' a , P , T > ) -> Self {
450
+ Self :: from_flat ( & mut flat)
451
+ }
452
+ }
453
+
454
+ impl < ' a , P , T > From < MappedMultiColorTimeSeries < ' a , P , T > > for FlatMultiColorTimeSeries < ' a , P , T >
455
+ where
456
+ P : PassbandTrait ,
457
+ T : Float ,
458
+ {
459
+ fn from ( mut mapped : MappedMultiColorTimeSeries < ' a , P , T > ) -> Self {
460
+ Self :: from_mapping ( & mut mapped. 0 )
461
+ }
462
+ }
463
+
464
+ impl < ' a , P , T > From < FlatMultiColorTimeSeries < ' a , P , T > > for MultiColorTimeSeries < ' a , P , T >
465
+ where
466
+ P : PassbandTrait ,
467
+ T : Float ,
468
+ {
469
+ fn from ( flat : FlatMultiColorTimeSeries < ' a , P , T > ) -> Self {
470
+ Self :: Flat ( flat)
471
+ }
472
+ }
473
+
474
+ impl < ' a , P , T > From < MappedMultiColorTimeSeries < ' a , P , T > > for MultiColorTimeSeries < ' a , P , T >
475
+ where
476
+ P : PassbandTrait ,
477
+ T : Float ,
478
+ {
479
+ fn from ( mapped : MappedMultiColorTimeSeries < ' a , P , T > ) -> Self {
480
+ Self :: Mapping ( mapped)
481
+ }
482
+ }
483
+
484
+ impl < ' a , P , T > From < MultiColorTimeSeries < ' a , P , T > > for FlatMultiColorTimeSeries < ' a , P , T >
485
+ where
486
+ P : PassbandTrait ,
487
+ T : Float ,
488
+ {
489
+ fn from ( mcts : MultiColorTimeSeries < ' a , P , T > ) -> Self {
490
+ match mcts {
491
+ MultiColorTimeSeries :: Flat ( flat) => flat,
492
+ MultiColorTimeSeries :: Mapping ( mapped) => mapped. into ( ) ,
493
+ MultiColorTimeSeries :: MappingFlat { flat, .. } => flat,
494
+ }
495
+ }
496
+ }
497
+
498
+ impl < ' a , P , T > From < MultiColorTimeSeries < ' a , P , T > > for MappedMultiColorTimeSeries < ' a , P , T >
499
+ where
500
+ P : PassbandTrait ,
501
+ T : Float ,
502
+ {
503
+ fn from ( mcts : MultiColorTimeSeries < ' a , P , T > ) -> Self {
504
+ match mcts {
505
+ MultiColorTimeSeries :: Flat ( flat) => flat. into ( ) ,
506
+ MultiColorTimeSeries :: Mapping ( mapping) => mapping,
507
+ MultiColorTimeSeries :: MappingFlat { mapping, .. } => mapping,
508
+ }
509
+ }
510
+ }
511
+
512
+ #[ cfg( test) ]
513
+ mod tests {
514
+ use super :: * ;
515
+
516
+ use crate :: MonochromePassband ;
517
+
518
+ use ndarray:: Array1 ;
519
+
520
+ #[ test]
521
+ fn multi_color_ts_insert ( ) {
522
+ let mut mcts = MultiColorTimeSeries :: default ( ) ;
523
+ mcts. insert (
524
+ MonochromePassband :: new ( 4700.0 , "g" ) ,
525
+ TimeSeries :: new_without_weight ( Array1 :: linspace ( 0.0 , 1.0 , 11 ) , Array1 :: zeros ( 11 ) ) ,
526
+ ) ;
527
+ assert_eq ! ( mcts. passband_count( ) , 1 ) ;
528
+ assert_eq ! ( mcts. total_lenu( ) , 11 ) ;
529
+ mcts. insert (
530
+ MonochromePassband :: new ( 6200.0 , "r" ) ,
531
+ TimeSeries :: new_without_weight ( Array1 :: linspace ( 0.0 , 1.0 , 6 ) , Array1 :: zeros ( 6 ) ) ,
532
+ ) ;
533
+ assert_eq ! ( mcts. passband_count( ) , 2 ) ;
534
+ assert_eq ! ( mcts. total_lenu( ) , 17 ) ;
535
+ }
536
+
537
+ fn compare_variants < P : PassbandTrait , T : Float > ( mcts : MultiColorTimeSeries < P , T > ) {
538
+ let flat: FlatMultiColorTimeSeries < _ , _ > = mcts. clone ( ) . into ( ) ;
539
+ let mapped: MappedMultiColorTimeSeries < _ , _ > = mcts. clone ( ) . into ( ) ;
540
+ let mapped_from_flat: MappedMultiColorTimeSeries < _ , _ > = flat. clone ( ) . into ( ) ;
541
+ let flat_from_mapped: FlatMultiColorTimeSeries < _ , _ > = mapped. clone ( ) . into ( ) ;
542
+ assert_eq ! ( mapped, mapped_from_flat) ;
543
+ assert_eq ! ( flat, flat_from_mapped) ;
544
+ }
545
+
546
+ #[ test]
547
+ fn convert_between_variants ( ) {
548
+ let mut mcts = MultiColorTimeSeries :: default ( ) ;
549
+ compare_variants ( mcts. clone ( ) ) ;
550
+ mcts. insert (
551
+ MonochromePassband :: new ( 4700.0 , "g" ) ,
552
+ TimeSeries :: new_without_weight ( Array1 :: linspace ( 0.0 , 1.0 , 11 ) , Array1 :: zeros ( 11 ) ) ,
553
+ ) ;
554
+ compare_variants ( mcts. clone ( ) ) ;
555
+ mcts. insert (
556
+ MonochromePassband :: new ( 6200.0 , "r" ) ,
557
+ TimeSeries :: new_without_weight ( Array1 :: linspace ( 0.0 , 1.0 , 6 ) , Array1 :: zeros ( 6 ) ) ,
558
+ ) ;
559
+ compare_variants ( mcts. clone ( ) ) ;
560
+ }
350
561
}
0 commit comments