22import io
33import logging
44import json
5+ import numpy as np
6+ from scipy .interpolate import interp1d
57
68from 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
1315from rocketpy ._encoders import RocketPyEncoder
16+ from rocketpy import Function , Flight
1417from starlette .datastructures import Headers , MutableHeaders
1518from starlette .types import ASGIApp , Message , Receive , Scope , Send
1619
1720logger = 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+
2068def 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):
4593def 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+
146201class RocketPyGZipMiddleware :
147202 def __init__ (
148203 self , app : ASGIApp , minimum_size : int = 500 , compresslevel : int = 9
0 commit comments