Skip to content

Commit

Permalink
Merge pull request #147 from nasa/feature/t_keys_to_events
Browse files Browse the repository at this point in the history
Rename `threshold_keys`
  • Loading branch information
teubert committed Jul 15, 2024
2 parents d2b1e00 + a717175 commit 380efd2
Show file tree
Hide file tree
Showing 25 changed files with 148 additions and 132 deletions.
36 changes: 18 additions & 18 deletions examples/01_Simulation.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@
"source": [
"By default, `simulate_to_threshold` simulates until the first event occurs. In this case, that's `falling` (i.e., when the object begins falling). For this model `falling` will always occur before `impact`, but for many models you won't have such a strict ordering of events. \n",
"\n",
"For users interested in when a specific event is reached, you can indicate which event(s) you'd like to simulate to using the `threshold_keys` argument. For example,"
"For users interested in when a specific event is reached, you can indicate which event(s) you'd like to simulate to using the `events` argument. For example,"
]
},
{
Expand All @@ -246,7 +246,7 @@
"metadata": {},
"outputs": [],
"source": [
"results = m.simulate_to_threshold(save_freq=0.5, threshold_keys='impact')\n",
"results = m.simulate_to_threshold(save_freq=0.5, events='impact')\n",
"fig = results.outputs.plot(ylabel='Position (m)')\n",
"fig = results.event_states.plot()"
]
Expand All @@ -255,7 +255,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"Now the model simulated past the `falling` event untill the `impact` event occured. `threshold_keys` accepts a single event, or a list of events, so for models with many events you can specify a list of events where any will stop simulation."
"Now the model simulated past the `falling` event until the `impact` event occurred. `events` accepts a single event, or a list of events, so for models with many events you can specify a list of events where any will stop simulation."
]
},
{
Expand All @@ -273,7 +273,7 @@
"metadata": {},
"outputs": [],
"source": [
"results = m.simulate_to_threshold(save_freq=0.5, threshold_keys='impact', horizon=7)\n",
"results = m.simulate_to_threshold(save_freq=0.5, events='impact', horizon=7)\n",
"fig = results.outputs.plot(ylabel='Position (m)')\n",
"fig = results.event_states.plot()"
]
Expand All @@ -291,7 +291,7 @@
"metadata": {},
"outputs": [],
"source": [
"results = m.simulate_to_threshold(save_freq=0.5, threshold_keys='impact', horizon=10)\n",
"results = m.simulate_to_threshold(save_freq=0.5, events='impact', horizon=10)\n",
"fig = results.outputs.plot(ylabel='Position (m)')\n",
"fig = results.event_states.plot()"
]
Expand All @@ -318,7 +318,7 @@
"metadata": {},
"outputs": [],
"source": [
"results = m.simulate_to_threshold(save_freq=0.5, threshold_keys='impact', print=True, progress=True)"
"results = m.simulate_to_threshold(save_freq=0.5, events='impact', print=True, progress=True)"
]
},
{
Expand Down Expand Up @@ -970,7 +970,7 @@
"outputs": [],
"source": [
"results = m.simulate_to_threshold(\n",
" threshold_keys='impact',\n",
" events='impact',\n",
" dt=2.5,\n",
" save_freq=2.5)\n",
"fig = results.outputs.plot(ylabel='Position (m)')"
Expand All @@ -992,7 +992,7 @@
"outputs": [],
"source": [
"results = m.simulate_to_threshold(\n",
" threshold_keys='impact',\n",
" events='impact',\n",
" dt=0.25,\n",
" save_freq=0.25)\n",
"fig = results.outputs.plot(ylabel='Position (m)')"
Expand All @@ -1016,7 +1016,7 @@
"outputs": [],
"source": [
"results = m.simulate_to_threshold(\n",
" threshold_keys='impact',\n",
" events='impact',\n",
" dt=0.05,\n",
" save_freq=0.05)\n",
"fig = results.outputs.plot(ylabel='Position (m)')"
Expand Down Expand Up @@ -1052,7 +1052,7 @@
"outputs": [],
"source": [
"results = m.simulate_to_threshold(\n",
" threshold_keys='impact',\n",
" events='impact',\n",
" dt=1,\n",
" save_freq=1.5)\n",
"print('Times saved: ', results.times)"
Expand All @@ -1074,7 +1074,7 @@
"outputs": [],
"source": [
"results = m.simulate_to_threshold(\n",
" threshold_keys='impact',\n",
" events='impact',\n",
" dt=('auto', 1),\n",
" save_freq=1.5)\n",
"print('Times saved: ', results.times)"
Expand Down Expand Up @@ -1118,7 +1118,7 @@
" return 0.25\n",
" return 1\n",
"\n",
"results=m.simulate_to_threshold(dt=next_time, save_freq= 0.25, threshold_keys='impact')\n",
"results=m.simulate_to_threshold(dt=next_time, save_freq= 0.25, events='impact')\n",
"\n",
"print(results.times)"
]
Expand Down Expand Up @@ -1197,15 +1197,15 @@
"metadata": {},
"outputs": [],
"source": [
"results1 = m.simulate_to_threshold(threshold_keys='impact', dt=0.1, save_freq=0.1)\n",
"results1 = m.simulate_to_threshold(events='impact', dt=0.1, save_freq=0.1)\n",
"fig = results1.outputs.plot(title='default')\n",
"\n",
"m['throwing_speed'] = 10\n",
"results2 = m.simulate_to_threshold(threshold_keys='impact', dt=0.1, save_freq=0.1)\n",
"results2 = m.simulate_to_threshold(events='impact', dt=0.1, save_freq=0.1)\n",
"fig = results2.outputs.plot(title='slow')\n",
"\n",
"m['throwing_speed'] = 80\n",
"results3 = m.simulate_to_threshold(threshold_keys='impact', dt=0.1, save_freq=0.1)\n",
"results3 = m.simulate_to_threshold(events='impact', dt=0.1, save_freq=0.1)\n",
"fig = results3.outputs.plot(title='fast')"
]
},
Expand All @@ -1223,11 +1223,11 @@
"outputs": [],
"source": [
"m_e = ThrownObject(g=-9.81) # Earth gravity\n",
"results_earth = m_e.simulate_to_threshold(threshold_keys='impact', dt=0.1, save_freq=0.1)\n",
"results_earth = m_e.simulate_to_threshold(events='impact', dt=0.1, save_freq=0.1)\n",
"fig = results_earth.outputs.plot(title='Earth')\n",
"\n",
"m_j = ThrownObject(g=-24.79) # Jupiter gravity\n",
"results_jupiter = m_j.simulate_to_threshold(threshold_keys='impact', dt=0.1, save_freq=0.1)\n",
"results_jupiter = m_j.simulate_to_threshold(events='impact', dt=0.1, save_freq=0.1)\n",
"fig = results_jupiter.outputs.plot(title='Jupiter')"
]
},
Expand Down Expand Up @@ -1293,7 +1293,7 @@
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "aee8b7b246df8f9039afb4144a1f6fd8d2ca17a180786b69acc140d282b71a49"
"hash": "1a1af0ee75eeea9e2e1ee996c87e7a2b11a0bebd85af04bb136d915cefc0abce"
}
}
},
Expand Down
18 changes: 9 additions & 9 deletions examples/04_New Models.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@
"outputs": [],
"source": [
"m = ThrownObject()\n",
"save = m.simulate_to_threshold(print=True, save_freq=1, threshold_keys='impact', dt=0.1)"
"save = m.simulate_to_threshold(print=True, save_freq=1, events='impact', dt=0.1)"
]
},
{
Expand Down Expand Up @@ -547,7 +547,7 @@
"cell_type": "markdown",
"metadata": {},
"source": [
"We'll start by simulating to impact. We'll specify the `threshold_keys` to specifically indicate we are interested in impact. For more information on simulation, see 1. Simulation. "
"We'll start by simulating to impact. We'll specify the `events` to specifically indicate we are interested in impact. For more information on simulation, see 1. Simulation. "
]
},
{
Expand All @@ -558,7 +558,7 @@
"source": [
"# Simulate to impact\n",
"event = 'impact'\n",
"simulated_results = m_st.simulate_to_threshold(threshold_keys=[event], dt=0.005, save_freq=1, print = True)\n",
"simulated_results = m_st.simulate_to_threshold(events=event, dt=0.005, save_freq=1, print = True)\n",
"\n",
"# Print result: \n",
"print('The object hit the ground in {} seconds'.format(round(simulated_results.times[-1],2)))"
Expand Down Expand Up @@ -938,7 +938,7 @@
"# Simulate to threshold \n",
"m_matrix.simulate_to_threshold(\n",
" print = True, \n",
" threshold_keys = 'impact', \n",
" events = 'impact', \n",
" dt = 0.1, \n",
" save_freq = 1)\n",
"toc_matrix = time.perf_counter()"
Expand All @@ -963,7 +963,7 @@
"tic_st = time.perf_counter()\n",
"m_st.simulate_to_threshold(\n",
" print = True, \n",
" threshold_keys = 'impact', \n",
" events = 'impact', \n",
" dt = 0.1, \n",
" save_freq = 1)\n",
"toc_st = time.perf_counter()\n",
Expand Down Expand Up @@ -1030,7 +1030,7 @@
"outputs": [],
"source": [
"event = 'impact'\n",
"simulated_results = m_limits.simulate_to_threshold(threshold_keys=[event], dt=0.005, save_freq=1)\n",
"simulated_results = m_limits.simulate_to_threshold(events=event, dt=0.005, save_freq=1)\n",
"\n",
"print('Example: No State Limits')\n",
"for i, state in enumerate(simulated_results.states):\n",
Expand Down Expand Up @@ -1086,7 +1086,7 @@
"outputs": [],
"source": [
"event = 'impact'\n",
"simulated_results = m_limits.simulate_to_threshold(threshold_keys=[event], dt=0.005, save_freq=1)\n",
"simulated_results = m_limits.simulate_to_threshold(events=event, dt=0.005, save_freq=1)\n",
"\n",
"print('Example: With State Limits')\n",
"for i, state in enumerate(simulated_results.states):\n",
Expand Down Expand Up @@ -1117,7 +1117,7 @@
"x0 = m_limits.initialize(u = {}, z = {})\n",
"x0['x'] = -1 # Initial position value set to an unrealistic value of -1\n",
"\n",
"simulated_results = m_limits.simulate_to_threshold(threshold_keys=[event], dt=0.005, save_freq=1, x = x0)\n",
"simulated_results = m_limits.simulate_to_threshold(events=event, dt=0.005, save_freq=1, x = x0)\n",
"\n",
"# Print states\n",
"print('Example 2: With -1 as initial x value')\n",
Expand Down Expand Up @@ -1373,7 +1373,7 @@
"metadata": {},
"outputs": [],
"source": [
"simulated_results = m.simulate_to_threshold(future_loading, threshold_keys=['EOD'], print = True)\n",
"simulated_results = m.simulate_to_threshold(future_loading, events='EOD', print = True)\n",
"\n",
"simulated_results.event_states.plot()\n",
"plt.show()"
Expand Down
14 changes: 7 additions & 7 deletions examples/full_lstm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ def future_loading(t, x=None):
# Step 1: Generate additional data
# We will use data generated above, but we also want data at additional timesteps
print('Generating data...')
data = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP, dt=TIMESTEP)
data_half = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP/2, dt=TIMESTEP/2)
data_quarter = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP/4, dt=TIMESTEP/4)
data_twice = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP*2, dt=TIMESTEP*2)
data_four = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP*4, dt=TIMESTEP*4)
data = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP, dt=TIMESTEP)
data_half = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP/2, dt=TIMESTEP/2)
data_quarter = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP/4, dt=TIMESTEP/4)
data_twice = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP*2, dt=TIMESTEP*2)
data_four = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP*4, dt=TIMESTEP*4)

# Step 2: Data Prep
# We need to add the timestep as a input
Expand Down Expand Up @@ -109,8 +109,8 @@ def future_loading3(t, x = None):
# Use new dt, not used in training
# Using a dt not used in training will demonstrate the model's
# ability to handle different timesteps not part of training set
data = m.simulate_to_threshold(future_loading, threshold_keys='impact', dt=TIMESTEP*3, save_freq=TIMESTEP*3)
results3 = m2.simulate_to_threshold(future_loading3, threshold_keys='impact', dt=TIMESTEP*3, save_freq=TIMESTEP*3)
data = m.simulate_to_threshold(future_loading, events='impact', dt=TIMESTEP*3, save_freq=TIMESTEP*3)
results3 = m2.simulate_to_threshold(future_loading3, events='impact', dt=TIMESTEP*3, save_freq=TIMESTEP*3)

# Step 6: Compare Results
print('Comparing results...')
Expand Down
10 changes: 5 additions & 5 deletions examples/lstm_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ def run_example():
def future_loading(t, x=None):
return m.InputContainer({}) # No input for thrown object

data = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP, dt=TIMESTEP)
data = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP, dt=TIMESTEP)

# Step 2: Generate model
# We'll use the LSTMStateTransitionModel class to generate a model
Expand Down Expand Up @@ -91,10 +91,10 @@ def future_loading2(t, x=None):
# We will use data generated above, but we also want data at additional timesteps
print('\n------------------------------------------\nExample 2...')
print('Generating additional data...')
data_half = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP/2, dt=TIMESTEP/2)
data_quarter = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP/4, dt=TIMESTEP/4)
data_twice = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP*2, dt=TIMESTEP*2)
data_four = m.simulate_to_threshold(future_loading, threshold_keys='impact', save_freq=TIMESTEP*4, dt=TIMESTEP*4)
data_half = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP/2, dt=TIMESTEP/2)
data_quarter = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP/4, dt=TIMESTEP/4)
data_twice = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP*2, dt=TIMESTEP*2)
data_four = m.simulate_to_threshold(future_loading, events='impact', save_freq=TIMESTEP*4, dt=TIMESTEP*4)

# Step 2: Data Prep
# We need to add the timestep as a input
Expand Down
10 changes: 5 additions & 5 deletions examples/new_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ def future_load(t, x=None):

# Step 3: Simulate to impact
event = 'impact'
simulated_results = m.simulate_to_threshold(future_load, threshold_keys=[event], dt=0.005, save_freq=1, print = True)
simulated_results = m.simulate_to_threshold(future_load, events=event, dt=0.005, save_freq=1, print = True)

# Print flight time
print('The object hit the ground in {} seconds'.format(round(simulated_results.times[-1],2)))
Expand All @@ -86,24 +86,24 @@ def future_load(t, x=None):

# The first way to change the configuration is to pass in your desired config into construction of the model
m = ThrownObject(g = grav_moon)
simulated_moon_results = m.simulate_to_threshold(future_load, threshold_keys=[event], dt=0.005, save_freq=1)
simulated_moon_results = m.simulate_to_threshold(future_load, events=event, dt=0.005, save_freq=1)

grav_mars = -3.711
# You can also update the parameters after it's constructed
m.parameters['g'] = grav_mars
simulated_mars_results = m.simulate_to_threshold(future_load, threshold_keys=[event], dt=0.005, save_freq=1)
simulated_mars_results = m.simulate_to_threshold(future_load, events=event, dt=0.005, save_freq=1)

grav_venus = -8.87
m.parameters['g'] = grav_venus
simulated_venus_results = m.simulate_to_threshold(future_load, threshold_keys=[event], dt=0.005, save_freq=1)
simulated_venus_results = m.simulate_to_threshold(future_load, events=event, dt=0.005, save_freq=1)

print('Time to hit the ground: ')
print('\tvenus: {}s'.format(round(simulated_venus_results.times[-1],2)))
print('\tearth: {}s'.format(round(simulated_results.times[-1],2)))
print('\tmars: {}s'.format(round(simulated_mars_results.times[-1],2)))
print('\tmoon: {}s'.format(round(simulated_moon_results.times[-1],2)))

# We can also simulate until any event is met by neglecting the threshold_keys argument
# We can also simulate until any event is met by neglecting the events argument
simulated_results = m.simulate_to_threshold(future_load, dt=0.005, save_freq=1)
threshs_met = m.threshold_met(simulated_results.states[-1])
for (key, met) in threshs_met.items():
Expand Down
2 changes: 1 addition & 1 deletion examples/noise.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def future_load(t=None, x=None):

# Define configuration for simulation
config = {
'threshold_keys': 'impact', # Simulate until the thrown object has impacted the ground
'events': 'impact', # Simulate until the thrown object has impacted the ground
'dt': 0.005, # Time step (s)
'save_freq': 0.5, # Frequency at which results are saved (s)
}
Expand Down
4 changes: 2 additions & 2 deletions examples/sensitivity.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ def run_example():
eods = np.empty(len(thrower_height_range))
for (i, thrower_height) in zip(range(len(thrower_height_range)), thrower_height_range):
m.parameters['thrower_height'] = thrower_height
simulated_results = m.simulate_to_threshold(threshold_keys=[event], dt =1e-3, save_freq =10)
simulated_results = m.simulate_to_threshold(events=event, dt =1e-3, save_freq =10)
eods[i] = simulated_results.times[-1]

# Step 4: Analysis
Expand All @@ -36,7 +36,7 @@ def run_example():
eods = np.empty(len(throw_speed_range))
for (i, throw_speed) in zip(range(len(throw_speed_range)), throw_speed_range):
m.parameters['throwing_speed'] = throw_speed
simulated_results = m.simulate_to_threshold(threshold_keys=[event], options={'dt':1e-3, 'save_freq':10})
simulated_results = m.simulate_to_threshold(events=event, options={'dt':1e-3, 'save_freq':10})
eods[i] = simulated_results.times[-1]

print('\nFor a reasonable range of throwing speeds, impact time is between {} and {}'.format(round(eods[0],3), round(eods[-1],3)))
Expand Down
2 changes: 1 addition & 1 deletion examples/sim_battery_eol.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def future_loading(t, x=None):
options = {
'save_freq': 1000, # Frequency at which results are saved
'dt': 2, # Timestep
'threshold_keys': ['InsufficientCapacity'], # Simulate to InsufficientCapacity
'events': 'InsufficientCapacity', # Simulate to InsufficientCapacity
'print': True
}
simulated_results = batt.simulate_to_threshold(future_loading, **options)
Expand Down
2 changes: 1 addition & 1 deletion examples/vectorized.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ def future_load(t, x=None):

# Step 3: Simulate to threshold
# Here we are simulating till impact using the first state defined above
(times, inputs, states, outputs, event_states) = m.simulate_to_threshold(future_load, x = first_state, threshold_keys=['impact'], print = True, dt=0.1, save_freq=2)
(times, inputs, states, outputs, event_states) = m.simulate_to_threshold(future_load, x = first_state, events='impact', print = True, dt=0.1, save_freq=2)

# Now lets do the same thing but only stop when all hit the ground
def thresholds_met_eqn(thresholds_met):
Expand Down
2 changes: 1 addition & 1 deletion src/progpy/data_models/data_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def from_model(cls, m: PrognosticsModel, load_functions: list, **kwargs) -> "Dat
# Only one function
load_functions = [load_functions]

sim_cfg_params = ['dt', 't0', 'integration_method', 'save_freq', 'save_pts', 'horizon', 'first_output', 'threshold_keys', 'x', 'thresholds_met_eqn']
sim_cfg_params = ['dt', 't0', 'integration_method', 'save_freq', 'save_pts', 'horizon', 'first_output', 'events', 'x', 'thresholds_met_eqn']

# Check format of cfg item and split into cfg for each sim if scalar
for cfg in sim_cfg_params:
Expand Down
4 changes: 2 additions & 2 deletions src/progpy/data_models/dmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -416,14 +416,14 @@ def next_state(self, x, u, _):

return x

def simulate_to_threshold(self, future_loading_eqn, first_output=None, threshold_keys=None, **kwargs):
def simulate_to_threshold(self, future_loading_eqn, first_output=None, events=None, **kwargs):
# Save keyword arguments same as DMD training for approximation
kwargs_sim = kwargs.copy()
kwargs_sim['save_freq'] = self.dt
kwargs_sim['dt'] = self.dt

# Simulate to threshold at DMD time step
results = super().simulate_to_threshold(future_loading_eqn, first_output, threshold_keys, **kwargs_sim)
results = super().simulate_to_threshold(future_loading_eqn, first_output, events, **kwargs_sim)

# Interpolate results to be at user-desired time step
if 'dt' in kwargs:
Expand Down
Loading

0 comments on commit 380efd2

Please sign in to comment.