File | /wise/base/deliv/dev/lib/perl/WISE/Ingest/Seq.pm | Statements Executed | 697854 | Total Time | 1.35006700000011 seconds |
Calls | P | F | Exclusive Time |
Inclusive Time |
Subroutine | |
---|---|---|---|---|---|---|
15825 | 1 | 1 | 0.50300 | 1.01434 | WISE::Ingest::Seq::PEF:: | find_bracketing_events |
1 | 1 | 1 | 0.42030 | 0.42032 | WISE::Ingest::Seq::PEF:: | index_bracketing_events |
1 | 1 | 1 | 0.18771 | 0.18771 | WISE::Ingest::Seq::PEF:: | track_events |
1 | 1 | 1 | 0.18160 | 1.81513 | WISE::Ingest::Seq::PEF:: | load_event_ipactbl |
15828 | 4 | 1 | 0.09107 | 0.09109 | WISE::Ingest::Seq:: | _isopt |
1 | 1 | 1 | 8.5e-5 | 1.81537 | WISE::Ingest::Seq::PEF:: | new |
1 | 1 | 1 | 4.2e-5 | 4.2e-5 | WISE::Ingest::Seq::PEF:: | event_tbl |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq:: | BEGIN |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | BEGIN |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | _event_ipactbl_meta |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | _get_next_rec |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | _slurp_hdr |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | build_event_table |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | dump_event_ipactbl |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | err |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | event |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | event_ipactbl_meta |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | event_num |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | hdr |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | info |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | key_event |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | naif |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | next_event |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | next_key_event |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | offset_orbit |
0 | 0 | 0 | 0 | 0 | WISE::Ingest::Seq::PEF:: | recognize_event |
Line | Stmts. | Exclusive Time | Avg. | Code |
---|---|---|---|---|
1 | #! /usr/bin/env perl | |||
2 | ||||
3 | 3 | 3.5e-5 | 1.2e-5 | use strict; # spent 17µs making 1 call to strict::import |
4 | 3 | 5.4e-5 | 1.8e-5 | use warnings; # spent 48µs making 1 call to warnings::import |
5 | ||||
6 | package WISE::Ingest::Seq; | |||
7 | ||||
8 | use WISE::Env ( | |||
9 | mod => 'WISE::Ingest::Seq', # spent 534µs making 1 call to WISE::Env::import | |||
10 | cfglib => '<:LIB:>', | |||
11 | version => '$Id: Seq.pm 7112 2010-01-30 00:51:55Z tim $ ', | |||
12 | 3 | 3.2e-5 | 1.1e-5 | ); |
13 | ||||
14 | 3 | 3.3e-5 | 1.1e-5 | use Exporter::Lite; # spent 42µs making 1 call to Exporter::Lite::import |
15 | 3 | 0.00014 | 4.5e-5 | use vars qw(@ISA @EXPORT_OK); # spent 42µs making 1 call to vars::import |
16 | 1 | 2.0e-6 | 2.0e-6 | @EXPORT_OK = (); |
17 | ||||
18 | # spent 91.1ms (91.1+14µs) within WISE::Ingest::Seq::_isopt which was called 15828 times, avg 6µs/call:
# 15825 times (91.0ms+0) by WISE::Ingest::Seq::PEF::find_bracketing_events at line 852, avg 6µs/call
# once (20µs+4µs) by WISE::Ingest::Seq::PEF::index_bracketing_events at line 872
# once (16µs+7µs) by WISE::Ingest::Seq::PEF::new at line 272
# once (9µs+3µs) by WISE::Ingest::Seq::PEF::load_event_ipactbl at line 908 | |||
19 | 31656 | 0.05220 | 1.6e-6 | my $r = @_ ? shift : $_; |
20 | return ref($r)=~/hash/i && ! UNIVERSAL::isa($r,__PACKAGE__); # spent 14µs making 3 calls to UNIVERSAL::isa, avg 5µs/call | |||
21 | } | |||
22 | ||||
23 | package WISE::Ingest::Seq::PEF; | |||
24 | ||||
25 | 3 | 5.9e-5 | 2.0e-5 | use vars qw(@ISA @EXPORT_OK); # spent 41µs making 1 call to vars::import |
26 | ||||
27 | 1 | 1.2e-5 | 1.2e-5 | my ($err, $warn) = WISE::Env->err_prefix(); # spent 35µs making 1 call to WISE::Env::err_prefix |
28 | ||||
29 | 1 | 1.9e-5 | 1.9e-5 | @ISA = qw(WISE::Ingest::Seq); |
30 | ||||
31 | 3 | 3.2e-5 | 1.1e-5 | use Clone; # spent 40µs making 1 call to Exporter::import |
32 | ||||
33 | 3 | 2.5e-5 | 8.3e-6 | use WISE; # spent 592µs making 1 call to WISE::import |
34 | 3 | 2.5e-5 | 8.3e-6 | use WISE::Ingest::NAIF; # spent 19µs making 1 call to Exporter::Lite::import |
35 | 3 | 1.9e-5 | 6.3e-6 | use File::Basename (); |
36 | ||||
37 | 3 | 0.00681 | 0.00227 | use Carp 'confess'; # spent 56µs making 1 call to Exporter::import |
38 | ||||
39 | # Events subject to long term tracking | |||
40 | 1 | 3.0e-6 | 3.0e-6 | my %track = ( |
41 | ANNEAL=>{SCAN=>1}, | |||
42 | ); | |||
43 | ||||
44 | # Event types; 0=single event (start==stop), | |||
45 | # 1=start of a bracketted event, | |||
46 | # 2=stop of a bracketted event, | |||
47 | # 3=start and stop of a bracketted event (both times in 1 event), | |||
48 | # 4=split event boundary, start or stop | |||
49 | # Types 1&2 are assigned during evaluation of type 4 events | |||
50 | 1 | 0.00011 | 0.00011 | my @event_specs = ( |
51 | # Primary | |||
52 | { | |||
53 | name => 'NEP', | |||
54 | id => 1, | |||
55 | type => 0, # Single, unbracketed event | |||
56 | quick_re => 'N_POLE_CROSS', | |||
57 | ev_field => 'comment', | |||
58 | ev_re => qr'Spacecraft\s+north\s+pole\s+crossing'ix, | |||
59 | data_field => 'event', | |||
60 | data_re => qr'GEV,N_POLE_CROSS,.*,(\d+\.[05])0*;'ix, | |||
61 | data_names => [qw/orbit_num/], | |||
62 | }, | |||
63 | { | |||
64 | name => 'SEP', | |||
65 | id => 2, | |||
66 | type => 0, # Single, unbracketed event | |||
67 | quick_re => 'S_POLE_CROSS', | |||
68 | ev_field => 'comment', | |||
69 | ev_re => qr'Spacecraft\s+south\s+pole\s+crossing'ix, | |||
70 | data_field => 'event', | |||
71 | data_re => qr'GEV,S_POLE_CROSS,.*,(\d+\.[05])0*;'ix, | |||
72 | data_names => [qw/orbit_num/], | |||
73 | }, | |||
74 | { | |||
75 | name => 'SCAN_BNDRY', | |||
76 | id => 3, | |||
77 | type => 4, # Boundary for bracketed event | |||
78 | quick_re => 'SLEW_', | |||
79 | ev_field => 'event', | |||
80 | ev_re => qr'NOTE,SEQ,.*, | |||
81 | ( | |||
82 | (SLEW_START_(SCAN|SURVEY)_TO_\S+) | | |||
83 | (SLEW_SETTLE_\S+_TO_(SURVEY|SCAN)) | | |||
84 | (SLEW_START_TO_NEAR_PT_STDBY) | |||
85 | )'ix, | |||
86 | data_field => 'event', | |||
87 | data_re => qr'SLEW_(START|SETTLE)_? | |||
88 | (TDRS|SURVEY|SCAN)? | |||
89 | _TO_ | |||
90 | (TDRS|SURVEY|SCAN|NEAR_PT_STDBY)'ix, | |||
91 | data_names => [qw/turn_state from to/], | |||
92 | }, | |||
93 | { | |||
94 | name => 'SAA', | |||
95 | id => 4, | |||
96 | type => 3, # Start AND stop times in one event | |||
97 | quick_re => 'GEV,SAA', | |||
98 | ev_field => 'comment', | |||
99 | ev_re => qr'South\s+Atlantic\s+Anomaly'ix, | |||
100 | data_field => 'event', | |||
101 | data_re => qr'GEV,SAA,.*, | |||
102 | (2\d\d\d-\d\d\dT\d\d:\d\d:\d\d\.\d*),'ix, | |||
103 | data_names => [qw/end_ydt/], | |||
104 | }, | |||
105 | { | |||
106 | name => 'MOON', | |||
107 | id => 5, | |||
108 | type => 3, # Start AND stop times in one event | |||
109 | quick_re => 'GEV,MOON', | |||
110 | ev_field => 'comment', | |||
111 | ev_re => qr'Moon\s+Near\s+Z-Axis'ix, | |||
112 | data_field => 'event', | |||
113 | data_re => qr'GEV,MOON_ZAXIS,.*, | |||
114 | (2\d\d\d-\d\d\dT\d\d:\d\d:\d\d\.\d*),'ix, | |||
115 | data_names => [qw/end_ydt/], | |||
116 | }, | |||
117 | { | |||
118 | name => 'NODATA_BNDRY', | |||
119 | id => 6, | |||
120 | type => 4, | |||
121 | quick_re => 'CMD,PLBANDALL', | |||
122 | ev_field => 'comment', | |||
123 | ev_re => qr'(ENABLE|DISABLE)\s+SCIENCE\s+DATA'ix, | |||
124 | data_field => 'comment', | |||
125 | data_re => qr'(ENABLE|DISABLE)'ix, | |||
126 | data_names => [qw/data_state/], | |||
127 | }, | |||
128 | { | |||
129 | name => 'ANNEAL', | |||
130 | id => 7, | |||
131 | type => 5, # Start AND duration times in one event | |||
132 | quick_re => 'NOTE,SEQ,ANNEAL', | |||
133 | ev_field => 'event', | |||
134 | ev_re => qr'ANNEALING\s+HEATER\s+DRIVE\s+.*\sON\s'ix, | |||
135 | data_field => 'event', | |||
136 | data_re => qr'\sON\s+TIMER\s*=\s*(\d+)\s*;'ix, | |||
137 | data_names => [qw/duration/], | |||
138 | }, | |||
139 | # Informatory | |||
140 | { | |||
141 | name => 'ANODE', | |||
142 | id => 11, | |||
143 | type => 0, | |||
144 | quick_re => 'GEV,NODE_CROSS', | |||
145 | ev_field => 'comment', | |||
146 | ev_re => qr'Spacecraft\s+ascending\s+node\s+crossing'ix, | |||
147 | data_field => 'event', | |||
148 | data_re => qr'GEV,NODE_CROSS,.*,(\d+\.[05])0*;'ix, | |||
149 | data_names => [qw/orbit_num/], | |||
150 | }, | |||
151 | { | |||
152 | name => 'TDRS_BNDRY', | |||
153 | id => 12, | |||
154 | type => 4, | |||
155 | quick_re => 'TDRS', | |||
156 | ev_field => 'event', | |||
157 | ev_re => qr'NOTE,SEQ,.*, | |||
158 | ((SLEW_START_TDRS_TO_(SURVEY|PT_STDBY)) | | |||
159 | (SLEW_COMPLETE_(SURVEY|PT_STDBY)_TO_TDRS))'ix, | |||
160 | data_field => 'event', | |||
161 | data_re => qr'SLEW_(START|COMPLETE)_ | |||
162 | (TDRS|SURVEY|SCAN|PT_STDBY)_TO_ | |||
163 | (TDRS|SURVEY|SCAN|PT_STDBY)'ix, | |||
164 | data_names => [qw/turn_state from to/], | |||
165 | }, | |||
166 | { | |||
167 | name => '12PM', | |||
168 | id => 13, | |||
169 | type => 0, | |||
170 | quick_re => 'GEV,SUN_NOON', | |||
171 | ev_field => 'comment', | |||
172 | ev_re => qr'GEV,SUN_NOON'ix, | |||
173 | data_field => 'event', | |||
174 | data_re => qr'GEV,SUN_NOON,.*,(\d+\.[05])0*;'ix, | |||
175 | data_names => [qw/orbit_num/], | |||
176 | }, | |||
177 | { | |||
178 | name => '6AM', | |||
179 | id => 14, | |||
180 | type => 0, | |||
181 | quick_re => 'GEV,SUN_6AM', | |||
182 | ev_field => 'event', | |||
183 | ev_re => qr'GEV,SUN_6AM'ix, | |||
184 | data_field => 'event', | |||
185 | data_re => qr'GEV,SUN_6AM,.*,(\d+\.[05])0*;'ix, | |||
186 | data_names => [qw/orbit_num/], | |||
187 | }, | |||
188 | { | |||
189 | name => '6PM', | |||
190 | id => 15, | |||
191 | type => 0, | |||
192 | quick_re => 'GEV,SUN_6PM', | |||
193 | ev_field => 'event', | |||
194 | ev_re => qr'GEV,SUN_6PM'ix, | |||
195 | data_field => 'event', | |||
196 | data_re => qr'GEV,SUN_6PM,.*,(\d+\.[05])0*;'ix, | |||
197 | data_names => [qw/orbit_num/], | |||
198 | }, | |||
199 | { | |||
200 | name => '12AM', | |||
201 | id => 16, | |||
202 | type => 0, | |||
203 | quick_re => 'GEV,SUN_MIDNIGHT', | |||
204 | ev_field => 'event', | |||
205 | ev_re => qr'GEV,SUN_MIDNIGHT'ix, | |||
206 | data_field => 'event', | |||
207 | data_re => qr'GEV,SUN_MIDNIGHT,.*,(\d+\.[05])0*;'ix, | |||
208 | data_names => [qw/orbit_num/], | |||
209 | }, | |||
210 | { | |||
211 | name => 'MOM', | |||
212 | id => 17, | |||
213 | type => 5, # Start AND duration times in one event | |||
214 | quick_re => 'NOTE,SEQ,MOM_DUMP', | |||
215 | ev_field => 'event', | |||
216 | ev_re => qr'MOMENTUM_UNLOAD_DURATION'ix, | |||
217 | data_field => 'event', | |||
218 | data_re => qr'MOMENTUM_UNLOAD_DURATION\s*=\s*(\d+:\d+:\d+)\s*;'ix, | |||
219 | data_names => [qw/duration/], | |||
220 | }, | |||
221 | { | |||
222 | name => 'OCCULT', | |||
223 | id => 18, | |||
224 | type => 3, # Start AND stop times in one event | |||
225 | quick_re => 'GEV,OCCULT', | |||
226 | ev_field => 'event', | |||
227 | ev_re => qr'GEV,OCCULT'ix, | |||
228 | data_field => 'event', | |||
229 | data_re => qr'GEV,OCCULT,.*, | |||
230 | (2\d\d\d-\d\d\dT\d\d:\d\d:\d\d\.\d*),'ix, | |||
231 | data_names => [qw/end_ydt/], | |||
232 | }, | |||
233 | { | |||
234 | name => 'IMCAL', | |||
235 | id => 19, | |||
236 | type => 5, # Start AND duration times in one event | |||
237 | quick_re => 'NOTE,SEQ,IMAGE_CAL', | |||
238 | ev_field => 'event', | |||
239 | ev_re => qr'NOTE,SEQ,IMAGE_CAL'ix, | |||
240 | data_field => 'event', | |||
241 | data_re => qr'CALIBRATION[\s_]+DURATION[\s_]+FOR\s+(\d+:\d+:\d+)\s*;'ix, | |||
242 | data_names => [qw/duration/], | |||
243 | }, | |||
244 | { | |||
245 | name => 'SBAND_BNDRY', | |||
246 | id => 20, | |||
247 | type => 4, # Boundary for bracketed event | |||
248 | quick_re => 'TCSXPOWER', | |||
249 | ev_field => 'event', | |||
250 | ev_re => qr'CMD,TCSXPOWER,.*,STATE='ix, | |||
251 | data_field => 'event', | |||
252 | data_re => qr'CMD,TCSXPOWER,.*,STATE=(\d+);'ix, | |||
253 | data_names => [qw/onoff/], | |||
254 | }, | |||
255 | { | |||
256 | name => 'SWITCH', | |||
257 | id => 21, | |||
258 | type => 0, # Start AND duration times in one event | |||
259 | quick_re => ',CMKILLSEQ,', | |||
260 | ev_field => 'event', | |||
261 | ev_re => qr'CMD,CMKILLSEQ,'ix, | |||
262 | data_field => 'event', | |||
263 | data_re => qr'FNAME=([^;]+);'ix, | |||
264 | data_names => [qw/prevpef/], | |||
265 | }, | |||
266 | ); | |||
267 | ||||
268 | 1 | 1.5e-5 | 1.5e-5 | my $quick_re = "(".join(")|(", map { $_->{quick_re} } @event_specs).")"; |
269 | ||||
270 | # spent 1.82s (85µs+1.82) within WISE::Ingest::Seq::PEF::new which was called
# once (85µs+1.82s) by main::load_events at line 335 of /wise/base/deliv/dev/bin/wdate | |||
271 | 21 | 8.3e-5 | 4.0e-6 | my $class = shift; |
272 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; # spent 23µs making 1 call to WISE::Ingest::Seq::_isopt | |||
273 | my $file = shift; | |||
274 | my $fromtbl = $opts->{from_tbl}; | |||
275 | my $naif = $opts->{naif}; | |||
276 | my $this = {}; | |||
277 | $class = ref($class) || $class; | |||
278 | ||||
279 | $this->{file} = $file; | |||
280 | $this->{from_tbl} = $fromtbl; | |||
281 | $this->{base} = File::Basename::basename($file); # spent 133µs making 1 call to File::Basename::basename | |||
282 | $this->{verbose} = $opts->{verbose}; | |||
283 | $this->{pef_ydt_start} = $opts->{pef_ydt_start}; | |||
284 | $this->{pef_t_start} = WISE::Time::Str_time($this->{pef_ydt_start},{z=>1}) | |||
285 | if $this->{pef_ydt_start}; | |||
286 | $this->{pef_t_end} = WISE::Time::Str_time($this->{pef_ydt_end}, {z=>1}) | |||
287 | if $this->{pef_ydt_end}; | |||
288 | $this->{pef_t_end} = $opts->{pef_ydt_end}; | |||
289 | $this->{naif} = $naif; | |||
290 | $this->{tls} = $opts->{tls} // '/wise/fops/ref/mos/naif/wise.tls'; | |||
291 | $this->{tsc} = $opts->{tsc} // '/wise/fops/ref/mos/naif/wise.tsc'; | |||
292 | $this->{debug} = $opts->{debug}; | |||
293 | ||||
294 | 2 | 1.3e-5 | 6.5e-6 | if(! $fromtbl) { |
295 | # Parse a PEF file | |||
296 | my $fh; | |||
297 | print "Loading PEF file '$file' ...\n" if $this->{verbose}; | |||
298 | open($fh, "<", $file) | |||
299 | or die "$err: Unable to open '$file'; $!.\n"; | |||
300 | ||||
301 | $this->{fh} = \$fh; | |||
302 | $this->{hdr} = _slurp_hdr($this,$fh); | |||
303 | $this->{next} = {}; | |||
304 | $this->{event_num} = 0; | |||
305 | } else { | |||
306 | # Load an event table | |||
307 | print "Loading event table file '$file' ...\n" if $this->{verbose}; | |||
308 | load_event_ipactbl($this,$file,{orbitoff=>$opts->{orbitoff}}); # spent 1.82s making 1 call to WISE::Ingest::Seq::PEF::load_event_ipactbl | |||
309 | } | |||
310 | ||||
311 | return bless $this, $class; | |||
312 | } | |||
313 | ||||
314 | sub naif { | |||
315 | my $this = shift; | |||
316 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
317 | my $naif = shift; | |||
318 | if(defined $naif) { | |||
319 | $this->{naif} = $naif; | |||
320 | } | |||
321 | return $this->{naif}; | |||
322 | } | |||
323 | ||||
324 | sub build_event_table { | |||
325 | my $this = shift; | |||
326 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
327 | my $pretbl = $opts->{pre_tbl}; # The previous event table | |||
328 | my @keep = @{ $opts->{keep} || [] }; # Needed events (empty=all known) | |||
329 | my @not = @{ $opts->{not} || [] }; # Events to skip | |||
330 | my $tls = $opts->{tls} // $this->{tls} // '/wise/fops/ref/mos/naif/wise.tls'; | |||
331 | my $tsc = $opts->{tsc} // $this->{tsc} // '/wise/fops/ref/mos/naif/wise.tsc'; | |||
332 | my $tbuf = 10; # Time clearance around commands required for switch to new file | |||
333 | my $t2ovlap = 300; # Time to good overlap period from nominal file start time | |||
334 | my $scan_max_dur = $opts->{scan_max_dur} // 6000; # Max. scan duration before punting | |||
335 | my $good_scan_letters = "abxz"; | |||
336 | my @tbl; # Output table | |||
337 | my %open; # Opened but unclosed events | |||
338 | my $scan_letter = 'z'; # Scan started before we get a pole crossing | |||
339 | my $orbit; # Running current orbit number | |||
340 | my %used_scan_ids; # Track used scan IDs | |||
341 | my $fakeorbit = 90000; # In case the file is bad, still want scan IDs | |||
342 | my $verbose = $opts->{verbose} // $this->{verbose}; | |||
343 | my $append = $opts->{append}; # No longer used. Always append the pre-table. | |||
344 | my $t_boundary = $opts->{t_boundary}; # Proposed switch time | |||
345 | my %keep = map { (lc($_)=>1) } @keep; | |||
346 | my %not = map { (lc($_)=>1) } @not; | |||
347 | my $naif = $opts->{naif} || $this->{naif}; | |||
348 | die "$err: Can't specify both keep and not.\n" | |||
349 | if %keep && %not; | |||
350 | ||||
351 | my @pretbl; | |||
352 | ||||
353 | if($pretbl) { | |||
354 | if(ref $pretbl) { | |||
355 | @pretbl = @$pretbl; | |||
356 | } else { | |||
357 | # File name to open and load | |||
358 | print "Loading preceding table '$pretbl' ...\n" | |||
359 | if $verbose; | |||
360 | my $pre = WISE::IPACTbl->new($pretbl) | |||
361 | or die "$err: Can't load pre-table '$pretbl'.\n"; | |||
362 | @pretbl = $pre->data({hashrow=>1}); | |||
363 | } | |||
364 | } | |||
365 | ||||
366 | my $file_t0 = $this->{hdr}{start_t}; | |||
367 | my $file_t1 = $this->{hdr}{end_t}; | |||
368 | ||||
369 | my ($force_switch,$t_switch,$utc_switch); | |||
370 | if($t_boundary) { | |||
371 | # Proposed or forced switch time | |||
372 | $force_switch = $t_boundary =~ s/^=//; | |||
373 | my $tmp = WISE::Time::Str_time($t_boundary,{z=>1}) | |||
374 | or die "$err: Boundary time '$t_boundary' not parseable.\n"; | |||
375 | $t_boundary = $tmp; | |||
376 | if($force_switch) { | |||
377 | $t_switch = $t_boundary; | |||
378 | $utc_switch = WISE::Time::Time_str($t_switch,{form=>4}); | |||
379 | } | |||
380 | } else { | |||
381 | # Default proposed boundary time | |||
382 | $t_boundary = $file_t0+$t2ovlap-$tbuf/2; | |||
383 | } | |||
384 | my $utc_boundary = WISE::Time::Time_str($t_boundary,{form=>4}); | |||
385 | ||||
386 | my $recnum = 0; | |||
387 | my ($pre_t1,$pre_ydt1,$pre_rec1,$pre_name1); | |||
388 | ||||
389 | if(@pretbl) { | |||
390 | # Rebuild event history from extant table. | |||
391 | # Initialize orbit, used scan IDs, and pending (open) events | |||
392 | # by searching through the previous event table | |||
393 | print "Scanning preceding event table for switch time and open events ...\n" | |||
394 | if $verbose; | |||
395 | print "Switch around $utc_boundary.\n" if $verbose; | |||
396 | my $t_last; | |||
397 | my $i = 0; | |||
398 | for my $ev (@pretbl) { | |||
399 | my ($ydt,$t) = ($ev->{ydt}, | |||
400 | WISE::Time::Str_time($ev->{ydt},{z=>1})); | |||
401 | my $t_next; | |||
402 | $t_next = WISE::Time::Str_time($pretbl[$i+1]->{ydt},{z=>1}) | |||
403 | if $pretbl[$i+1]; | |||
404 | # We can skip the rest of the overlap if: | |||
405 | # - We already have a switch time selected (forced) and we've passed it | |||
406 | last if $t_switch && $t >= $t_switch; | |||
407 | # ... or ... | |||
408 | # - We're past the start of the new file and the 5 min. runup period | |||
409 | # (or past the specified time) | |||
410 | # - The current and preceding events were 5 secs away from the boundary | |||
411 | if($t >= $t_boundary+$tbuf/2) { | |||
412 | if(! $t_last || $t_boundary >= $t_last+$tbuf/2) { | |||
413 | # Can switch | |||
414 | $t_switch = $t_boundary; | |||
415 | $utc_switch = WISE::Time::Time_str($t_switch,{form=>4}); | |||
416 | print "Making switch to new file at $utc_switch (event time $ydt) ...\n" | |||
417 | if $verbose; | |||
418 | last; | |||
419 | } else { | |||
420 | # Can't switch here, move boundary forward to next proposed spot | |||
421 | $t_boundary = $t + $tbuf/2; | |||
422 | } | |||
423 | } | |||
424 | my ($ydt_end,$t_end); | |||
425 | ($ydt_end,$t_end) = ($ev->{end_ydt}, | |||
426 | WISE::Time::Str_time($ev->{end_ydt},{z=>1})) | |||
427 | if $ev->{end_ydt} && ($ev->{type}//-1) == 4; | |||
428 | # Save the latest time recorded from the pre-table. It might | |||
429 | # be the end time of a split (type 4) event. | |||
430 | my $last = $t_end || $t; | |||
431 | if(! $pre_t1 || $last > $pre_t1) { | |||
432 | $pre_t1 = $last; | |||
433 | $pre_ydt1 = $ydt_end || $ydt; | |||
434 | $pre_rec1 = $recnum; | |||
435 | $pre_name1 = $ev->{name}; | |||
436 | } | |||
437 | if($ev->{scan_id} && $ev->{name} =~ /^SCAN/) { | |||
438 | # Note that a particular scan ID has already been | |||
439 | # seen, so we can enforce uniqueness and properly | |||
440 | # assign subsequent scan IDs correctly by tracking | |||
441 | # the last scan letter used. | |||
442 | $used_scan_ids{$ev->{scan_id}} = $ev->{ydt}; | |||
443 | ($scan_letter) = $ev->{scan_id} =~ /([a-z])$/; | |||
444 | ++$scan_letter; | |||
445 | } | |||
446 | if($ev->{name} =~ /^[SN]EP/) { | |||
447 | # Pole crossing; reset scan letter until overridden by a scan | |||
448 | $scan_letter = 'a'; | |||
449 | } | |||
450 | if(defined $ev->{orbit}) { | |||
451 | # Track the orbit so when we start processing the new file | |||
452 | # we can pick up where we left off. | |||
453 | $orbit = $ev->{orbit}; | |||
454 | } | |||
455 | if($ev->{name} =~ /^(.*)_BNDRY$/ && $ev->{type} == 1) { | |||
456 | # If this is a start boundary event, add an entry in %open | |||
457 | my $name = $1; | |||
458 | $open{$name} = {ydt=>$ev->{start_ydt}, recnum=>$recnum}; | |||
459 | } | |||
460 | if($open{$ev->{name}} && $ev->{type} == 1) { | |||
461 | warn "$warn: Unmatched $ev->{name} event at ". | |||
462 | "$open{$ev->{name}}{ydt} superceded by ". | |||
463 | "closed event at $ev->{ydt}.\n" | |||
464 | if $ev->{name} !~ /nodata/i; | |||
465 | $open{$ev->{name}} = undef; | |||
466 | } | |||
467 | push @tbl,$ev; | |||
468 | ++$recnum; | |||
469 | ++$i; | |||
470 | $t_last = $t if ! $t_last || $t != $t_last; | |||
471 | } | |||
472 | } | |||
473 | ||||
474 | die "$err: Current file completely contained within extant ". | |||
475 | "event time range:\n". | |||
476 | "$err: Prev range=$this->{hdr}{start_ydt} to $this->{hdr}{end_ydt}\n". | |||
477 | "$err: Curr end =$pre_ydt1\n". | |||
478 | "$err: File =$this->{file}\n" | |||
479 | if @pretbl && $file_t1 <= $pre_t1; | |||
480 | ||||
481 | if($t_switch && @tbl) { | |||
482 | # We have a switch time, so now we have to go through the pre-table | |||
483 | # and look for bracketed events that start before the switch time but | |||
484 | # end after and re-open them | |||
485 | my $recnum = 0; | |||
486 | for my $ev (@tbl) { | |||
487 | my ($ydt0,$ydt1) = ($ev->{start_ydt},$ev->{end_ydt}); | |||
488 | my ($t0,$t1) = (WISE::Time::Str_time($ydt0,{z=>1}), | |||
489 | WISE::Time::Str_time($ydt1,{z=>1})) | |||
490 | if $ydt0 && $ydt1; | |||
491 | if($ev->{type} == 1 && $ydt0 && $ydt1 && | |||
492 | $t0 < $t_switch && $t1 >= $t_switch) { | |||
493 | my $name = $ev->{name}; | |||
494 | if(! $open{$name} || $ydt0 > $open{$name}{ydt}) { | |||
495 | print "Re-opening event $name that ran $ydt0 to $ydt1.\n" if $verbose; | |||
496 | warn "$warn: Re-open orphans previous open event at $open{$name}{ydt}.\n" | |||
497 | if $open{$name}; | |||
498 | $ev->{name} .= '_BNDRY'; | |||
499 | $ev->{end_ydt} = undef; | |||
500 | $ev->{duration} = undef; | |||
501 | $ev->{end_et} = undef; | |||
502 | $open{$name} = {ydt=>$ydt0, recnum=>$recnum}; | |||
503 | } | |||
504 | } | |||
505 | ++$recnum; | |||
506 | } | |||
507 | } | |||
508 | ||||
509 | EVENT: while(my $info = $this->next_key_event($opts)) { | |||
510 | ||||
511 | my $tev = WISE::Time::Str_time($info->{ydt},{z=>1}); | |||
512 | ||||
513 | # Skip events that are in the overlap period | |||
514 | if($t_switch && @pretbl) { | |||
515 | next if $tev <= $t_switch; | |||
516 | } | |||
517 | ||||
518 | # Set start/end times based on event type | |||
519 | if( $info->{type} == 0) { # Instantaneous event | |||
520 | $info->{start_ydt} = undef; | |||
521 | $info->{end_ydt} = undef; | |||
522 | } elsif ($info->{type} == 1) { # Start of an event pair | |||
523 | $info->{start_ydt} = $info->{ydt}; | |||
524 | $info->{end_ydt} = undef; | |||
525 | } elsif ($info->{type} == 2) { # End of an event pair | |||
526 | $info->{start_ydt} = undef; | |||
527 | $info->{end_ydt} = $info->{ydt}; | |||
528 | } elsif ($info->{type} == 3) { # Start and end of an event | |||
529 | $info->{start_ydt} = $info->{ydt}; | |||
530 | $info->{end_ydt} = $info->{data}{end_ydt}; | |||
531 | } elsif ($info->{type} == 4) { # Paired event; two times given | |||
532 | $info->{start_ydt} = undef; # Times deduced below | |||
533 | $info->{end_ydt} = undef; | |||
534 | } elsif ($info->{type} == 5) { # Start and duration of an event given | |||
535 | $info->{start_ydt} = $info->{ydt}; | |||
536 | my $dt = $info->{data}{duration}; | |||
537 | if($dt =~ /^(\d+):(\d+):(\d+)$/) { | |||
538 | my($h,$m,$s) = ($1,$2,$3); | |||
539 | $dt = $h*3600+$m*60+$s; | |||
540 | } | |||
541 | $info->{end_ydt} = WISE::Time::Time_str($tev+$dt,{form=>4}); | |||
542 | } | |||
543 | ||||
544 | # Event-specific special handling, especially scan start/end pairing | |||
545 | if($info->{name} =~ /^[SN]EP/) { | |||
546 | # Pole crossing | |||
547 | my $orbnum = $info->{data}{orbit_num}; | |||
548 | # Deal with any possible strange numeric precision issues | |||
549 | $orbit = sprintf("%.1f",$orbnum+0.01); | |||
550 | # Initialize the scan-letter by half-orbit | |||
551 | $scan_letter = 'a'; | |||
552 | } elsif($info->{name} eq 'SCAN_BNDRY') { | |||
553 | # Scan start or stop | |||
554 | if($info->{data}{turn_state} =~ /^SETTLE|COMPLETE$/) { | |||
555 | # Start of a scan ('STOP' refers to the end of a turn) | |||
556 | $info->{start_ydt} = $info->{ydt}; | |||
557 | # Compute scan ID | |||
558 | my $scanid; | |||
559 | if(defined $orbit) { | |||
560 | $scanid = sprintf("%05d",int(2*$orbit+.01)); | |||
561 | } else { # Fallback | |||
562 | warn "$warn: Orbit number not yet set at scan start at ". | |||
563 | "$info->{ydt}.\n"; | |||
564 | $scanid = sprintf("%05d",$fakeorbit++); | |||
565 | $scan_letter = 'p'; | |||
566 | } | |||
567 | $info->{scan_id} = $scanid = $scanid.$scan_letter; | |||
568 | warn "$warn: Scan ID $scanid already seen at time ". | |||
569 | "$used_scan_ids{$scanid} and again at $info->{ydt}.\n" | |||
570 | if $used_scan_ids{$scanid}; # Belt and suspenders | |||
571 | warn "$warn: Scan $scanid starting at $info->{ydt} employs ". | |||
572 | "a scan letter beyond the pale.\n" | |||
573 | if $scan_letter !~ /[$good_scan_letters]/; | |||
574 | $used_scan_ids{$scanid} = $info->{ydt}; | |||
575 | ++$scan_letter; # Alpha increment | |||
576 | if($open{SCAN}) { | |||
577 | warn "$warn: Unterminated scan at $open{SCAN}{ydt}; ". | |||
578 | "replaced at $info->{ydt}.\n"; | |||
579 | # This scan will be lost | |||
580 | } | |||
581 | # Indicate we have an open scan. | |||
582 | $open{SCAN} = {ydt=>$info->{start_ydt}, recnum=>$recnum}; | |||
583 | # Post-facto set this as the start of a bracketting pair | |||
584 | $info->{type} = 1; | |||
585 | } else { | |||
586 | # End of a scan | |||
587 | # Look for an open scan and fill in that event's stop time | |||
588 | $info->{end_ydt} = $info->{ydt}; | |||
589 | if($open{SCAN}) { | |||
590 | my $row = $tbl[$open{SCAN}{recnum}]; | |||
591 | my $t1 = WISE::Time::Str_time($open{SCAN}{ydt},{z=>1}); | |||
592 | my $t2 = WISE::Time::Str_time($info->{ydt}, {z=>1}); | |||
593 | my $scandur = $t2-$t1; | |||
594 | if($scan_max_dur > 0 && $scandur > $scan_max_dur) { | |||
595 | warn "$warn: Unterminated scan at $open{SCAN}{ydt}; ". | |||
596 | "too long ($scandur secs), removed at $info->{ydt}.\n"; | |||
597 | # This scan will be lost | |||
598 | } else { | |||
599 | $row->{end_ydt} = $info->{ydt}; | |||
600 | $row->{name} = 'SCAN'; # Rename for clarity and distinction | |||
601 | } | |||
602 | $open{SCAN} = undef; # Close scan | |||
603 | # Do not add to the table | |||
604 | next EVENT; | |||
605 | } else { | |||
606 | # !!! We won't always want this warning, at least | |||
607 | # not without some additional logic, since most | |||
608 | # deliveries will have an unterminated scan at the | |||
609 | # beginning and end | |||
610 | # E.g. we don't want this warning at all if the target | |||
611 | # of the turn is pt. stdby | |||
612 | if($info->{data}{to} !~ /pt_stdby/i) { | |||
613 | warn "$warn: Uninitialized scan at $info->{ydt}.\n"; | |||
614 | # Post-facto set this as the end of a bracketting pair | |||
615 | $info->{type} = 2; | |||
616 | } | |||
617 | } | |||
618 | } | |||
619 | } elsif($info->{name} eq 'NODATA_BNDRY') { | |||
620 | if($info->{data}{data_state} eq 'DISABLE') { | |||
621 | $open{NODATA} = {ydt=>$info->{start_ydt}, recnum=>$recnum}; | |||
622 | $info->{start_ydt} = $info->{ydt}; | |||
623 | $info->{type} = 1; | |||
624 | } else { | |||
625 | $info->{end_ydt} = $info->{ydt}; | |||
626 | if($open{NODATA}) { | |||
627 | my $row = $tbl[$open{NODATA}{recnum}]; | |||
628 | $row->{end_ydt} = $info->{ydt}; | |||
629 | $row->{name} = 'NODATA'; | |||
630 | $open{NODATA} = undef; | |||
631 | next EVENT; | |||
632 | } else { | |||
633 | $info->{type} = 2; | |||
634 | } | |||
635 | } | |||
636 | } elsif($info->{name} eq 'TDRS_BNDRY') { | |||
637 | if($info->{data}{turn_state} eq 'COMPLETE') { | |||
638 | $open{TDRS} = {ydt=>$info->{start_ydt}, recnum=>$recnum}; | |||
639 | $info->{start_ydt} = $info->{ydt}; | |||
640 | $info->{type} = 1; | |||
641 | } else { | |||
642 | $info->{end_ydt} = $info->{ydt}; | |||
643 | if($open{TDRS}) { | |||
644 | my $row = $tbl[$open{TDRS}{recnum}]; | |||
645 | $row->{end_ydt} = $info->{ydt}; | |||
646 | $row->{name} = 'TDRS'; | |||
647 | $open{TDRS} = undef; | |||
648 | next EVENT; | |||
649 | } else { | |||
650 | $info->{type} = 2; | |||
651 | } | |||
652 | } | |||
653 | } elsif($info->{name} eq 'SBAND_BNDRY') { | |||
654 | if($info->{data}{onoff} eq '1') { | |||
655 | $open{SBAND} = {ydt=>$info->{start_ydt}, recnum=>$recnum}; | |||
656 | $info->{start_ydt} = $info->{ydt}; | |||
657 | $info->{type} = 1; | |||
658 | } else { | |||
659 | $info->{end_ydt} = $info->{ydt}; | |||
660 | if($open{SBAND}) { | |||
661 | my $row = $tbl[$open{SBAND}{recnum}]; | |||
662 | $row->{end_ydt} = $info->{ydt}; | |||
663 | $row->{name} = 'SBAND'; | |||
664 | $open{SBAND} = undef; | |||
665 | next EVENT; | |||
666 | } else { | |||
667 | $info->{type} = 2; | |||
668 | } | |||
669 | } | |||
670 | } elsif($info->{name} =~ /^(ASCE|DESC)_BNDRY$/) { | |||
671 | my $aord = $1; | |||
672 | if($info->{data}{start}) { | |||
673 | $open{$aord} = {ydt=>$info->{start_ydt}, recnum=>$recnum}; | |||
674 | $info->{start_ydt} = $info->{ydt}; | |||
675 | my $scanid = sprintf("%05d",int(2*$orbit+.01)); | |||
676 | $info->{scan_id} = $scanid.'x'; | |||
677 | $info->{type} = 1; | |||
678 | } else { | |||
679 | $info->{end_ydt} = $info->{ydt}; | |||
680 | if($open{$aord}) { | |||
681 | my $row = $tbl[$open{$aord}{recnum}]; | |||
682 | $row->{end_ydt} = $info->{ydt}; | |||
683 | $row->{name} = $aord; | |||
684 | $open{$aord} = undef; | |||
685 | next EVENT; | |||
686 | } else { | |||
687 | $info->{type} = 2; | |||
688 | } | |||
689 | } | |||
690 | } elsif($info->{name} eq 'ANODE' && defined $orbit) { | |||
691 | # Ascending node crossing | |||
692 | my $orbnum = $info->{data}{orbit_num}; | |||
693 | # Deal with any possible strange numeric precision issues | |||
694 | $orbnum = sprintf("%.1f",$orbnum+0.01); | |||
695 | warn "$warn: Pole/node crossing orbit nums out of sync ". | |||
696 | "at $info->{ydt}; pole orbit=$orbit, node orbit=$orbnum.\n" | |||
697 | if $orbnum != $orbit; | |||
698 | } | |||
699 | ||||
700 | # Add other known info to this event | |||
701 | $info->{orbit} = $orbit; | |||
702 | ||||
703 | # Add to table | |||
704 | push @tbl, $info; | |||
705 | ++$recnum; | |||
706 | ||||
707 | } # EVENT | |||
708 | ||||
709 | if($open{SCAN}) { | |||
710 | warn "$warn: Unterminated scan at $open{SCAN}{ydt}.\n"; | |||
711 | # This scan will probably be found in the next delivery | |||
712 | } | |||
713 | ||||
714 | # Drop unwanted events | |||
715 | if(%keep || %not) { | |||
716 | @tbl = (grep { (%keep && $keep{lc $_->{name}}) || | |||
717 | (%not && ! $not{ lc $_->{name}}) } | |||
718 | @tbl); | |||
719 | } | |||
720 | ||||
721 | # Add offset to all orbit numbers | |||
722 | if($opts->{orbitoff}) { | |||
723 | offset_orbit(\@tbl,$opts->{orbitoff}); | |||
724 | } | |||
725 | ||||
726 | if($tls && $tsc) { | |||
727 | # Convert to ephem. time | |||
728 | ||||
729 | if(! $naif) { | |||
730 | $naif = WISE::Ingest::NAIF->new({ | |||
731 | tls => $tls, | |||
732 | tsc => $tsc, | |||
733 | }); | |||
734 | } | |||
735 | ||||
736 | for my $info (@tbl) { | |||
737 | $info->{et} = $naif->utc2et($info->{ydt}); | |||
738 | $info->{vtc} = $naif->sce2c_secs($info->{et}); | |||
739 | $info->{start_et} = $naif->utc2et($info->{start_ydt}) | |||
740 | if $info->{start_ydt}; | |||
741 | $info->{end_et} = $naif->utc2et($info->{end_ydt}) | |||
742 | if $info->{end_ydt}; | |||
743 | $info->{duration} = sprintf("%.3f", | |||
744 | $info->{end_et}-$info->{start_et}) | |||
745 | if $info->{start_ydt} && $info->{end_ydt}; | |||
746 | } | |||
747 | } | |||
748 | ||||
749 | # Track elapsed time since certain events occured | |||
750 | track_events(\@tbl); | |||
751 | ||||
752 | $this->{event_tbl} = \@tbl; | |||
753 | ||||
754 | return wantarray ? @tbl : \@tbl; | |||
755 | } | |||
756 | ||||
757 | sub next_key_event { | |||
758 | my $this = shift; | |||
759 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
760 | ||||
761 | my ($rc,$virt,$info); | |||
762 | ||||
763 | my $prev = $this->{key_event}; # The previous event, if any | |||
764 | ||||
765 | if($prev) { | |||
766 | # Make a fake (virtual) bracketing events out of various | |||
767 | # geomteric events which have already been read. | |||
768 | $rc = -1; | |||
769 | $virt = Clone::clone($prev); # Copy | |||
770 | if($virt->{name} eq 'NEP') { | |||
771 | # Start a descending scan | |||
772 | $virt->{name} = 'DESC_BNDRY'; | |||
773 | $virt->{id} = 101; | |||
774 | $virt->{type} = 4; | |||
775 | $virt->{data} = { start => 1 }; | |||
776 | $info = $virt; | |||
777 | } elsif($virt->{name} eq 'DESC_BNDRY' && $virt->{data}{start}) { | |||
778 | # End an ascending scan | |||
779 | $virt->{name} = 'ASCE_BNDRY'; | |||
780 | $virt->{id} = 102; | |||
781 | $virt->{type} = 4; | |||
782 | $virt->{data} = { end => 1 }; | |||
783 | $info = $virt; | |||
784 | } elsif($virt->{name} eq 'SEP') { | |||
785 | # Start an ascending scan | |||
786 | $virt->{type} = 4; | |||
787 | $virt->{id} = 102; | |||
788 | $virt->{name} = 'ASCE_BNDRY'; | |||
789 | $virt->{data} = { start => 1 }; | |||
790 | $info = $virt; | |||
791 | } elsif($virt->{name} eq 'ASCE_BNDRY' && $virt->{data}{start}) { | |||
792 | # End a descending scan | |||
793 | $virt->{type} = 4; | |||
794 | $virt->{id} = 101; | |||
795 | $virt->{name} = 'DESC_BNDRY'; | |||
796 | $virt->{data} = { end => 1 }; | |||
797 | $info = $virt; | |||
798 | } | |||
799 | } | |||
800 | # No virtual event assigned, so look for a real one | |||
801 | if(! $info) { | |||
802 | # Search PEF for next key event | |||
803 | while($rc = $this->next_event($opts)) { | |||
804 | last if $info = $this->recognize_event(); | |||
805 | } | |||
806 | } | |||
807 | return $rc if ! $rc; | |||
808 | $this->{key_event} = $info; | |||
809 | return $info; | |||
810 | } | |||
811 | ||||
812 | sub next_event { | |||
813 | my $this = shift; | |||
814 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
815 | ||||
816 | $this->{prev} = { %{ $this->{next} } }; # Copy | |||
817 | my $next = -1; | |||
818 | # Retrieve a new, real event, skipping unwanted records | |||
819 | while($next && ! ref $next && $next < 0) { | |||
820 | $next = _get_next_rec($this,${$this->{fh}},$opts) | |||
821 | } | |||
822 | $this->{next} = $next if $next; | |||
823 | $this->{eof} = 1 if defined $next && $next == 0; | |||
824 | $this->{err} = 1 if ! defined $next; | |||
825 | $this->{last} = 1 if ! $next; | |||
826 | return $next; | |||
827 | } | |||
828 | ||||
829 | sub recognize_event { | |||
830 | my $this = shift; | |||
831 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
832 | my ($event_name, $event_id, $yd, $type, $spec, %data); | |||
833 | return 0 if $this->{next}{rec} !~ m/$quick_re/i; | |||
834 | my $ev = $this->{next}; | |||
835 | # We may have matched something. Find out what. | |||
836 | ($spec) = (grep {$ev->{$_->{ev_field}} =~ m/$_->{ev_re}/} | |||
837 | @event_specs); | |||
838 | return 0 if ! $spec; # Nope, false alarm | |||
839 | # Found one. Extract info | |||
840 | if($spec->{data_re}) { | |||
841 | # Get other data from the field, if any | |||
842 | @data{@{$spec->{data_names}}} = | |||
843 | $ev->{$spec->{data_field}} =~ m/$spec->{data_re}/; | |||
844 | } | |||
845 | my %info = (name=>$spec->{name}, id=>$spec->{id}, type=>$spec->{type}, | |||
846 | ydt=>$ev->{ydt}, file=>$this->{base}, data=>\%data); | |||
847 | return wantarray ? %info : \%info; | |||
848 | } | |||
849 | ||||
850 | # spent 1.01s (503ms+511ms) within WISE::Ingest::Seq::PEF::find_bracketing_events which was called 15825 times, avg 64µs/call:
# 15825 times (503ms+511ms) by main::get_event_info at line 438 of /wise/base/deliv/dev/bin/wdate, avg 64µs/call | |||
851 | 205725 | 0.29377 | 1.4e-6 | my $this = shift; |
852 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; # spent 91.0ms making 15825 calls to WISE::Ingest::Seq::_isopt, avg 6µs/call | |||
853 | my $et = shift; | |||
854 | my $binsz= $opts->{binsz} || 1000; | |||
855 | my $tbl = $opts->{event_tbl} || $this->{event_tbl}; | |||
856 | my $ix = $opts->{event_ix} || $this->{event_ix}; | |||
857 | $ix ||= $this->index_bracketing_events({event_tbl=>$tbl,binsz=>$binsz}); # spent 420ms making 1 call to WISE::Ingest::Seq::PEF::index_bracketing_events | |||
858 | my $bin = int($et / $binsz); | |||
859 | my $range = $ix->{$bin}; | |||
860 | return [] if ! $range || ! @$range; | |||
861 | my @subset; | |||
862 | for my $try (@$range) { | |||
863 | 116303 | 0.20686 | 1.8e-6 | if($et >= $try->{start_et} && $et <= $try->{end_et}) { |
864 | push @subset, $try; | |||
865 | } | |||
866 | } | |||
867 | return \@subset; | |||
868 | } | |||
869 | ||||
870 | # spent 420ms (420+24µs) within WISE::Ingest::Seq::PEF::index_bracketing_events which was called
# once (420ms+24µs) by WISE::Ingest::Seq::PEF::find_bracketing_events at line 857 | |||
871 | 8 | 2.5e-5 | 3.1e-6 | my $this = shift; |
872 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; # spent 24µs making 1 call to WISE::Ingest::Seq::_isopt | |||
873 | my $tbl = $opts->{event_tbl} || $this->{event_tbl}; | |||
874 | my $binsz= $opts->{binsz} || 1000; | |||
875 | my $ix; | |||
876 | for my $row (@$tbl) { | |||
877 | 113099 | 0.21653 | 1.9e-6 | next if ! $row->{start_et} || ! $row->{end_et}; |
878 | my $bin0 = int($row->{start_et}/$binsz); | |||
879 | my $bin1 = int($row->{end_et} /$binsz) + 1; | |||
880 | for my $bin ($bin0..$bin1) { | |||
881 | 86374 | 0.20374 | 2.4e-6 | push @{$ix->{$bin}}, $row; |
882 | } | |||
883 | } | |||
884 | $this->{event_ix} = $ix; | |||
885 | return $ix; | |||
886 | } | |||
887 | ||||
888 | sub dump_event_ipactbl { | |||
889 | my $this = shift; | |||
890 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
891 | my $file = shift || '-'; | |||
892 | require WISE::IPACTbl; | |||
893 | my $ev = $opts->{tbl} || $this->{event_tbl}; | |||
894 | my $tbl = WISE::IPACTbl->new($file,'w', | |||
895 | { | |||
896 | meta => _event_ipactbl_meta($this), | |||
897 | data => $ev, | |||
898 | fast => 1, | |||
899 | }) | |||
900 | or die "$err: Unable to init IPAC table file '$file'.\n"; | |||
901 | $tbl->data($ev) | |||
902 | or die "$err: Unable to write IPAC table file '$file'.\n"; | |||
903 | return 1; | |||
904 | } | |||
905 | ||||
906 | # spent 1.82s (182ms+1.63) within WISE::Ingest::Seq::PEF::load_event_ipactbl which was called
# once (182ms+1.63s) by WISE::Ingest::Seq::PEF::new at line 308 | |||
907 | 10 | 0.18166 | 0.01817 | my $this = shift; |
908 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; # spent 12µs making 1 call to WISE::Ingest::Seq::_isopt | |||
909 | my $file = shift || $opts->{file}; | |||
910 | require WISE::IPACTbl; | |||
911 | my $tbl = WISE::IPACTbl->new($file,{fast=>1}) # spent 577ms making 1 call to WISE::IPACTbl::new | |||
912 | or die "$err: Unable to init events from IPAC table file '$file'.\n"; | |||
913 | my $rows = $tbl->data({hashrow=>1}) # spent 869ms making 1 call to WISE::IPACTbl::data | |||
914 | or die "$err: Unable to read IPAC event table file '$file'.\n"; | |||
915 | $this->{event_tbl} = $rows; | |||
916 | # Add offset to all orbit numbers | |||
917 | if($opts->{orbitoff}) { | |||
918 | offset_orbit($rows,$opts->{orbitoff}); | |||
919 | } | |||
920 | # Track elapsed time since certain events occured | |||
921 | track_events($rows); # spent 188ms making 1 call to WISE::Ingest::Seq::PEF::track_events | |||
922 | return $rows; | |||
923 | } | |||
924 | ||||
925 | # spent 42µs within WISE::Ingest::Seq::PEF::event_tbl which was called
# once (42µs+0) by main::load_events at line 342 of /wise/base/deliv/dev/bin/wdate | |||
926 | 3 | 9.0e-6 | 3.0e-6 | my $this = shift; |
927 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
928 | return $this->{event_tbl}; | |||
929 | } | |||
930 | ||||
931 | sub offset_orbit { | |||
932 | my $rows = shift; | |||
933 | my $off = shift; | |||
934 | return if ! $rows || ! @$rows || ! $off; | |||
935 | warn "$warn: Applying offset of $off to orbit numbers.\n"; | |||
936 | for my $info (@$rows) { | |||
937 | if(defined $info->{orbit}) { | |||
938 | $info->{orbit} += $off; | |||
939 | if($info->{scan_id}) { | |||
940 | $info->{scan_id} = sprintf("%05d%1s", | |||
941 | $info->{orbit}*2, | |||
942 | substr($info->{scan_id},-1,1)); | |||
943 | } | |||
944 | } | |||
945 | } | |||
946 | return 1; | |||
947 | } | |||
948 | ||||
949 | # spent 188ms within WISE::Ingest::Seq::PEF::track_events which was called
# once (188ms+0) by WISE::Ingest::Seq::PEF::load_event_ipactbl at line 921 | |||
950 | 3 | 2.2e-5 | 7.3e-6 | my $tbl = shift; |
951 | ||||
952 | 4 | 1.8e-5 | 4.5e-6 | if(%track) { # Are we tracking anything? |
953 | my %lasttrack; # Saved events we want to track | |||
954 | my %lastwant; # Saved events that want to track something | |||
955 | # Compose hash to find what events want to know about tracked events | |||
956 | my %wants = map { ($_ => 1) } map { (keys %$_) } values %track; | |||
957 | for my $info (@$tbl) { # Step through full event table | |||
958 | 119850 | 0.13358 | 1.1e-6 | my $name = $info->{name}; |
959 | 560 | 0.00080 | 1.4e-6 | if($track{$name}) { |
960 | # Have we already seen an event that's tracking this one? | |||
961 | for my $want (keys %lastwant) { # Who wants something | |||
962 | 840 | 0.00263 | 3.1e-6 | if($track{$name}{$want}) { # Yup, we want this event |
963 | my $last = $lastwant{$want}; | |||
964 | if($last->{start_et} && $last->{end_et} && | |||
965 | $info->{et} >= $last->{start_et} && | |||
966 | $info->{et} <= $last->{end_et} | |||
967 | ) { | |||
968 | push @{$last->{tracked}{$name}}, | |||
969 | {ev => $info, | |||
970 | et => $info->{et}, | |||
971 | dt => $last->{et} - $info->{et} | |||
972 | }; | |||
973 | #print "--- 1: Added $name at $info->{ydt} to ". | |||
974 | # "$last->{name} at $last->{ydt}; ", | |||
975 | # "Now ".@{$last->{tracked}{$name}}." deep. ". | |||
976 | # "Dt=",$last->{et} - $info->{et},"\n"; | |||
977 | } | |||
978 | } | |||
979 | } | |||
980 | $lasttrack{$name} = $info; # Save last event info for events we're tracking | |||
981 | } | |||
982 | 9546 | 0.01243 | 1.3e-6 | if($wants{$name}) { |
983 | # Event $name wants to track something. Look and see if we've seen one | |||
984 | for my $tracked (keys %track) { # Step through events to be tracked | |||
985 | 13809 | 0.03820 | 2.8e-6 | next if ! $track{$tracked}{$name}; # Doesn't want this ($name) event |
986 | next if ! $lasttrack{$tracked}; # Haven't seen one of these yet | |||
987 | # We've seen an event that $name wants to track | |||
988 | push @{$info->{tracked}{$tracked}}, | |||
989 | {ev => $info, | |||
990 | et => $lasttrack{$tracked}{et}, | |||
991 | dt => $info->{et} - $lasttrack{$tracked}{et} | |||
992 | }; | |||
993 | #print "--- 2: Added $tracked at $lasttrack{$tracked}{ydt} ". | |||
994 | # "to $name at $info->{ydt}; ", | |||
995 | # "Now ".@{$info->{tracked}{$tracked}}." deep. ". | |||
996 | # "Dt=",$info->{et} - $lasttrack{$tracked}{et},"\n"; | |||
997 | } | |||
998 | $lastwant{$name} = $info; | |||
999 | } | |||
1000 | } | |||
1001 | } | |||
1002 | ||||
1003 | return 1; | |||
1004 | } | |||
1005 | ||||
1006 | sub hdr { | |||
1007 | my $this = shift; | |||
1008 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1009 | return $this->{hdr}; | |||
1010 | } | |||
1011 | ||||
1012 | sub info { | |||
1013 | my $this = shift; | |||
1014 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1015 | return $this->{next}; | |||
1016 | } | |||
1017 | ||||
1018 | sub event { | |||
1019 | my $this = shift; | |||
1020 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1021 | return $this->{next}{event}; | |||
1022 | } | |||
1023 | ||||
1024 | sub event_num { | |||
1025 | my $this = shift; | |||
1026 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1027 | return $this->{event_num}; | |||
1028 | } | |||
1029 | ||||
1030 | sub key_event { | |||
1031 | my $this = shift; | |||
1032 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1033 | ||||
1034 | return $this->{key_event}; | |||
1035 | } | |||
1036 | ||||
1037 | sub err { | |||
1038 | my $this = shift; | |||
1039 | my $opts = @_ && _isopt($_[-1]) ? pop : {}; | |||
1040 | return $this->{err}; | |||
1041 | } | |||
1042 | ||||
1043 | sub event_ipactbl_meta { | |||
1044 | my $this = shift; | |||
1045 | ||||
1046 | return _event_ipactbl_meta(); | |||
1047 | } | |||
1048 | ||||
1049 | # Parts of a sample PEF header: | |||
1050 | ||||
1051 | #SPACECRAFT_NAME = WISE; | |||
1052 | #APPLICABLE_START_TIME = 2010-010T23:54:59.000; | |||
1053 | #APPLICABLE_STOP_TIME = 2010-016T12:04:59.000; | |||
1054 | #PRODUCT_CREATION_TIME = 2009-245T21:03:10; | |||
1055 | #SEQ_ID = WIS_WSEQ_1003_1A; | |||
1056 | #*OPERATOR Toni Feldman | |||
1057 | #*SEQGEN V28.2 Thu Mar 10 11:42:07 PST 2005 | |||
1058 | #*CONTEXT Wed Aug 26 18:31:22 2009 /home/MPSSS/sol9/dev/adapt/WISE.cvf | |||
1059 | #*SC_MODEL Wed Aug 26 19:45:57 2009 /home/MPSSS/sol9/dev/adapt/WISE_CMD_DEF.smf | |||
1060 | #*SC_MODEL Fri Jul 24 18:11:33 2009 /home/MPSSS/sol9/dev/adapt/WISE_OEF.smf | |||
1061 | #*SC_MODEL Fri Jul 24 18:11:33 2009 /home/MPSSS/sol9/dev/adapt/WISE_EVENTS.smf | |||
1062 | #*CATALOG Wed Sep 2 21:02:24 2009 /home/MPSSS/sol9/dev/adapt/WISE_BLKS.satf | |||
1063 | #*CATALOG Fri Jul 24 18:11:33 2009 /home/MPSSS/sol9/dev/adapt/WISE_PROCEDURES.satf | |||
1064 | #*CLOCK Fri Jul 24 18:11:33 2009 /home/MPSSS/sol9/dev/adapt/WISE.sclk | |||
1065 | #*SEQUENCE Wed Sep 2 21:03:10 2009 /home/MPST/seq_dirs/WISE/WIS_WSEQ_1003_1A/WIS_WSEQ_1003_1A.sasf | |||
1066 | ||||
1067 | # Parse the above header | |||
1068 | sub _slurp_hdr { | |||
1069 | my $this = shift; | |||
1070 | my $fh = shift; | |||
1071 | my $hdrtxt = $_; | |||
1072 | my $line; | |||
1073 | while(defined ($line = <$fh>) && $line !~ /\$\$EOH/) { | |||
1074 | $hdrtxt .= $line; | |||
1075 | } | |||
1076 | die "$err: Unable to read header from '$this->{file}'; $!." | |||
1077 | if ! defined $line; | |||
1078 | die "$err: No header found in '$this->{file}'." | |||
1079 | if ! $hdrtxt; | |||
1080 | # Check prerequisites | |||
1081 | my @bad; | |||
1082 | for my $pat ('CONTEXT .* \.cvf', | |||
1083 | 'SC_MODEL .* DEF \.smf', | |||
1084 | 'SC_MODEL .* OEF \.smf', | |||
1085 | 'SC_MODEL .* EVENTS \.smf', | |||
1086 | 'CATALOG .* BLKS \.satf', | |||
1087 | 'CATALOG .* PROCEDURES \.satf', | |||
1088 | 'CLOCK .* \.sclk', | |||
1089 | 'SEQUENCE .* \.sasf', | |||
1090 | ) { | |||
1091 | push @bad, $pat if $hdrtxt !~ m|\n\s*\*$pat\s*\n|x; | |||
1092 | } | |||
1093 | warn "$warn: Missing file prerequisite(s) in PEF '$this->{file}'.\n", | |||
1094 | "$warn: Missing pattern='".join("'\n$warn: Missing pattern='",@bad),"'\n" | |||
1095 | if @bad; | |||
1096 | # Capture header values | |||
1097 | my %hdr; | |||
1098 | @hdr{qw/sc_name start_ydt end_ydt create_ydt seq_id operator seqgen_vsn/} = | |||
1099 | $hdrtxt =~ | |||
1100 | / | |||
1101 | ^ SPACECRAFT_NAME \s* = \s* (\S.*?) \s* ; \s* $ .* | |||
1102 | ^ APPLICABLE_START_TIME \s* = \s* (\S.*?) \s* ; \s* $ .* | |||
1103 | ^ APPLICABLE_STOP _TIME \s* = \s* (\S.*?) \s* ; \s* $ .* | |||
1104 | ^ PRODUCT_CREATION_TIME \s* = \s* (\S.*?) \s* ; \s* $ .* | |||
1105 | ^ SEQ_ID \s* = \s* (\S.*?) \s* ; \s* $ .* | |||
1106 | ^ \*OPERATOR \s+ (\S.*?) \s* $ .* | |||
1107 | ^ \*SEQGEN \s+ (\S.*?) \s* $ .* | |||
1108 | /smx; | |||
1109 | # Plenty o' date conversions | |||
1110 | $hdr{create_t} = WISE::Time::Str_time($hdr{create_ydt},{z=>1}); | |||
1111 | $hdr{start_t} = WISE::Time::Str_time($hdr{start_ydt},{z=>1}); | |||
1112 | $hdr{end_t} = WISE::Time::Str_time($hdr{end_ydt},{z=>1}); | |||
1113 | $hdr{create_gmt_full} = WISE::Time::Time_str($hdr{create_t}); | |||
1114 | $hdr{start_gmt_full} = WISE::Time::Time_str($hdr{start_t}); | |||
1115 | $hdr{end_gmt_full} = WISE::Time::Time_str($hdr{end_t}); | |||
1116 | $hdr{create_gmt_ansi} = WISE::Time::Time_str($hdr{create_t},{ansi=>1}); | |||
1117 | $hdr{start_gmt_ansi} = WISE::Time::Time_str($hdr{start_t}, {ansi=>1}); | |||
1118 | $hdr{end_gmt_ansi} = WISE::Time::Time_str($hdr{end_t}, {ansi=>1}); | |||
1119 | return \%hdr; | |||
1120 | } | |||
1121 | ||||
1122 | sub _get_next_rec { | |||
1123 | my $this = shift; | |||
1124 | my $fh = shift; | |||
1125 | my $opts = shift || {}; | |||
1126 | my $ydt0 = $opts->{event_ydt_start} || $opts->{pef_ydt_start}; | |||
1127 | my $ydt1 = $opts->{event_ydt_end} || $opts->{pef_ydt_end}; | |||
1128 | local $/ = "\n"; | |||
1129 | my $rec = $this->{readahead} || <$fh>; | |||
1130 | confess "$err: Error reading '$this->{file}' at record $.; $!.\n" | |||
1131 | if ! defined $rec; | |||
1132 | #warn("$err: Error reading '$this->{file}' at record $.; $!.\n"), | |||
1133 | #return | |||
1134 | # if ! defined $rec; | |||
1135 | return 0 if $rec =~ /^\$\$EOF/; | |||
1136 | my $ahead; | |||
1137 | while(defined ($ahead = <$fh>) && $ahead =~ /^\s/) { | |||
1138 | $rec .= $ahead; | |||
1139 | } | |||
1140 | $rec =~ s/[\s\n]+/ /g; | |||
1141 | $this->{readahead} = $ahead; | |||
1142 | my ($tcode,$ydt,$event) = $rec =~ /^(\d+:\d+)\s+(\S+)\s+(\S.*)\s*$/; | |||
1143 | warn("$err: Unexpected format at record $.;". | |||
1144 | "\n THIS='$rec'\n". | |||
1145 | "\n PREV='$this->{prev}{rec}'\n"), | |||
1146 | return | |||
1147 | if ! $tcode || ! $ydt || ! $event; | |||
1148 | return -1 | |||
1149 | if $ydt0 && $tcode lt $ydt0; | |||
1150 | return 0 | |||
1151 | if $ydt1 && $tcode gt $ydt1; | |||
1152 | my $comment = ""; | |||
1153 | $event =~ s/\s*<<\s*(.*?)\s*>>\s*// | |||
1154 | and $comment = $1; | |||
1155 | $event =~ s/^[:;]+\s*//; | |||
1156 | ++$this->{event_num}; | |||
1157 | my %info = (event_num => $this->{event_num}, rec => $rec, | |||
1158 | tcode=>$tcode, ydt=>$ydt, event=>$event, comment=>$comment, | |||
1159 | file=>$this->{base}); | |||
1160 | return wantarray ? %info : \%info; | |||
1161 | } | |||
1162 | ||||
1163 | sub _event_ipactbl_meta { | |||
1164 | my $this = shift; | |||
1165 | ||||
1166 | return { | |||
1167 | names => [qw/name ydt start_ydt end_ydt duration scan_id orbit et vtc start_et end_et type file/], | |||
1168 | types => [qw/c c c c r c r r r r r i c /], | |||
1169 | blanks=> [qw/- - null null null null null null null null null null null/], | |||
1170 | lens => [qw/10 23 23 23 12 6 11 11 11 11 11 6 32 /], | |||
1171 | }; | |||
1172 | } | |||
1173 | ||||
1174 | 1 | 2.0e-6 | 2.0e-6 | *_isopt = \&WISE::Ingest::Seq::_isopt; |
1175 | ||||
1176 | 1 | 7.2e-5 | 7.2e-5 | 1; |