Skip to content

Commit ded3bfe

Browse files
authored
Fixed time handling issues and missing map street names. (#431)
# Fixes - Fixed `FileIndex` loading if time hint is specified but start/stop not specified - Fixed `DataLoader` handling of messages containing both P1 and system timestamps - Fixed dtype on `MeasurementDetails` GPS and system time numpy arrays - Fixed missing street names on `p1_display` map
2 parents ca474cd + 08cfff5 commit ded3bfe

5 files changed

Lines changed: 33 additions & 20 deletions

File tree

python/fusion_engine_client/analysis/analyzer.py

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -92,29 +92,30 @@ def _build_map_style(mapbox_token: Optional[str]):
9292
"""!
9393
@brief Build a `layout.map.style` value for a MapLibre-based Scattermap figure.
9494
95-
If a Mapbox access token is available, pull Mapbox satellite tiles via a custom raster style spec (the mechanism
96-
MapLibre-based maps use in place of the old `layout.mapbox.accesstoken` field, which no longer exists). Otherwise,
97-
fall back to Plotly's built-in token-free `satellite-streets` style, which serves ESRI World Imagery aerial tiles
98-
(max zoom 16, lower resolution than Mapbox) with OpenMapTiles street labels drawn on top.
95+
If a Mapbox access token is available, pull Mapbox's rendered `satellite-streets-v12` tiles (imagery with street
96+
labels composited on top) via a custom raster style spec, the mechanism MapLibre-based maps use in place of the
97+
old `layout.mapbox.accesstoken` field, which no longer exists. Otherwise, fall back to Plotly's built-in
98+
token-free `satellite-streets` style, which serves ESRI World Imagery aerial tiles (max zoom 16, lower resolution
99+
than Mapbox) with OpenMapTiles street labels drawn on top.
99100
"""
100101
if not mapbox_token:
101102
return 'satellite-streets'
102103

103104
return {
104105
'version': 8,
105106
'sources': {
106-
'mapbox-satellite': {
107+
'mapbox-satellite-streets': {
107108
'type': 'raster',
108109
'tiles': [
109-
f'https://api.mapbox.com/v4/mapbox.satellite/{{z}}/{{x}}/{{y}}@2x.jpg90'
110+
f'https://api.mapbox.com/styles/v1/mapbox/satellite-streets-v12/tiles/256/{{z}}/{{x}}/{{y}}@2x'
110111
f'?access_token={mapbox_token}'
111112
],
112113
'tileSize': 256,
113114
'attribution': '© Mapbox',
114115
},
115116
},
116117
'layers': [
117-
{'id': 'mapbox-satellite-layer', 'type': 'raster', 'source': 'mapbox-satellite'},
118+
{'id': 'mapbox-satellite-streets-layer', 'type': 'raster', 'source': 'mapbox-satellite-streets'},
118119
],
119120
}
120121

python/fusion_engine_client/analysis/data_loader.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -441,8 +441,12 @@ def _read(self,
441441
# fast reading, messages with system times may have their index entry timestamps set to NAN since A) they can
442442
# occur in a log before P1 time is established, and B) there's not necessarily a direct way to convert between
443443
# system and P1 time.
444-
p1_time_messages_requested = any([t in messages_with_p1_time for t in needed_message_types])
445-
system_time_messages_requested = any([t in messages_with_system_time for t in needed_message_types])
444+
requested_messages_with_p1_time = any([t in messages_with_p1_time for t in needed_message_types])
445+
requested_messages_with_system_time = any([t in messages_with_system_time for t in needed_message_types])
446+
all_system_time_messages_have_p1_time = all([t in messages_with_p1_time
447+
for t in needed_message_types if t in messages_with_system_time])
448+
requested_messages_with_only_system_time = (requested_messages_with_system_time
449+
and not all_system_time_messages_have_p1_time)
446450

447451
# Create a dict with references to the requested types only to be returned below. If any data was already
448452
# cached, it will be present in self.data and populated here.
@@ -471,8 +475,8 @@ def _read(self,
471475

472476
# If we need to establish t0 (either P1 time or system time), we will wait to apply the user's filter criteria.
473477
# We can get t0 from any message type.
474-
need_t0 = self._need_t0 and p1_time_messages_requested
475-
need_system_t0 = self._need_system_t0 and system_time_messages_requested
478+
need_t0 = self._need_t0 and requested_messages_with_p1_time
479+
need_system_t0 = self._need_system_t0 and requested_messages_with_system_time
476480

477481
reader_max_messages_applied = False
478482
if need_t0 or need_system_t0:
@@ -486,7 +490,7 @@ def _read(self,
486490
self.reader.filter_in_place(None, source_ids=source_ids)
487491

488492
# If the user is requiring (valid) P1 timestamps, filter to those now.
489-
if require_p1_time and not system_time_messages_requested:
493+
if require_p1_time and not requested_messages_with_only_system_time:
490494
self.reader.filter_out_invalid_p1_times()
491495

492496
# If the user requested max messages, tell the reader to return max N results. The reader only supports this
@@ -497,7 +501,7 @@ def _read(self,
497501
# not system time. The read_next() call below will apply this condition and only return messages with valid
498502
# system time.
499503
if (max_messages is not None and self.reader.have_index() and
500-
not (require_system_time and system_time_messages_requested)):
504+
not (require_system_time and requested_messages_with_system_time)):
501505
reader_max_messages_applied = True
502506
if max_messages >= 0:
503507
self.reader.filter_in_place(slice(None, max_messages))

python/fusion_engine_client/messages/measurement_details.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -133,13 +133,13 @@ def to_numpy(cls, messages):
133133

134134
idx = time_source == SystemTimeSource.GPS_TIME
135135
if np.any(idx):
136-
gps_time = np.full_like(time_source, np.nan)
136+
gps_time = np.full(time_source.shape, np.nan)
137137
gps_time[idx] = measurement_time[idx]
138138
result['gps_time'] = gps_time
139139

140140
idx = time_source == SystemTimeSource.TIMESTAMPED_ON_RECEPTION
141141
if np.any(idx):
142-
system_time = np.full_like(time_source, np.nan)
142+
system_time = np.full(time_source.shape, np.nan)
143143
system_time[idx] = measurement_time[idx]
144144
result['system_time'] = system_time
145145

python/fusion_engine_client/parsers/file_index.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,11 @@ def get_time_range(self, start: Union[Timestamp, float] = None, stop: Union[Time
376376
if len(self._data) == 0:
377377
return FileIndex(data=np.copy(self._data), t0=self.t0)
378378
# No time bounds specified. Return the complete dataset.
379-
elif start is None and stop is None:
379+
elif start is None and stop is None and hint is None:
380380
return FileIndex(data=np.copy(self._data), t0=self.t0)
381381
# If there's no P1 timestamps in the index file whatsoever, t0 will be None. In that case, we cannot apply time
382382
# bounds to the data, since they are based on P1 time. This should be extremely rare.
383-
elif self.t0 is None:
383+
elif (start is not None or stop is not None) and self.t0 is None:
384384
raise IndexError(f'No P1 timestamps present in index. Cannot apply time bounds. '
385385
f'[start={start}, stop={stop}]')
386386
else:

python/tests/test_file_index.py

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,9 +353,17 @@ def _lower_bound(time):
353353

354354
# If the log does not contain P1 time, slicing it by time is not supported.
355355
with pytest.raises(IndexError):
356-
sliced_index = index[1.0:]
357-
sliced_index = index[TimeRange(start=2.0, absolute=True)]
358-
sliced_index = index[TimeRange(start=2.0, absolute=False)]
356+
index[1.0:]
357+
with pytest.raises(IndexError):
358+
index.get_time_range(start=1.0)
359+
with pytest.raises(IndexError):
360+
index[TimeRange(start=2.0, absolute=True)]
361+
with pytest.raises(IndexError):
362+
index[TimeRange(start=2.0, absolute=False)]
363+
364+
# However, if you don't set start or stop, setting hint should still work.
365+
sliced_index = index.get_time_range(hint='include_nans')
366+
assert (sliced_index.message_index == [e[3] for e in raw_data]).all()
359367

360368

361369
def test_empty_index():

0 commit comments

Comments
 (0)