Skip to content

Commit bafd992

Browse files
committed
FIX: small rediscretize functions to reduce json size.
1 parent a8862c4 commit bafd992

File tree

5 files changed

+80
-18
lines changed

5 files changed

+80
-18
lines changed

src/services/flight.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
from src.views.environment import EnvironmentSimulation
1414
from src.utils import collect_attributes
1515

16+
1617
class FlightService:
1718
_flight: RocketPyFlight
1819

@@ -59,7 +60,12 @@ def get_flight_simulation(self) -> FlightSimulation:
5960
"""
6061
encoded_attributes = collect_attributes(
6162
self.flight,
62-
[FlightSimulation, RocketSimulation, MotorSimulation, EnvironmentSimulation]
63+
[
64+
FlightSimulation,
65+
RocketSimulation,
66+
MotorSimulation,
67+
EnvironmentSimulation,
68+
],
6369
)
6470
flight_simulation = FlightSimulation(**encoded_attributes)
6571
return flight_simulation

src/services/rocket.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
from src.views.motor import MotorSimulation
2121
from src.utils import collect_attributes
2222

23+
2324
class RocketService:
2425
_rocket: RocketPyRocket
2526

@@ -108,8 +109,7 @@ def get_rocket_simulation(self) -> RocketSimulation:
108109
RocketSimulation
109110
"""
110111
encoded_attributes = collect_attributes(
111-
self.rocket,
112-
[RocketSimulation, MotorSimulation]
112+
self.rocket, [RocketSimulation, MotorSimulation]
113113
)
114114
rocket_simulation = RocketSimulation(**encoded_attributes)
115115
return rocket_simulation

src/utils.py

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,21 +2,69 @@
22
import io
33
import logging
44
import json
5+
import numpy as np
6+
from scipy.interpolate import interp1d
57

68
from typing import NoReturn
79

8-
from views.environment import EnvironmentSimulation
9-
from views.flight import FlightSimulation
10-
from views.motor import MotorSimulation
11-
from views.rocket import RocketSimulation
10+
from src.views.environment import EnvironmentSimulation
11+
from src.views.flight import FlightSimulation
12+
from src.views.motor import MotorSimulation
13+
from src.views.rocket import RocketSimulation
1214

1315
from rocketpy._encoders import RocketPyEncoder
16+
from rocketpy import Function, Flight
1417
from starlette.datastructures import Headers, MutableHeaders
1518
from starlette.types import ASGIApp, Message, Receive, Scope, Send
1619

1720
logger = logging.getLogger(__name__)
1821

1922

23+
class InfinityEncoder(RocketPyEncoder):
24+
def __init__(self, *args, **kwargs):
25+
super().__init__(*args, **kwargs)
26+
27+
def default(self, obj):
28+
if (
29+
isinstance(obj, Function)
30+
and not callable(obj.source)
31+
and obj.__dom_dim__ == 1
32+
):
33+
size = len(obj._domain)
34+
reduction_factor = 1
35+
if size > 25:
36+
reduction_factor = size // 25
37+
if reduction_factor > 1:
38+
obj = obj.set_discrete(
39+
obj.x_array[0],
40+
obj.x_array[-1],
41+
size // reduction_factor,
42+
mutate_self=False,
43+
)
44+
if isinstance(obj, Flight):
45+
obj._Flight__evaluate_post_process
46+
solution = np.array(obj.solution)
47+
size = len(solution)
48+
if size > 25:
49+
reduction_factor = size // 25
50+
reduced_solution = np.zeros(
51+
(size // reduction_factor, solution.shape[1])
52+
)
53+
reduced_scale = np.linspace(
54+
solution[0, 0], solution[-1, 0], size // reduction_factor
55+
)
56+
for i, col in enumerate(solution.T):
57+
reduced_solution[:, i] = interp1d(
58+
solution[:, 0], col, assume_sorted=True
59+
)(reduced_scale)
60+
obj.solution = reduced_solution.tolist()
61+
62+
obj.flight_phases = None
63+
obj.function_evaluations = None
64+
65+
return super().default(obj)
66+
67+
2068
def rocketpy_encoder(obj):
2169
"""
2270
Encode a RocketPy object using official RocketPy encoders.
@@ -33,7 +81,7 @@ def rocketpy_encoder(obj):
3381

3482
json_str = json.dumps(
3583
obj,
36-
cls=RocketPyEncoder,
84+
cls=InfinityEncoder,
3785
include_outputs=True,
3886
include_function_data=True,
3987
discretize=True,
@@ -45,7 +93,7 @@ def rocketpy_encoder(obj):
4593
def collect_attributes(obj, attribute_classes=None):
4694
"""
4795
Collect attributes from various simulation classes and populate them from the flight object.
48-
96+
4997
Args:
5098
obj: RocketPy Flight object
5199
attribute_classes: List of attribute classes to collect from
@@ -61,7 +109,8 @@ def collect_attributes(obj, attribute_classes=None):
61109
for attribute_class in attribute_classes:
62110
if issubclass(attribute_class, FlightSimulation):
63111
flight_attributes_list = [
64-
attr for attr in attribute_class.__annotations__.keys()
112+
attr
113+
for attr in attribute_class.__annotations__.keys()
65114
if attr not in ['message', 'rocket', 'env']
66115
]
67116
try:
@@ -76,10 +125,11 @@ def collect_attributes(obj, attribute_classes=None):
76125
pass
77126
except Exception:
78127
pass
79-
128+
80129
elif issubclass(attribute_class, RocketSimulation):
81130
rocket_attributes_list = [
82-
attr for attr in attribute_class.__annotations__.keys()
131+
attr
132+
for attr in attribute_class.__annotations__.keys()
83133
if attr not in ['message', 'motor']
84134
]
85135
try:
@@ -96,15 +146,18 @@ def collect_attributes(obj, attribute_classes=None):
96146
pass
97147
except Exception:
98148
pass
99-
149+
100150
elif issubclass(attribute_class, MotorSimulation):
101151
motor_attributes_list = [
102-
attr for attr in attribute_class.__annotations__.keys()
152+
attr
153+
for attr in attribute_class.__annotations__.keys()
103154
if attr not in ['message']
104155
]
105156
try:
106157
for key in motor_attributes_list:
107-
if key not in attributes.get("rocket", {}).get("motor", {}):
158+
if key not in attributes.get("rocket", {}).get(
159+
"motor", {}
160+
):
108161
try:
109162
value = getattr(obj.rocket.motor, key)
110163
if "rocket" not in attributes:
@@ -118,10 +171,11 @@ def collect_attributes(obj, attribute_classes=None):
118171
pass
119172
except Exception:
120173
pass
121-
174+
122175
elif issubclass(attribute_class, EnvironmentSimulation):
123176
environment_attributes_list = [
124-
attr for attr in attribute_class.__annotations__.keys()
177+
attr
178+
for attr in attribute_class.__annotations__.keys()
125179
if attr not in ['message']
126180
]
127181
try:
@@ -143,6 +197,7 @@ def collect_attributes(obj, attribute_classes=None):
143197

144198
return rocketpy_encoder(attributes)
145199

200+
146201
class RocketPyGZipMiddleware:
147202
def __init__(
148203
self, app: ASGIApp, minimum_size: int = 500, compresslevel: int = 9

src/views/flight.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ class FlightSimulation(ApiBaseView):
135135
frontal_surface_wind: Optional[Any] = None
136136
lateral_surface_wind: Optional[Any] = None
137137

138+
138139
class FlightView(FlightModel):
139140
flight_id: str
140141
rocket: RocketView

src/views/rocket.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from typing import Optional, Any, List, Tuple
1+
from typing import Optional, Any
22
from pydantic import ConfigDict
33
from src.models.rocket import RocketModel
44
from src.views.interface import ApiBaseView

0 commit comments

Comments
 (0)