0
# IO and Utilities
1
2
Functions for importing and exporting trajectory data in various formats, with special support for OGC Moving Features JSON, plus utility functions for system information and unit handling.
3
4
## Capabilities
5
6
### Moving Features JSON IO
7
8
Functions for working with OGC Moving Features JSON format, a standard for representing movement data.
9
10
#### Reading Moving Features JSON
11
12
```python { .api }
13
def read_mf_json(json_file_path, traj_id_property=None, traj_id=0):
14
"""
15
Read OGC Moving Features JSON files into Trajectory/TrajectoryCollection objects.
16
17
Parameters:
18
- json_file_path: Path to Moving Features JSON file
19
- traj_id_property: Property name to use as trajectory ID (optional)
20
- traj_id: Default trajectory ID if traj_id_property not specified
21
22
Returns:
23
Trajectory or TrajectoryCollection object depending on input data
24
25
Raises:
26
ValueError: If JSON format is invalid or unsupported
27
"""
28
29
def read_mf_dict(data, traj_id=0, traj_id_property=None):
30
"""
31
Read Moving Features JSON from dictionary format.
32
33
Parameters:
34
- data: Dictionary containing Moving Features JSON data
35
- traj_id: Default trajectory ID
36
- traj_id_property: Property name to use as trajectory ID (optional)
37
38
Returns:
39
Trajectory or TrajectoryCollection object
40
41
Raises:
42
ValueError: If dictionary format is invalid
43
"""
44
```
45
46
#### Writing Moving Features JSON
47
48
```python { .api }
49
def gdf_to_mf_json(gdf, traj_id_column, datetime_column, temporal_columns=None, temporal_columns_static_fields=None, interpolation=None, crs=None, trs=None, datetime_encoder=None, datetime_to_str=False):
50
"""
51
Convert GeoDataFrame to Moving Features JSON format.
52
53
Parameters:
54
- gdf: GeoDataFrame with trajectory data
55
- traj_id_column: Column name containing trajectory IDs
56
- datetime_column: Column name containing datetime values
57
- temporal_columns: List of column names with temporal data (optional)
58
- temporal_columns_static_fields: Dict mapping temporal columns to static field definitions (optional)
59
- interpolation: Interpolation method for temporal properties ("Linear", "Discrete", etc.)
60
- crs: Coordinate reference system specification (optional)
61
- trs: Temporal reference system specification (optional)
62
- datetime_encoder: Function to encode datetime objects (optional)
63
- datetime_to_str: Whether to convert datetime to string format (default: False)
64
65
Returns:
66
Dictionary in Moving Features JSON format
67
68
Raises:
69
ValueError: If required columns are missing or data format is invalid
70
"""
71
```
72
73
### System Information Utilities
74
75
Utility functions for system diagnostics and version reporting.
76
77
```python { .api }
78
def show_versions():
79
"""
80
Print system information and installed module versions.
81
82
Displays:
83
- Python version and implementation
84
- Platform information
85
- MovingPandas version
86
- Versions of key dependencies (pandas, GeoPandas, Shapely, etc.)
87
- Optional dependencies and their availability
88
89
Returns:
90
None (prints to stdout)
91
"""
92
```
93
94
### Unit Handling
95
96
Constants and utilities for working with different unit systems.
97
98
```python { .api }
99
from collections import namedtuple
100
101
UNITS = namedtuple("UNITS", "distance time time2 crs", defaults=(None, None, None, None))
102
```
103
104
#### Available Distance Units
105
106
MovingPandas supports a wide range of distance units through its integration with GeoPandas and pyproj:
107
108
- **Metric**: km, m, dm, cm, mm, nm
109
- **Imperial**: inch, ft, yd, mi
110
- **Maritime**: fathom, nautical_mile
111
- **Surveying**: link, chain, rod
112
- **Regional**: british_ft, british_yd, us_ft, us_yd
113
114
#### Available Time Units
115
116
Standard time units supported:
117
118
- **Basic**: s (seconds), min (minutes), h (hours), d (days)
119
- **Extended**: ms (milliseconds), us (microseconds), ns (nanoseconds)
120
- **Calendar**: w (weeks), M (months), Y (years)
121
122
## Usage Examples
123
124
### Reading Moving Features JSON
125
126
```python
127
import movingpandas as mpd
128
129
# Read from file
130
trajectory = mpd.read_mf_json('trajectory_data.json')
131
132
# Read with specific trajectory ID property
133
collection = mpd.read_mf_json(
134
'multi_trajectory.json',
135
traj_id_property='vehicle_id'
136
)
137
138
# Read from dictionary
139
mf_data = {
140
"type": "Feature",
141
"geometry": {
142
"type": "MovingPoint",
143
"coordinates": [[[0, 0], [1, 1], [2, 2]]],
144
"datetimes": ["2023-01-01T12:00:00Z", "2023-01-01T12:05:00Z", "2023-01-01T12:10:00Z"]
145
},
146
"properties": {"vehicle_id": "A"}
147
}
148
149
traj = mpd.read_mf_dict(mf_data, traj_id_property='vehicle_id')
150
```
151
152
### Converting to Moving Features JSON
153
154
```python
155
import geopandas as gpd
156
import pandas as pd
157
from shapely.geometry import Point
158
from datetime import datetime, timedelta
159
160
# Create sample trajectory data
161
data = []
162
base_time = datetime(2023, 1, 1, 12, 0, 0)
163
for i in range(5):
164
data.append({
165
'geometry': Point(i * 0.1, i * 0.1),
166
'timestamp': base_time + timedelta(minutes=i * 5),
167
'vehicle_id': 'A',
168
'speed': 10 + i * 2,
169
'temperature': 20 + i * 0.5
170
})
171
172
gdf = gpd.GeoDataFrame(data, crs='EPSG:4326')
173
174
# Convert to Moving Features JSON
175
mf_json = mpd.gdf_to_mf_json(
176
gdf=gdf,
177
traj_id_column='vehicle_id',
178
datetime_column='timestamp',
179
temporal_columns=['speed', 'temperature'],
180
interpolation='Linear',
181
datetime_to_str=True
182
)
183
184
# Save to file
185
import json
186
with open('output.json', 'w') as f:
187
json.dump(mf_json, f, indent=2)
188
```
189
190
### Advanced Moving Features JSON Export
191
192
```python
193
# More complex example with temporal properties
194
temporal_static_fields = {
195
'speed': {
196
'uom': 'm/s',
197
'description': 'Vehicle speed in meters per second'
198
},
199
'temperature': {
200
'uom': 'celsius',
201
'description': 'Ambient temperature'
202
}
203
}
204
205
mf_json = mpd.gdf_to_mf_json(
206
gdf=trajectory_gdf,
207
traj_id_column='trajectory_id',
208
datetime_column='time',
209
temporal_columns=['speed', 'temperature', 'elevation'],
210
temporal_columns_static_fields=temporal_static_fields,
211
interpolation='Linear',
212
crs='EPSG:4326',
213
trs='http://www.opengis.net/def/uom/ISO-8601/0/Gregorian'
214
)
215
```
216
217
### System Information
218
219
```python
220
# Display system and dependency information
221
mpd.show_versions()
222
223
# Output includes:
224
# Python: 3.9.7 | packaged by conda-forge
225
# Platform: Linux-5.4.0-90-generic-x86_64
226
# MovingPandas: 0.22.4
227
# pandas: 1.5.2
228
# geopandas: 0.12.2
229
# shapely: 2.0.0
230
# ... (additional dependencies)
231
```
232
233
### Working with Units
234
235
```python
236
from movingpandas import UNITS
237
238
# Create trajectory and specify units for length calculation
239
traj = mpd.Trajectory(gdf, traj_id='test')
240
241
# Get length in different units
242
length_meters = traj.get_length() # Default units
243
length_km = traj.get_length(units=UNITS(distance='km'))
244
length_miles = traj.get_length(units=UNITS(distance='mi'))
245
246
print(f"Length: {length_meters:.2f} m, {length_km:.2f} km, {length_miles:.2f} mi")
247
248
# Add speed with specific units
249
traj_with_speed = traj.add_speed(units=UNITS(distance='km', time='h')) # km/h
250
traj_with_speed_ms = traj.add_speed(units=UNITS(distance='m', time='s')) # m/s
251
```
252
253
### File Format Detection and Conversion
254
255
```python
256
def convert_trajectory_formats(input_path, output_format='mf_json'):
257
"""Example function to convert between trajectory formats."""
258
259
# Detect input format and read accordingly
260
if input_path.endswith('.json'):
261
# Assume Moving Features JSON
262
traj = mpd.read_mf_json(input_path)
263
elif input_path.endswith(('.gpx', '.geojson', '.shp')):
264
# Read as GeoDataFrame first
265
gdf = gpd.read_file(input_path)
266
# Convert to trajectory (assumes appropriate columns exist)
267
traj = mpd.Trajectory(gdf, traj_id='imported')
268
else:
269
raise ValueError(f"Unsupported input format: {input_path}")
270
271
# Convert to requested output format
272
if output_format == 'mf_json':
273
# Convert to Moving Features JSON
274
result = traj.to_mf_json()
275
return result
276
elif output_format == 'geojson':
277
# Convert to point GeoJSON
278
return traj.to_point_gdf().to_json()
279
elif output_format == 'linestring':
280
# Convert to LineString GeoJSON
281
return traj.to_line_gdf().to_json()
282
else:
283
raise ValueError(f"Unsupported output format: {output_format}")
284
```
285
286
## Moving Features JSON Format
287
288
The OGC Moving Features JSON format supported by MovingPandas follows this structure:
289
290
```json
291
{
292
"type": "Feature",
293
"geometry": {
294
"type": "MovingPoint",
295
"coordinates": [
296
[longitude1, latitude1],
297
[longitude2, latitude2],
298
[longitude3, latitude3]
299
],
300
"datetimes": [
301
"2023-01-01T12:00:00Z",
302
"2023-01-01T12:05:00Z",
303
"2023-01-01T12:10:00Z"
304
]
305
},
306
"properties": {
307
"trajectory_id": "A",
308
"temporalProperties": [
309
{
310
"name": "speed",
311
"values": [10.5, 12.3, 8.7],
312
"interpolation": "Linear"
313
}
314
]
315
}
316
}
317
```
318
319
### Supported Moving Features Types
320
321
- **MovingPoint**: Point geometry changing over time
322
- **MovingLineString**: LineString geometry changing over time
323
- **MovingPolygon**: Polygon geometry changing over time
324
325
### Temporal Properties
326
327
Temporal properties allow associating time-varying attributes with geometries:
328
329
- **values**: Array of property values corresponding to geometry timestamps
330
- **interpolation**: How to interpolate between values ("Linear", "Discrete", "Step")
331
- **uom**: Unit of measure for the property
332
- **description**: Human-readable description of the property
333
334
## Error Handling
335
336
Common exceptions when working with IO operations:
337
338
```python
339
try:
340
traj = mpd.read_mf_json('invalid_file.json')
341
except FileNotFoundError:
342
print("File not found")
343
except ValueError as e:
344
print(f"Invalid Moving Features JSON format: {e}")
345
except Exception as e:
346
print(f"Unexpected error: {e}")
347
348
try:
349
mf_json = mpd.gdf_to_mf_json(gdf, 'missing_column', 'timestamp')
350
except KeyError as e:
351
print(f"Required column missing: {e}")
352
except ValueError as e:
353
print(f"Data format error: {e}")
354
```