Skip to content

Commit ad65264

Browse files
authored
Merge pull request #217 from nasa/update-prognostic-example-notebook
Update prognostics example notebook
2 parents d58d398 + 6494a64 commit ad65264

File tree

1 file changed

+61
-32
lines changed

1 file changed

+61
-32
lines changed

examples/09_Prognostic Example.ipynb

Lines changed: 61 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,32 @@
44
"cell_type": "markdown",
55
"metadata": {},
66
"source": [
7-
"# Integrated Prognostics Example\n",
7+
"# 9. Integrated Prognostics Example\n",
88
"\n",
9-
"This is an integrated example of Prognostics with ProgPy. This example is based on the prognostics example from the Tutorial at the 2024 PHM Society Conference."
9+
"This section demonstrates how to build a fully integrated prognostics example with ProgPy. This is based on the prognostics example section from the __[2024 PHM Tutorial](2024PHMTutorial.ipynb)__ notebook, which was shared at the 2024 PHM Society Conference. We will go through each step from data preparation to setup to putting the example together to make predictions."
1010
]
1111
},
1212
{
1313
"cell_type": "markdown",
1414
"metadata": {},
1515
"source": [
16-
"## Data preparation\n",
17-
"First, we need to download the data we will use in this chapter. To do this we use the datasets subpackage in progpy."
16+
"## Table of Contents\n",
17+
"\n",
18+
"* [Data Preparation](#Data-Preparation)\n",
19+
"* [Setting up for Prognostics](#Setting-up-for-Prognostics)\n",
20+
" * [Set up Model](#Set-up-Model)\n",
21+
" * [Set up State Estimator](#Set-up-State-Estimator)\n",
22+
" * [Set up Predictor](#Set-up-Predictor)\n",
23+
"* [Prognostics Example](#Prognostics-Example)\n",
24+
"* [Conclusion](#Conclusion)"
25+
]
26+
},
27+
{
28+
"cell_type": "markdown",
29+
"metadata": {},
30+
"source": [
31+
"## Data Preparation\n",
32+
"First, we need to download the data. To do this, we will use the datasets subpackage in ProgPy. Note that this downloads the battery data from the [PCoE datasets](https://www.nasa.gov/intelligent-systems-division/discovery-and-systems-health/pcoe/pcoe-data-set-repository)."
1833
]
1934
},
2035
{
@@ -24,17 +39,15 @@
2439
"outputs": [],
2540
"source": [
2641
"from progpy.datasets import nasa_battery\n",
42+
"\n",
2743
"(desc, data) = nasa_battery.load_data(1)"
2844
]
2945
},
3046
{
3147
"cell_type": "markdown",
3248
"metadata": {},
3349
"source": [
34-
"Note, this downloads the battery data from the PCoE datasets:\n",
35-
"https://www.nasa.gov/intelligent-systems-division/discovery-and-systems-health/pcoe/pcoe-data-set-repository/ \n",
36-
"\n",
37-
"Let's prepare the dataset."
50+
"Let's examine the dataset."
3851
]
3952
},
4053
{
@@ -50,9 +63,9 @@
5063
"cell_type": "markdown",
5164
"metadata": {},
5265
"source": [
53-
"The dataset includes 4 different kinds of runs: trickle, step, reference, random walk. For this example we will use the trickle dataset. \n",
66+
"The dataset includes 4 different kinds of runs: trickle, step, reference, and random walk. For this example, we will use the trickle dataset. \n",
5467
"\n",
55-
"The dataset includes 4 columns: relativeTime, current, voltage, and temperature. relativeTime is the time in a specific \"run\" (i.e., with one current draw). To use the random walk dataset, we need to concatenate multiple runs. To support this, we add a new column, absoluteTime, which shows time in the dataset (instead of run)."
68+
"The dataset also includes 4 columns: `relativeTime`, `current`, `voltage`, and `temperature`. `relativeTime` is the time in a specific \"run\" (i.e., with one current draw). To use the random walk dataset, we need to concatenate multiple runs. To do this, we add a new column, `absoluteTime`, which shows time in the dataset (instead of run)."
5669
]
5770
},
5871
{
@@ -62,6 +75,7 @@
6275
"outputs": [],
6376
"source": [
6477
"data[35]['absoluteTime'] = data[35]['relativeTime']\n",
78+
"\n",
6579
"for i in range(36, 50):\n",
6680
" data[i]['absoluteTime'] = data[i]['relativeTime'] + data[i-1]['absoluteTime'].iloc[-1]"
6781
]
@@ -70,7 +84,7 @@
7084
"cell_type": "markdown",
7185
"metadata": {},
7286
"source": [
73-
"Next, we combine the data into a single dataset and investigate the results"
87+
"Next, we combine the data into a single dataset and investigate the results."
7488
]
7589
},
7690
{
@@ -80,9 +94,16 @@
8094
"outputs": [],
8195
"source": [
8296
"import pandas as pd\n",
97+
"import matplotlib.pyplot as plt\n",
98+
"\n",
8399
"random_walk_dataset = pd.concat(data[35:50], ignore_index=True)\n",
84100
"print(random_walk_dataset)\n",
85-
"random_walk_dataset.plot(y=['current', 'voltage', 'temperature'], subplots=True, xlabel='Time (sec)')"
101+
"\n",
102+
"fig = random_walk_dataset.plot(y=['current', 'voltage', 'temperature'], subplots=True, xlabel='time (sec)', title='Random Walk Trickle Data')\n",
103+
"fig[0].set_ylabel('current (A)')\n",
104+
"fig[1].set_ylabel('voltage (V)')\n",
105+
"fig[2].set_ylabel('temperature (K)')\n",
106+
"plt.show()"
86107
]
87108
},
88109
{
@@ -103,11 +124,16 @@
103124
"cell_type": "markdown",
104125
"metadata": {},
105126
"source": [
106-
"To illustrate how to do prognostics, let's use the [Battery Electrochemistry model](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html#:~:text=class%20progpy.models.BatteryElectroChemEOD(**kwargs)). This model predicts the end-of-discharge of a Lithium-ion battery based on a set of differential equations that describe the electrochemistry of the system [Daigle et al. 2013](https://papers.phmsociety.org/index.php/phmconf/article/view/2252).\n",
127+
"To illustrate how to do prognostics, we will use the [BatteryElectrochemEOD](https://nasa.github.io/progpy/api_ref/progpy/IncludedModels.html#:~:text=class%20progpy.models.BatteryElectroChemEOD(**kwargs)) model. This model predicts the end-of-discharge of a Lithium-ion battery based on a set of differential equations that describe the electrochemistry of the system in [Daigle et al. 2013](https://papers.phmsociety.org/index.php/phmconf/article/view/2252). For more information on using model, refer to the relevant section in __[03 Included Models](03_Existing%20Models.ipynb)__.\n",
107128
"\n",
108-
"First, lets setup the model.\n",
109-
"\n",
110-
"### Setup Model"
129+
"### Set up Model"
130+
]
131+
},
132+
{
133+
"cell_type": "markdown",
134+
"metadata": {},
135+
"source": [
136+
"First, let's import and initialize the model."
111137
]
112138
},
113139
{
@@ -117,14 +143,15 @@
117143
"outputs": [],
118144
"source": [
119145
"from progpy.models import BatteryElectroChemEOD\n",
146+
"\n",
120147
"batt: BatteryElectroChemEOD = BatteryElectroChemEOD()"
121148
]
122149
},
123150
{
124151
"cell_type": "markdown",
125152
"metadata": {},
126153
"source": [
127-
"We will also update the Ro and qMobile parameters to better represent the age of the battery. See 02. Parameter Estimation notebook for examples on how to estimate model parameters. "
154+
"We will also update the `Ro` and `qMobile` parameters to better represent the age of the battery. See __[02 Parameter Estimation](02_Parameter%20Estimation.ipynb)__ for examples on how to estimate model parameters. "
128155
]
129156
},
130157
{
@@ -141,10 +168,14 @@
141168
"cell_type": "markdown",
142169
"metadata": {},
143170
"source": [
144-
"The two basic components of prognostics are [state estimation and prediction](https://nasa.github.io/progpy/prog_algs_guide.html#state-estimation-and-prediction-guide). ProgPy includes functionality to do both. See 07. State Estimation and 08. Prediction for examples of this.\n",
145-
"\n",
146-
"First, let's setup our state estimator\n",
147-
"### Setup State Estimator"
171+
"### Set up State Estimator"
172+
]
173+
},
174+
{
175+
"cell_type": "markdown",
176+
"metadata": {},
177+
"source": [
178+
"The two basic components of prognostics are [state estimation and prediction](https://nasa.github.io/progpy/prog_algs_guide.html#state-estimation-and-prediction-guide). ProgPy includes functionality to do both. See __[07 State Estimation](07_State%20Estimation.ipynb)__ and __[08 Prediction](08_Prediction.ipynb)__ for examples of this. First, let's setup our state estimator."
148179
]
149180
},
150181
{
@@ -172,6 +203,7 @@
172203
"outputs": [],
173204
"source": [
174205
"initial_state = batt.initialize() # Initialize model\n",
206+
"\n",
175207
"# Define distribution around initial state\n",
176208
"x_guess = MultivariateNormalDist(\n",
177209
" labels=initial_state.keys(),\n",
@@ -200,9 +232,7 @@
200232
"cell_type": "markdown",
201233
"metadata": {},
202234
"source": [
203-
"Next, we should setup our predictor\n",
204-
"\n",
205-
"### Setup Predictor\n",
235+
"### Set up Predictor\n",
206236
"\n",
207237
"Now that we know how to do state estimation, the next key component of prognostics is [prediction](https://nasa.github.io/progpy/prog_algs_guide.html#prediction). ProgPy includes multiple predictors, and we'll implement a [Monte Carlo](https://nasa.github.io/progpy/api_ref/progpy/Predictor.html?highlight=monte%20carlo#included-predictors) predictor here. Let's load the necessary imports. "
208238
]
@@ -325,7 +355,7 @@
325355
"cell_type": "markdown",
326356
"metadata": {},
327357
"source": [
328-
"## Putting it together- Prognostics Example"
358+
"## Prognostics Example"
329359
]
330360
},
331361
{
@@ -338,7 +368,7 @@
338368
"\n",
339369
"In some cases the update frequency may be in wall clock time, or after every operational period (e.g., flight). Predictions can also be triggered (or made more frequently) by proximity to event or by the output of a diagnoser. \n",
340370
"\n",
341-
"In this case we are specifying a certain number of update steps between predictions"
371+
"In this case, we are specifying a certain number of update steps between predictions."
342372
]
343373
},
344374
{
@@ -411,9 +441,7 @@
411441
"source": [
412442
"This is an example with playback data. In a real application, the state estimator would be listening to data from a data stream and would be publishing the results to some consumer (e.g., a data bus or directly updating a dispaly)\n",
413443
"\n",
414-
"With our prognostics results, we can now calculate some metrics to analyze the accuracy.\n",
415-
"\n",
416-
"We'll start by calculating the cumulative relative accuracy given the ground truth value. "
444+
"With our prognostics results, we can now calculate some metrics to analyze the accuracy. We'll start by calculating the cumulative relative accuracy given the ground truth value. "
417445
]
418446
},
419447
{
@@ -424,14 +452,15 @@
424452
"source": [
425453
"GROUND_TRUTH= {'EOD': 1600} \n",
426454
"cra = profile.cumulative_relative_accuracy(GROUND_TRUTH)\n",
455+
"\n",
427456
"print(f\"Cumulative Relative Accuracy for 'EOD': {cra['EOD']}\")"
428457
]
429458
},
430459
{
431460
"cell_type": "markdown",
432461
"metadata": {},
433462
"source": [
434-
"We'll also generate some plots of the results, given a specific ground truth"
463+
"We'll also generate some plots of the results, given a specific ground truth."
435464
]
436465
},
437466
{
@@ -448,9 +477,9 @@
448477
"cell_type": "markdown",
449478
"metadata": {},
450479
"source": [
451-
"## Conclusions\n",
480+
"## Conclusion\n",
452481
"\n",
453-
"**TODO**"
482+
"In this notebook, we were able to demonstrate how to use ProgPy to build an integrated prognostics example with a state estimator and predictor. In the next notebook __[10 Prognostics Server](10_Prognostics%20Server.ipynb)__, we will be exploring how to use the ProgPy server."
454483
]
455484
}
456485
],

0 commit comments

Comments
 (0)