Skip to content

Commit

Permalink
Merge pull request #212 from nasa/release/v1.4
Browse files Browse the repository at this point in the history
Release/v1.4
  • Loading branch information
teubert authored Oct 28, 2022
2 parents 1703bb1 + c964abb commit b077d65
Show file tree
Hide file tree
Showing 61 changed files with 984 additions and 764 deletions.
34 changes: 34 additions & 0 deletions .github/workflows/pr-messages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: Print PR Message - Non Release

on:
pull_request:
branches:
- 'dev'
types: [opened]

jobs:
benchmark_branch:
runs-on: ubuntu-latest
steps:
- name: Auto Comment
uses: wow-actions/auto-comment@v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pullRequestOpened: >
Thank you for opening this PR. Each PR into dev requires a code review. For the code review, look at the following:
- [ ] Reviewer should look for bugs, efficiency, readability, testing, and coverage in examples (if relevant).
- [ ] Ensure that each PR adding a new feature should include a test verifying that feature.
- [ ] All tests must be passing.
- [ ] All errors from static analysis must be resolved.
- [ ] Review the test coverage reports (if there is a change) - will be added as comment on PR if there is a change
- [ ] Review the software benchmarking results (if there is a change) - will be added as comment on PR
- [ ] Any added dependencies are included in requirements.txt, setup.py, and dev_guide.rst (this document)
- [ ] All warnings from static analysis must be reviewed and resolved - if deemed appropriate.
38 changes: 19 additions & 19 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,25 +32,25 @@ jobs:
python -m pip install testbook
- name: Run tests
run: python -m tests
test-prog_models-released:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install
run: |
python -m pip install --upgrade pip
python -m pip install -e .
python -m pip install notebook
python -m pip install testbook
- name: Run tests
run: python -m tests
# test-prog_models-released:
# runs-on: ubuntu-latest
# strategy:
# matrix:
# python-version: ['3.9']
# steps:
# - uses: actions/checkout@v2
# - name: Set up Python ${{ matrix.python-version }}
# uses: actions/setup-python@v2
# with:
# python-version: ${{ matrix.python-version }}
# - name: Install
# run: |
# python -m pip install --upgrade pip
# python -m pip install -e .
# python -m pip install notebook
# python -m pip install testbook
# - name: Run tests
# run: python -m tests
copyright:
runs-on: ubuntu-latest
strategy:
Expand Down
56 changes: 56 additions & 0 deletions .github/workflows/release-messages.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
name: Print PR Message - Release

on:
pull_request:
branches:
- 'release/**'
types: [opened]

jobs:
benchmark_branch:
runs-on: ubuntu-latest
steps:
- name: Auto Comment
uses: wow-actions/auto-comment@v1
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
pullRequestOpened: >
Thank you for opening this PR. Since this is a release branch, the PR must complete the release checklist, below:
- [ ] Check that each new feature has corresponding tests
- [ ] Confirm all dependencies are in the following: requirements.txt, setup.py, the bottom of dev_guide.rst
- [ ] Confirm that all issues associated with the release have been closed (i.e., requirements have been met) or assigned to another release
- [ ] Run unit tests `python -m tests`
- [ ] If present, run manual tests `python -m tests.test_manual`
- [ ] Review the template(s)
- [ ] Review static-analysis/linter results
- [ ] Review the tutorial
- [ ] Run and review the examples
- [ ] Check that all examples are tested
- [ ] Check new files in PR for any accidentally added
- [ ] Check documents
- [ ] Check that all desired examples are in docs
- [ ] General review: see if any updates are required
- [ ] Rebuild sphinx documents: `sphinx-build sphinx_config/ docs/`
- [ ] Write release notes
- [ ] Update version number in src/\*/__init__.py and setup.py
- [ ] For releases adding new features- ensure that NASA release process has been followed.
- [ ] Confirm that on GitHub Releases page, the next release has been started and that a schedule is present including at least Release Date, Release Review Date, and Release Branch Opening Date.`
19 changes: 8 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,12 @@ This is designed to be used with the [Prognostics Models Package](https://github
`pip3 install prog_algs`

## Documentation
See documentation [here](https://nasa.github.io/prog_algs/)
See documentation [here](https://nasa.github.io/progpy/prog_algs_guide.html)

## Repository Directory Structure

`src/prog_algs/` - The prognostics algorithm python package<br />
&nbsp;&nbsp; |- `metrics/` - Tools for analyzing the results of state estimation and prognostics
&nbsp;&nbsp; |- `predictors/` - Algorithms for performing the prediction step of model-based prognostics<br />
&nbsp;&nbsp; |- `state_estimators/` - Algorithms for performing the state estimation step of model-based prognostics<br />
&nbsp;&nbsp; |- `uncertain_data/` - Tools for storing and manipulating data with uncertainty<br />
&nbsp;&nbsp; |- `visualize/` - Tools for visualizing the results of state estimation and prognostics<br />
`docs/` - Project documentation (see also [github.io](https://nasa.github.io/prog_algs/))<br />
`sphinx_config/` - Configuration for automatic documentation generation<br />
`examples/` - Example Python scripts using prog_algs<br />
`tests/` - Tests for prog_models<br />
`README.md` - The readme (this file)<br />
Expand All @@ -35,16 +29,20 @@ Use the following to cite this repository:
@misc{2022_nasa_prog_algs,
author = {Christopher Teubert and Matteo Corbetta and Chetan Kulkarni},
title = {Prognostics Algorithm Python Package},
month = May,
month = Oct,
year = 2022,
version = {1.3.0},
version = {1.4.0},
url = {https://github.com/nasa/prog\_algs}
}
```

The corresponding reference should look like this:

C. Teubert, M. Corbetta, C. Kulkarni, Prognostics Algorithm Python Package, v1.3.0, May 2022. URL https://github.com/nasa/prog_algs.
C. Teubert, M. Corbetta, C. Kulkarni, Prognostics Algorithm Python Package, v1.4.0, Oct 2022. URL https://github.com/nasa/prog_algs.

Alternatively, if using both prog_models and prog_algs, you can cite the combined package as

C. Teubert, C. Kulkarni, M. Corbetta, K. Jarvis, M. Daigle, ProgPy Prognostics Python Packages, v1.4, October 2022. URL https://nasa.github.io/progpy.

## Acknowledgements
The structure and algorithms of this package are strongly inspired by the [MATLAB Prognostics Algorithm Library](https://github.com/nasa/PrognosticsAlgorithmLibrary) and the [MATLAB Prognostics Metrics Library](https://github.com/nasa/PrognosticsMetricsLibrary). We would like to recognize Matthew Daigle, Shankar Sankararaman and the rest of the team that contributed to the Prognostics Model Library for the contributions their work on the MATLAB library made to the design of prog_algs
Expand All @@ -53,7 +51,6 @@ The structure and algorithms of this package are strongly inspired by the [MATLA
Copyright © 2021 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved.

## Disclaimers

No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND LIABILITIES REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT "AS IS."

Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS THE UNITED STATES GOVERNMENT, ITS CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY LAW. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
2 changes: 1 addition & 1 deletion examples/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Copyright © 2021 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved.

__all__ = ['basic_example', 'benchmarking_example', 'eol_event', 'horizon', 'kalman_filter', 'utpredictor', 'new_state_estimator_example', 'measurement_eqn_example', 'playback', 'predict_specific_event', 'thrown_object_example']
__all__ = ['basic_example', 'basic_example_battery', 'benchmarking_example', 'eol_event', 'horizon', 'kalman_filter', 'new_state_estimator_example', 'measurement_eqn_example', 'playback', 'predict_specific_event']
78 changes: 36 additions & 42 deletions examples/basic_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"""
This example performs a state estimation and prediction with uncertainty given a Prognostics Model.
Method: An instance of the BatteryCircuit model in prog_models is created, and the prediction process is achieved in three steps:
Method: An instance of the ThrownObject model in prog_models is created, and the prediction process is achieved in three steps:
1) State estimation of the current state is performed using a chosen state_estimator, and samples are drawn from this estimate
2) Prediction of future states (with uncertainty) and the times at which the event threshold will be reached
3) Metrics tools are used to further investigate the results of prediction
Expand All @@ -14,72 +14,60 @@
iv) Figures illustrating results
"""

from prog_models.models import BatteryCircuit as Battery
# VVV Uncomment this to use Electro Chemistry Model VVV
from prog_models.models import BatteryElectroChemEOD as Battery

from prog_models.models import ThrownObject
from prog_algs import *

def run_example():
# Step 1: Setup model & future loading
m = ThrownObject(process_noise = 1)
def future_loading(t, x = None):
# Variable (piece-wise) future loading scheme
if (t < 600):
i = 2
elif (t < 900):
i = 1
elif (t < 1800):
i = 4
elif (t < 3000):
i = 2
else:
i = 3
return {'i': i}
# Measurement noise
R_vars = {
't': 2,
'v': 0.02
}
batt = Battery(measurement_noise = R_vars)
initial_state = batt.parameters['x0']
# No load for a thrown object
return m.InputContainer({})
initial_state = m.initialize()

# Step 2: Demonstrating state estimator
# The state estimator is used to estimate the system state given sensor data.
print("\nPerforming State Estimation Step")

# Step 2a: Setup
filt = state_estimators.ParticleFilter(batt, initial_state)
filt = state_estimators.ParticleFilter(m, initial_state)
# VVV Uncomment this to use UKF State Estimator VVV
# filt = state_estimators.UnscentedKalmanFilter(batt, initial_state)
# filt = state_estimators.UnscentedKalmanFilter(m, initial_state)

# Step 2b: Print & Plot Prior State
print("Prior State:", filt.x.mean)
print('\tSOC: ', batt.event_state(filt.x.mean)['EOD'])
print('\nevent state: ', m.event_state(filt.x.mean))
fig = filt.x.plot_scatter(label='prior')

# Step 2c: Perform state estimation step
example_measurements = {'t': 32.2, 'v': 3.915}
# Step 2c: Perform state estimation step, given some measurement, above what's expected
example_measurements = m.OutputContainer({'x': 7.5})
t = 0.1
filt.estimate(t, future_loading(t), example_measurements)
u = future_loading(t)
filt.estimate(t, u, example_measurements) # Update state, given (example) sensor data

# Step 2d: Print & Plot Resulting Posterior State
# Note the posterior state is greater than the predicted state of 5.95
# This is because of the high measurement
print("\nPosterior State:", filt.x.mean)
print('\tSOC: ', batt.event_state(filt.x.mean)['EOD'])
# Event state for 'falling' is less, because velocity has decreased
print('\nEvent State: ', m.event_state(filt.x.mean))
filt.x.plot_scatter(fig=fig, label='posterior') # Add posterior state to figure from prior state

# Note: in a prognostic application the above state estimation step would be repeated each time
# there is new data. Here we're doing one step to demonstrate how the state estimator is used

# Step 3: Demonstrating Predictor
# Step 3: Demonstrating Prediction
print("\n\nPerforming Prediction Step")

# Step 3a: Setup Predictor
mc = predictors.MonteCarlo(batt)
mc = predictors.MonteCarlo(m)

# Step 3b: Perform a prediction
NUM_SAMPLES = 5
STEP_SIZE = 0.1
mc_results = mc.predict(filt.x, future_loading, n_samples = NUM_SAMPLES, dt=STEP_SIZE)
print('ToE', mc_results.time_of_event.mean)
NUM_SAMPLES = 50
STEP_SIZE = 0.01
mc_results = mc.predict(filt.x, future_loading, n_samples = NUM_SAMPLES, dt=STEP_SIZE, save_freq=STEP_SIZE)
print('Predicted time of event (ToE): ', mc_results.time_of_event.mean)
# Here there are 2 events predicted, when the object starts falling, and when it impacts the ground.

# Step 3c: Analyze the results

Expand All @@ -92,27 +80,33 @@ def future_loading(t, x = None):
# now you have all the samples corresponding to times[1]

# You can also access the final state (of type UncertainData), like so:
# Note: to get a more accurate final state, you can decrease the step size.
final_state = mc_results.time_of_event.final_state
print('Final state @EOD: ', final_state['EOD'].mean)
print('State when object starts falling: ', final_state['falling'].mean)

# You can also use the metrics package to generate some useful metrics on the result of a prediction
print("\nEOD Prediction Metrics")

from prog_algs.metrics import prob_success
print('\tPortion between 3005.2 and 3005.6: ', mc_results.time_of_event.percentage_in_bounds([3005.2, 3005.6]))
print('\tAssuming ground truth 3002.25: ', mc_results.time_of_event.metrics(ground_truth=3005.25))
print('\tP(Success) if mission ends at 3002.25: ', prob_success(mc_results.time_of_event, 3005.25))
print('\tPortion between 3.65 and 3.8: ', mc_results.time_of_event.percentage_in_bounds([3.65, 3.8], keys='falling'))
print('\tAssuming ground truth 3.7: ', mc_results.time_of_event.metrics(ground_truth=3.7, keys='falling'))
print('\tP(Success) if mission ends at 7.6: ', prob_success(mc_results.time_of_event, 7.6, keys='impact'))

# Plot state transition
# Here we will plot the states at t0, 25% to ToE, 50% to ToE, 75% to ToE, and ToE
# You should see the states move together (i.e., velocity is lowest and highest when closest to the ground (before impact, and at beginning, respectively))
fig = mc_results.states.snapshot(0).plot_scatter(label = "t={} s".format(int(mc_results.times[0]))) # 0
quarter_index = int(len(mc_results.times)/4)
mc_results.states.snapshot(quarter_index).plot_scatter(fig = fig, label = "t={} s".format(int(mc_results.times[quarter_index]))) # 25%
mc_results.states.snapshot(quarter_index*2).plot_scatter(fig = fig, label = "t={} s".format(int(mc_results.times[quarter_index*2]))) # 50%
mc_results.states.snapshot(quarter_index*3).plot_scatter(fig = fig, label = "t={} s".format(int(mc_results.times[quarter_index*3]))) # 75%
mc_results.states.snapshot(-1).plot_scatter(fig = fig, label = "t={} s".format(int(mc_results.times[-1]))) # 100%

mc_results.time_of_event.plot_hist()
# Plot time of event for each event
# If you dont see many bins here, this is because there is not much variety in the estimate.
# You can increase the number of bins, decrease step size, or increase the number of samples to see more of a distribution
mc_results.time_of_event.plot_hist(keys='impact')
mc_results.time_of_event.plot_hist(keys='falling')

# Step 4: Show all plots
import matplotlib.pyplot as plt # For plotting
Expand Down
Loading

0 comments on commit b077d65

Please sign in to comment.