Skip to content

Commit

Permalink
Merge pull request #233 from nasa/release/v1.5
Browse files Browse the repository at this point in the history
release/v1.5
  • Loading branch information
teubert committed Jun 28, 2023
2 parents 8e6e819 + dbd5cb8 commit ee25ad0
Show file tree
Hide file tree
Showing 33 changed files with 399 additions and 202 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10']
python-version: ['3.7']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -36,7 +36,7 @@ jobs:
# runs-on: ubuntu-latest
# strategy:
# matrix:
# python-version: ['3.9']
# python-version: ['3.7']
# steps:
# - uses: actions/checkout@v2
# - name: Set up Python ${{ matrix.python-version }}
Expand All @@ -55,7 +55,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.9']
python-version: ['3.10']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand All @@ -69,7 +69,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.9]
python-version: ['3.10']
steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
Expand Down
54 changes: 54 additions & 0 deletions .github/workflows/release-tests.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
name: Python package

on:
push:
branches:
- 'release/**'
pull_request:
branches:
- 'release/**'
paths:
- prog_algs

jobs:
test-prog_models-dev:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['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 prog_models
run: |
python -m pip install git+https://github.com/nasa/prog_models.git@dev
- 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.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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,5 @@ cython_debug/
.DS_Store
data_test.pkl
predictor_test.pkl

.VSCodeCounter/
13 changes: 6 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ See documentation [here](https://nasa.github.io/progpy/prog_algs_guide.html)
## Repository Directory Structure

`src/prog_algs/` - The prognostics algorithm python package<br />
`docs/` - Project documentation (see also [github.io](https://nasa.github.io/prog_algs/))<br />
`examples/` - Example Python scripts using prog_algs<br />
`tests/` - Tests for prog_models<br />
`README.md` - The readme (this file)<br />
Expand All @@ -26,23 +25,23 @@ See documentation [here](https://nasa.github.io/progpy/prog_algs_guide.html)
Use the following to cite this repository:

```
@misc{2022_nasa_prog_algs,
@misc{2023_nasa_prog_algs,
author = {Christopher Teubert and Matteo Corbetta and Chetan Kulkarni},
title = {Prognostics Algorithm Python Package},
month = Dec,
year = 2022,
version = {1.4.3},
month = May,
year = 2023,
version = {1.5},
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.4.3, Dec 2022. URL https://github.com/nasa/prog_algs.
C. Teubert, M. Corbetta, C. Kulkarni, Prognostics Algorithm Python Package, v1.5, May 2023. 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, December 2022. URL https://nasa.github.io/progpy.
C. Teubert, C. Kulkarni, M. Corbetta, K. Jarvis, M. Daigle, ProgPy Prognostics Python Packages, v1.5, May 2023. 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 Down
File renamed without changes.
12 changes: 6 additions & 6 deletions predictor_template.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ class TemplatePredictor(Predictor):
"""

# REPLACE THE FOLLOWING LIST WITH CONFIGURED PARAMETERS
default_parameters = { # Default Parameters, used as config for UKF
default_parameters = { # Default Parameters, used as config for UKF
'Example Parameter': 0.0
}

Expand Down Expand Up @@ -76,10 +76,10 @@ def predict(self, state, future_loading_eqn, **kwargs):
# time_of_event.final_state = {'event1': ScalarData({'state1': 10, 'state2': 20}), 'event2': ScalarData({'state1': 12, 'state2': 18})}

return PredictionResults(
times,
inputs,
states,
outputs,
event_states,
times,
inputs,
states,
outputs,
event_states,
time_of_event
)
4 changes: 0 additions & 4 deletions requirements.txt

This file was deleted.

3 changes: 0 additions & 3 deletions setup.cfg

This file was deleted.

6 changes: 3 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

setup(
name = 'prog_algs',
version = '1.4.3',
version = '1.5.0.pre',
description = "The NASA Prognostics Algorithm Package is a framework for model-based prognostics (computation of remaining useful life) of engineering systems. It includes algorithms for state estimation and prediction, including uncertainty propagation. The algorithms use prognostic models (see prog_models) to perform estimation and prediction. The package enables rapid development of prognostics solutions for given models of components and systems. Algorithms can be swapped for comparative studies and evaluations",
long_description=long_description,
long_description_content_type='text/markdown',
Expand All @@ -36,13 +36,13 @@
keywords = ['prognostics', 'diagnostics', 'fault detection', 'fdir', 'prognostics and health management', 'PHM', 'health management', 'ivhm'],
package_dir = {"":"src"},
packages = find_packages(where = 'src'),
python_requires='>=3.7, <3.11',
python_requires='>=3.7, <3.12',
install_requires = [
'numpy',
'scipy',
'filterpy',
'matplotlib',
'prog_models>=1.4.0'
'prog_models>=1.5.0.pre'
],
license = 'NOSA',
project_urls={ # Optional
Expand Down
2 changes: 1 addition & 1 deletion src/prog_algs/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

import warnings

__version__ = '1.4.3'
__version__ = '1.5.0.pre'

def run_prog_playback(obs, pred, future_loading, output_measurements, **kwargs):
warnings.warn("Depreciated in 1.2.0, will be removed in a future release.", DeprecationWarning)
Expand Down
19 changes: 0 additions & 19 deletions src/prog_algs/exceptions.py

This file was deleted.

4 changes: 2 additions & 2 deletions src/prog_algs/metrics/samples.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from .toe_metrics import prob_success
from .toe_profile_metrics import alpha_lambda

def mean_square_error(values : list, ground_truth : float) -> float:
def mean_square_error(values: list, ground_truth: float) -> float:
"""Mean Square Error
Args:
values (List[float]): Times of Event (ToE) for a single event, output from predictor
Expand All @@ -28,7 +28,7 @@ def root_mean_square_error(values, ground_truth):
"""
return sqrt(sum([(mean(x) - ground_truth)**2 for x in values])/len(values))

def percentage_in_bounds(toe : list, bounds : tuple) -> float:
def percentage_in_bounds(toe: list, bounds: tuple) -> float:
"""Calculate percentage of ToE dist is within specified bounds
Args:
Expand Down
2 changes: 1 addition & 1 deletion src/prog_algs/metrics/toe_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from ..uncertain_data import UncertainData, UnweightedSamples

def prob_success(toe : UncertainData, time : float, **kwargs) -> float:
def prob_success(toe: UncertainData, time: float, **kwargs) -> float:
"""Calculate probability of success - i.e., probability that event will not occur within a given time (i.e., success)
Args:
Expand Down
12 changes: 6 additions & 6 deletions src/prog_algs/metrics/toe_profile_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from ..predictors import ToEPredictionProfile

def alpha_lambda(toe_profile : ToEPredictionProfile, ground_truth : dict, lambda_value : float, alpha : float, beta : float, **kwargs) -> dict:
def alpha_lambda(toe_profile: ToEPredictionProfile, ground_truth: dict, lambda_value: float, alpha: float, beta: float, **kwargs) -> dict:
"""
Compute alpha lambda metric, a common metric in prognostics. Alpha-Lambda is met if alpha % of the Time to Event (TtE) distribution is within beta % of the ground truth at prediction time lambda.
Expand Down Expand Up @@ -45,7 +45,7 @@ def alpha_lambda(toe_profile : ToEPredictionProfile, ground_truth : dict, lambda
print('\tBounds: [{} - {}]({}%)'.format(bounds[key][0], bounds[key][1], pib[key]))
return result

def prognostic_horizon(toe_profile : ToEPredictionProfile, criteria_eqn : Callable, ground_truth : dict, **kwargs) -> dict:
def prognostic_horizon(toe_profile: ToEPredictionProfile, criteria_eqn: Callable, ground_truth: dict, **kwargs) -> dict:
"""
Compute prognostic horizon metric, defined as the difference between a time ti, when the predictions meet specified performance criteria, and the time corresponding to the true Time of Event (ToE), for each event.
PH = ToE - ti
Expand All @@ -69,7 +69,7 @@ def prognostic_horizon(toe_profile : ToEPredictionProfile, criteria_eqn : Callab
}
params.update(kwargs)

ph_result = {k:None for k in ground_truth.keys()} # False means not yet met; will be either a numerical value or None if met
ph_result = {k:None for k in ground_truth.keys()} # False means not yet met; will be either a numerical value or None if met
for (t_prediction, toe) in toe_profile.items():
# Convert to TtE for toe and ground_truth
tte = toe - t_prediction
Expand All @@ -81,14 +81,14 @@ def prognostic_horizon(toe_profile : ToEPredictionProfile, criteria_eqn : Callab
if v and (ph_result[k] == None):
ph_calc = ground_truth[k] - t_prediction
if ph_calc > 0:
ph_result[k] = ph_calc # PH = EOL - ti # ground truth is a dictionary {'EOD': 3005.2} should be ph_result[k] = g_truth[key] - t_prediction
ph_result[k] = ph_calc # PH = EOL - ti # ground truth is a dictionary {'EOD': 3005.2} should be ph_result[k] = g_truth[key] - t_prediction
if (all(v != None for v in ph_result.values())):
# Return PH once all criteria are met
return ph_result
# Return PH when criteria not met for at least one event key
return ph_result

def cumulative_relative_accuracy(toe_profile : ToEPredictionProfile, ground_truth : dict, **kwargs) -> Dict[str, float]:
def cumulative_relative_accuracy(toe_profile: ToEPredictionProfile, ground_truth: dict, **kwargs) -> Dict[str, float]:
"""
Compute cumulative relative accuracy for a given profile, defined as the normalized sum of relative prediction accuracies at specific time instances.
Expand All @@ -108,7 +108,7 @@ def cumulative_relative_accuracy(toe_profile : ToEPredictionProfile, ground_trut
ra_sums[event] += value
return {event:ra_sum/len(toe_profile) for event, ra_sum in ra_sums.items()}

def monotonicity(toe_profile : ToEPredictionProfile, **kwargs) -> Dict[str, float]:
def monotonicity(toe_profile: ToEPredictionProfile, **kwargs) -> Dict[str, float]:
"""Calculate monotonicty for a prediction profile.
Given a prediction profile, for each prediction: go through all predicted events and compare those to the next one.
Calculates monotonicity for each prediction key using its associated mean value in UncertainData.
Expand Down
2 changes: 1 addition & 1 deletion src/prog_algs/metrics/uncertain_data_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

from ..uncertain_data import UncertainData, UnweightedSamples

def calc_metrics(data : UncertainData, ground_truth : Union[float, dict] = None, **kwargs) -> dict:
def calc_metrics(data: UncertainData, ground_truth: Union[float, dict] = None, **kwargs) -> dict:
"""Calculate all time of event metrics
Args:
Expand Down
2 changes: 1 addition & 1 deletion src/prog_algs/predictors/monte_carlo.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ class MonteCarlo(Predictor):
'n_samples': 100 # Default number of samples to use, if none specified
}

def predict(self, state : UncertainData, future_loading_eqn : Callable, **kwargs) -> PredictionResults:
def predict(self, state: UncertainData, future_loading_eqn: Callable, **kwargs) -> PredictionResults:
if isinstance(state, dict) or isinstance(state, self.model.StateContainer):
from prog_algs.uncertain_data import ScalarData
state = ScalarData(state, _type = self.model.StateContainer)
Expand Down
12 changes: 6 additions & 6 deletions src/prog_algs/predictors/prediction.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def __init__(self, times : list, data : list):
self.times = times
self.data = data

def __eq__(self, other : "Prediction") -> bool:
def __eq__(self, other: "Prediction") -> bool:
"""Compare 2 Predictions
Args:
Expand All @@ -36,7 +36,7 @@ def __eq__(self, other : "Prediction") -> bool:
"""
return self.times == other.times and self.data == other.data

def snapshot(self, time_index : int) -> UncertainData:
def snapshot(self, time_index: int) -> UncertainData:
"""Get all samples from a specific timestep
Args:
Expand All @@ -63,7 +63,7 @@ def mean(self) -> List[dict]:
"""
return [dist.mean for dist in self.data]

def time(self, index : int):
def time(self, index: int):
warn("Deprecated. Please use prediction.times[index] instead.")
return self.times[index]

Expand Down Expand Up @@ -110,7 +110,7 @@ class UnweightedSamplesPrediction(Prediction, UserList):
Data points where data[n] is a SimResult for sample n
"""

def __init__(self, times : list, data : list):
def __init__(self, times: list, data: list):
super(UnweightedSamplesPrediction, self).__init__(times, data)
self.__transformed = False # If transform has been calculated

Expand All @@ -133,11 +133,11 @@ def mean(self) -> list:
self.__calculate_tranform()
return [dist.mean for dist in self.__transform]

def sample(self, sample_id : int):
def sample(self, sample_id: int):
warn("Deprecated. Please use prediction[sample_id] instead.")
return self[sample_id]

def snapshot(self, time_index : int) -> UnweightedSamples:
def snapshot(self, time_index: int) -> UnweightedSamples:
"""Get all samples from a specific timestep
Args:
Expand Down

0 comments on commit ee25ad0

Please sign in to comment.