Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bokeh timeseries plots now comply with OpenMDAO's placement of recorder files. #1106

Merged
merged 23 commits into from
Aug 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
cb9dfa4
Updated bokeh timeseries reports to look for simulation and solution …
robfalck Aug 20, 2024
7e9b918
timeseries plots now handle recordings not in the outputs directory.
robfalck Aug 20, 2024
5591e01
more version checking
robfalck Aug 20, 2024
f9acd3f
more fixes
robfalck Aug 21, 2024
cf43b18
consistent version checking function added: dymos.utils.misc.om_version
robfalck Aug 21, 2024
5a9c2b1
cleanup
robfalck Aug 21, 2024
6fc466b
ignore line length in ipynb for now.
robfalck Aug 21, 2024
c1df410
add RUN_BUILD condition to workflow steps
swryan Aug 21, 2024
9afcaf9
Build docs only against dev version of OpenMDAO for now
robfalck Aug 21, 2024
845b145
cleanup
robfalck Aug 21, 2024
c5d7314
Fixed more issues with reading solution and simulation output files.
robfalck Aug 21, 2024
4cf70f1
Notebook linting
robfalck Aug 21, 2024
e115c94
more linting
robfalck Aug 21, 2024
f4e684a
Fixes for tests which reference databases. Implemented use of om_vers…
robfalck Aug 22, 2024
8e20d09
fixes for ruff failures in benchmarks
robfalck Aug 22, 2024
27effff
Failing mpl test fix
robfalck Aug 22, 2024
289b061
closer
robfalck Aug 22, 2024
a9b1c6e
cleanup logic for timeseries simulation output
robfalck Aug 22, 2024
d4c0c99
disable ruff preview for now
robfalck Aug 22, 2024
3393ac6
last few tests under latest
robfalck Aug 22, 2024
5d213a4
Last couple of failures on latest.
robfalck Aug 23, 2024
efda760
Merge remote-tracking branch 'swryan/workflow' into recorder_output_u…
robfalck Aug 23, 2024
9518fd5
pep8
robfalck Aug 23, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/dymos_docs_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ jobs:
SCIPY: '1.13'
PETSc: '3.19'
PYOPTSPARSE: 'v2.11.0'
OPENMDAO: 'latest'
OPENMDAO: 'dev'
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed to dev to avoid backwards compatibility code in the documentation.

OPTIONAL: '[docs]'
JAX: '0.4.28'
PUBLISH_DOCS: 1
Expand Down
4 changes: 3 additions & 1 deletion .github/workflows/dymos_tests_workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,15 @@ jobs:
pipdeptree

- name: 'Upload environment artifact'
if: env.RUN_BUILD
uses: actions/upload-artifact@v3
with:
name: ${{ matrix.NAME }}_environment
path: ${{ matrix.NAME }}_environment.yml
retention-days: 5

- name: Check NumPy 2.0 Compatibility
if: env.RUN_BUILD
run: |
echo "============================================================="
echo "Check Dymos code for NumPy 2.0 compatibility"
Expand All @@ -321,7 +323,7 @@ jobs:
ruff check . --select NPY201

- name: Perform linting with Ruff
if: ${{ matrix.NAME == 'baseline' }}
if: env.RUN_BUILD && matrix.NAME == 'baseline'
run: |
echo "============================================================="
echo "Lint Dymos code per settings in pyproject.toml"
Expand Down
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,11 @@ repos:
# Run the linter.
- id: ruff
types_or: [ python, pyi, jupyter ]
- repo: local
hooks:
- id: check-notebook-outputs
name: Check that notebooks have no output cells.
description: Verifies that documentation notebooks contain no output cells.
language: python
pass_filenames: false
entry: python ./docs/clean_notebooks.py --dryrun ./docs
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added to prevent accidentally commit of unclean notebooks.

4 changes: 2 additions & 2 deletions benchmark/benchmark_balanced_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,8 +262,8 @@ def benchmark_gausslobatto_timeseries_nosim_nosolveseg(self):
solvesegs=False)

def benchmark_radau_timeseries_nosim_nosolveseg(self):
_run_balanced_field_length_problem(tx=dm.Radau, timeseries=True, sim=False,
solvesegs=False)
_run_balanced_field_length_problem(tx=dm.Radau, timeseries=True, sim=False,
solvesegs=False)

def benchmark_radau_notimeseries_nosim_solveseg(self):
_run_balanced_field_length_problem(tx=dm.Radau, timeseries=False, sim=False,
Expand Down
2 changes: 1 addition & 1 deletion benchmark/benchmark_brachistochrone.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def brachistochrone_min_time(transcription='gauss-lobatto', num_segments=8, tran
p = om.Problem(model=om.Group())

p.driver = om.pyOptSparseDriver()
OPT, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True)
_, OPTIMIZER = set_pyoptsparse_opt(optimizer, fallback=True)
p.driver.options['optimizer'] = OPTIMIZER

if simul_derivs:
Expand Down
4 changes: 0 additions & 4 deletions benchmark/benchmark_racecar.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
import dymos as dm

from dymos.examples.racecar.combinedODE import CombinedODE
from dymos.examples.racecar.spline import get_spline, get_track_points
from dymos.examples.racecar.tracks import ovaltrack # track curvature imports


Expand All @@ -17,10 +16,7 @@ def _run_racecar_problem(transcription, timeseries=False, make_plots=False):

# generate nodes along the centerline for curvature calculation (different
# than collocation nodes)
points = get_track_points(track)

# fit the centerline spline.
finespline, gates, gatesd, curv, slope = get_spline(points, s=0.0)
# by default 10000 points
s_final = track.get_total_length()

Expand Down
1 change: 0 additions & 1 deletion docs/build_source_docs.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
'transcriptions.common',
'transcriptions.explicit_shooting',
'transcriptions.pseudospectral',
'transcriptions.solve_ivp',
'utils',
]

Expand Down
78 changes: 78 additions & 0 deletions docs/clean_notebooks.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
#!/usr/bin/env python

import argparse
import json
import os
import pathlib
import subprocess


EXCLUDE_DIRS = ('_build', '.ipynb_checkpoints')


class bcolors:
FILE = '\033[96m' # blue
CYAN = '\033[96m'
GREEN = '\033[92m'
WARNING = '\033[93m'
FAIL = '\033[91m'
ENDC = '\033[0m'
BOLD = '\033[1m'
UNDERLINE = '\033[4m'


def _clear_notebook_outputs(path=os.getcwd(), dry_run=True):

# Find all the notebooks
notebooks = []
if pathlib.Path(path).is_dir():
for dirpath, dirs, files in os.walk(path, topdown=True):
dirs[:] = [d for d in dirs if d not in EXCLUDE_DIRS]
notebooks.extend(pathlib.Path(dirpath).glob('*.ipynb'))
if not notebooks:
print(f'{bcolors.FAIL}No notebooks found.{bcolors.ENDC}')
return
elif path.endswith('.ipynb'):
notebooks.append(path)
else:
print(f'{bcolors.FILE}{path}{bcolors.ENDC}{bcolors.FAIL} is not a notebook file.{bcolors.ENDC}')
return

num_cleaned = 0
for file in notebooks:
with open(file) as f:
json_data = json.load(f)
for i in json_data['cells']:
if 'execution_count' in i and i['execution_count'] is not None:
break
else:
# Notebook clean, process next notebook.
continue
num_cleaned += 1
if dry_run:
print(f'Would clear outputs from {bcolors.FILE}{file}{bcolors.ENDC}. '
f'{bcolors.WARNING}(dryrun = True){bcolors.ENDC}')
else:
print(f'Clearing {bcolors.FILE}{file}{bcolors.ENDC}...', end='')
subprocess.Popen(f"jupyter nbconvert --clear-output --inplace {file}",
shell=True,
stdout=subprocess.DEVNULL,
stderr=subprocess.STDOUT).wait()
print('done')

if num_cleaned == 0:
print('No unclean notebooks found.')

return num_cleaned



if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Clear notebook outputs in place.')
parser.add_argument('path', nargs='?', default='.', help='The or directory path to clean.')
parser.add_argument('-d', '--dryrun', action='store_true',
help='Print notebooks with outputs but do not clean them.')
args = parser.parse_args()
num_cleaned = _clear_notebook_outputs(path=args.path, dry_run=args.dryrun)
if num_cleaned >0 and args.dryrun:
exit(1)
5 changes: 3 additions & 2 deletions docs/dymos_book/examples/balanced_field/balanced_field.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -720,7 +720,8 @@
},
"outputs": [],
"source": [
"sim_case = om.CaseReader('dymos_simulation.db').get_case('final')\n",
"sim_prob = traj.sim_prob\n",
"sim_case = om.CaseReader(sim_prob.get_outputs_dir() / 'dymos_simulation.db').get_case('final')\n",
"\n",
"fig, axes = plt.subplots(2, 1, sharex=True, gridspec_kw={'top': 0.92}, figsize=(12,6))\n",
"for phase in ['br_to_v1', 'rto', 'v1_to_vr', 'rotate', 'climb']:\n",
Expand Down Expand Up @@ -813,7 +814,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.11.4"
}
},
"nbformat": 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -458,13 +458,13 @@
"metadata": {},
"outputs": [],
"source": [
"sim_case = om.CaseReader('dymos_solution.db').get_case('final')\n",
"sol_case = om.CaseReader(p.get_outputs_dir() / 'dymos_solution.db').get_case('final')\n",
"\n",
"fig, axes = plt.subplots(2, 1, sharex=True, gridspec_kw={'top': 0.92}, figsize=(12, 6))\n",
"for phase in ['br_to_v1', 'rto', 'v1_to_vr', 'rotate', 'climb']:\n",
" r = sim_case.get_val(f'traj.{phase}.timeseries.r', units='ft')\n",
" v = sim_case.get_val(f'traj.{phase}.timeseries.v', units='kn')\n",
" t = sim_case.get_val(f'traj.{phase}.timeseries.time', units='s')\n",
" r = sol_case.get_val(f'traj.{phase}.timeseries.r', units='ft')\n",
" v = sol_case.get_val(f'traj.{phase}.timeseries.v', units='kn')\n",
" t = sol_case.get_val(f'traj.{phase}.timeseries.time', units='s')\n",
" axes[0].plot(t, r, '-', label=phase)\n",
" axes[1].plot(t, v, '-', label=phase)\n",
"fig.suptitle('Balanced Field Length')\n",
Expand All @@ -474,11 +474,11 @@
"axes[0].grid(True)\n",
"axes[1].grid(True)\n",
"\n",
"tv1 = sim_case.get_val('traj.br_to_v1.timeseries.time', units='s')[-1, 0]\n",
"v1 = sim_case.get_val('traj.br_to_v1.timeseries.v', units='kn')[-1, 0]\n",
"tv1 = sol_case.get_val('traj.br_to_v1.timeseries.time', units='s')[-1, 0]\n",
"v1 = sol_case.get_val('traj.br_to_v1.timeseries.v', units='kn')[-1, 0]\n",
"\n",
"tf_rto = sim_case.get_val('traj.rto.timeseries.time', units='s')[-1, 0]\n",
"rf_rto = sim_case.get_val('traj.rto.timeseries.r', units='ft')[-1, 0]\n",
"tf_rto = sol_case.get_val('traj.rto.timeseries.time', units='s')[-1, 0]\n",
"rf_rto = sol_case.get_val('traj.rto.timeseries.r', units='ft')[-1, 0]\n",
"\n",
"axes[0].annotate(f'field length = {r[-1, 0]:5.1f} ft', xy=(t[-1, 0], r[-1, 0]),\n",
" xycoords='data', xytext=(0.7, 0.5),\n",
Expand Down Expand Up @@ -551,7 +551,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.11.4"
}
},
"nbformat": 4,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,11 @@
"i = np.array(0)\n",
"legend_contents = []\n",
"\n",
"sol_case = om.CaseReader('dymos_solution.db').get_case('final')\n",
"print(p.get_outputs_dir())\n",
"import os\n",
"print(os.listdir(os.getcwd()))\n",
"\n",
"sol_case = om.CaseReader(p.get_outputs_dir() / 'dymos_solution.db').get_case('final')\n",
"\n",
"sol_x = sol_case.get_val('phase0.timeseries.x')\n",
"sol_y = sol_case.get_val('phase0.timeseries.y')\n",
Expand Down Expand Up @@ -363,13 +367,6 @@
"\n",
"HTML(html_with_custom_height)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,19 +77,19 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"active-ipynb",
"remove-input",
"remove-output"
]
},
"outputs": [],
"source": [
"%matplotlib inline"
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"active-ipynb",
"remove-input",
"remove-output"
]
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
Expand Down Expand Up @@ -193,8 +193,7 @@
"# Test the results\n",
"print(p.get_val('traj.phase0.timeseries.time')[-1])\n",
"\n",
"# Check the validity of our results by using scipy.integrate.solve_ivp to\n",
"# integrate the solution.\n",
"# Check the validity of our results.\n",
"sim_out = traj.simulate()\n",
"\n",
"# Plot the results\n",
Expand Down Expand Up @@ -273,7 +272,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.11.4"
},
"orphan": true
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"active-ipynb",
"remove-input",
"remove-output"
]
},
"outputs": [],
"source": [
"%matplotlib inline"
"cell_type": "code",
"execution_count": null,
"metadata": {
"tags": [
"active-ipynb",
"remove-input",
"remove-output"
]
},
"outputs": [],
"source": [
"%matplotlib inline"
]
},
{
"cell_type": "code",
Expand Down Expand Up @@ -195,10 +195,9 @@
"metadata": {},
"outputs": [],
"source": [
"# Check the validity of our results by using scipy.integrate.solve_ivp to\n",
"# integrate the solution.\n",
"sol = om.CaseReader('dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader('dymos_simulation.db').get_case('final')\n",
"# Check the validity of our results.\n",
"sol = om.CaseReader(p.get_outputs_dir() / 'dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader(traj.sim_prob.get_outputs_dir() / 'dymos_simulation.db').get_case('final')\n",
"\n",
"# Plot the results\n",
"fig, axes = plt.subplots(nrows=1, ncols=2, figsize=(12, 4.5))\n",
Expand Down Expand Up @@ -259,7 +258,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.0"
"version": "3.11.4"
}
},
"nbformat": 4,
Expand Down
4 changes: 2 additions & 2 deletions docs/dymos_book/examples/bryson_denham/bryson_denham.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,8 @@
},
"outputs": [],
"source": [
"sol = om.CaseReader('dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader('dymos_simulation.db').get_case('final')\n",
"sol = om.CaseReader(p.get_outputs_dir() / 'dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader(traj.sim_prob.get_outputs_dir() / 'dymos_simulation.db').get_case('final')\n",
"\n",
"t = sol.get_val('traj.phase0.timeseries.time')\n",
"x = sol.get_val('traj.phase0.timeseries.x')\n",
Expand Down
4 changes: 2 additions & 2 deletions docs/dymos_book/examples/cart_pole/cart_pole.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@
"print('objective value:', obj)\n",
"\n",
"# get optimization solution and simulation (time integration) results\n",
"sol = om.CaseReader('dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader('dymos_simulation.db').get_case('final')\n",
"sol = om.CaseReader(p.get_outputs_dir() / 'dymos_solution.db').get_case('final')\n",
"sim = om.CaseReader(traj.sim_prob.get_outputs_dir() / 'dymos_simulation.db').get_case('final')\n",
"\n",
"# plot time histories of x, x_dot, theta, theta_dot\n",
"plot_results([('traj.phase.timeseries.time', 'traj.phase.timeseries.x', 'time (s)', 'x (m)'),\n",
Expand Down
Loading
Loading