Upload 65 files
Browse files- .gitattributes +6 -0
- Dockerfile +2 -1
- README.rst +40 -8
- assets/AIM-CU-Overview.png +3 -0
- assets/AIM-CU-Overview.xml +0 -0
- assets/ui.png +3 -0
- docs/build/html/_sources/index.rst.txt +57 -10
- docs/build/html/index.html +44 -2
- docs/build/html/searchindex.js +1 -1
- docs/build/latex/aim-cu.pdf +2 -2
- docs/source/index.rst +57 -10
- figure/fig_plot_average_metric.png +3 -0
- figure/fig_plot_cusum_chart.png +3 -0
- figure/fig_plot_data_distribution.png +3 -0
- figure/fig_table_h_arl0_k.png +0 -0
- figure/fig_table_h_k_arl1.png +3 -0
- src/package/ARLTheoretical.py +1 -1
- src/package/__pycache__/ARLTheoretical.cpython-310.pyc +0 -0
- src/package/__pycache__/cusum.cpython-310.pyc +0 -0
- src/package/__pycache__/utils.cpython-310.pyc +0 -0
- src/package/app.py +11 -8
- src/package/cusum.py +97 -107
- src/package/example_AIM_CU.ipynb +0 -0
- src/package/utils.py +4 -4
- tests/test.py +7 -4
.gitattributes
CHANGED
@@ -35,3 +35,9 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
|
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
assets/AIM-CU-Overview.drawio.png filter=lfs diff=lfs merge=lfs -text
|
37 |
docs/build/latex/aim-cu.pdf filter=lfs diff=lfs merge=lfs -text
|
|
|
|
|
|
|
|
|
|
|
|
|
|
35 |
*tfevents* filter=lfs diff=lfs merge=lfs -text
|
36 |
assets/AIM-CU-Overview.drawio.png filter=lfs diff=lfs merge=lfs -text
|
37 |
docs/build/latex/aim-cu.pdf filter=lfs diff=lfs merge=lfs -text
|
38 |
+
assets/AIM-CU-Overview.png filter=lfs diff=lfs merge=lfs -text
|
39 |
+
assets/ui.png filter=lfs diff=lfs merge=lfs -text
|
40 |
+
figure/fig_plot_average_metric.png filter=lfs diff=lfs merge=lfs -text
|
41 |
+
figure/fig_plot_cusum_chart.png filter=lfs diff=lfs merge=lfs -text
|
42 |
+
figure/fig_plot_data_distribution.png filter=lfs diff=lfs merge=lfs -text
|
43 |
+
figure/fig_table_h_k_arl1.png filter=lfs diff=lfs merge=lfs -text
|
Dockerfile
CHANGED
@@ -22,6 +22,7 @@ RUN Rscript -e "install.packages('spc')"
|
|
22 |
WORKDIR /app/src/package
|
23 |
COPY . /app/
|
24 |
|
25 |
-
RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt
|
|
|
26 |
|
27 |
CMD ["python3", "app.py"]
|
|
|
22 |
WORKDIR /app/src/package
|
23 |
COPY . /app/
|
24 |
|
25 |
+
RUN pip install --use-pep517 --no-cache-dir --upgrade -r /app/requirements.txt
|
26 |
+
RUN pip install --upgrade gradio gradio_client
|
27 |
|
28 |
CMD ["python3", "app.py"]
|
README.rst
CHANGED
@@ -1,20 +1,40 @@
|
|
1 |
-
AIM-CU
|
2 |
======
|
3 |
|
4 |
-
.. image:: assets/AIM-CU-Overview.
|
5 |
:width: 800
|
6 |
:align: center
|
7 |
:alt: AIM-CU flowchart
|
8 |
|
9 |
-
Monitoring a clinically deployed AI device to detect performance drift is an essential step to
|
10 |
-
|
|
|
11 |
|
12 |
-
AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU).
|
13 |
AIM-CU computes:
|
14 |
|
15 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
16 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
17 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
18 |
Code execution
|
19 |
--------------
|
20 |
Clone AIM-CU repository.
|
@@ -36,17 +56,30 @@ Run AIM-CU.
|
|
36 |
|
37 |
.. code-block:: shell
|
38 |
|
|
|
39 |
python3 app.py
|
40 |
|
41 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
42 |
|
43 |
Example code execution
|
44 |
----------------------
|
45 |
-
Example code can be run
|
46 |
|
47 |
Demo
|
48 |
----
|
49 |
-
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
51 |
Related References
|
52 |
------------------
|
@@ -58,7 +91,6 @@ Related References
|
|
58 |
|
59 |
* Smriti Prathapan, Ravi K. Samala, Nathan Hadjiyski, Pierre‑François D’Haese, Nicholas Petrick, Jana Delfino, Fabien Maldonado, Brandon Nelson, Ghada Zamzmi, Phuong Nguyen, Yelena Yesha, and Berkman Sahiner, "Post-market Monitoring of AI-enabled Medical Devices for Radiology and Healthcare Applications" (FDA-UMiami Collaboration Poster, September 2023)
|
60 |
|
61 |
-
|
62 |
Disclaimer
|
63 |
----------
|
64 |
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
|
|
1 |
+
AIM-CU: A CUSUM-based tool for AI Monitoring
|
2 |
======
|
3 |
|
4 |
+
.. image:: assets/AIM-CU-Overview.png
|
5 |
:width: 800
|
6 |
:align: center
|
7 |
:alt: AIM-CU flowchart
|
8 |
|
9 |
+
Monitoring a clinically deployed AI device to detect performance drift is an essential step to ensure the safety and effectiveness of AI.
|
10 |
+
|
11 |
+
AIM-CU is a statistical tool for AI monitoring based on a cumulative sum (AIM-CU) approach.
|
12 |
|
|
|
13 |
AIM-CU computes:
|
14 |
|
15 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
16 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
17 |
|
18 |
+
System setup
|
19 |
+
------------
|
20 |
+
Make sure R is installed in the system. There is no specific version that this relies on. Here we have used R version 4.1.2 (2021-11-01).
|
21 |
+
Instructions for Linux (the below setup is only performed in Linux):
|
22 |
+
|
23 |
+
.. code-block:: shell
|
24 |
+
|
25 |
+
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
|
26 |
+
add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
|
27 |
+
apt-get install -y --no-install-recommends r-base r-base-dev
|
28 |
+
|
29 |
+
# setup R configs
|
30 |
+
echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile
|
31 |
+
Rscript -e "install.packages('ggplot2')"
|
32 |
+
Rscript -e "install.packages('hexbin')"
|
33 |
+
Rscript -e "install.packages('lazyeval')"
|
34 |
+
Rscript -e "install.packages('cusumcharter')"
|
35 |
+
Rscript -e "install.packages('RcppCNPy')"
|
36 |
+
Rscript -e "install.packages('spc')"
|
37 |
+
|
38 |
Code execution
|
39 |
--------------
|
40 |
Clone AIM-CU repository.
|
|
|
56 |
|
57 |
.. code-block:: shell
|
58 |
|
59 |
+
cd src/package
|
60 |
python3 app.py
|
61 |
|
62 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
63 |
|
64 |
Example code execution
|
65 |
----------------------
|
66 |
+
Example code can be run through Jupyter Notebook. Do this by entering the ``jupyter notebook`` command from the ``/src/package/`` directory. The tool is designed to be used through a GUI, not from the console.
|
67 |
|
68 |
Demo
|
69 |
----
|
70 |
+
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button. Note: this Space uses a custom Docker container; build may break due to latest package updates pulled by HuggingFace.
|
71 |
+
|
72 |
+
Usability
|
73 |
+
---------
|
74 |
+
* Example AI output CSV file is available as `config/spec-60-60.csv <config/spec-60-60.csv>`_ to be uploaded in monitoring phase.
|
75 |
+
|
76 |
+
* Workflow instruction to run the tool is available at bottom-left of UI.
|
77 |
+
|
78 |
+
* Sample UI output is available at `assets/ui.png <assets/ui.png>`_.
|
79 |
+
|
80 |
+
* Setting ``control:save_figure`` to ``true`` from `config.toml <config/config.toml>`_ will save tables and plots in `figure/ <figure/>`_.
|
81 |
+
|
82 |
+
* Running AIM-CU usually only takes a few seconds, and it does not require a GPU to run.
|
83 |
|
84 |
Related References
|
85 |
------------------
|
|
|
91 |
|
92 |
* Smriti Prathapan, Ravi K. Samala, Nathan Hadjiyski, Pierre‑François D’Haese, Nicholas Petrick, Jana Delfino, Fabien Maldonado, Brandon Nelson, Ghada Zamzmi, Phuong Nguyen, Yelena Yesha, and Berkman Sahiner, "Post-market Monitoring of AI-enabled Medical Devices for Radiology and Healthcare Applications" (FDA-UMiami Collaboration Poster, September 2023)
|
93 |
|
|
|
94 |
Disclaimer
|
95 |
----------
|
96 |
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
assets/AIM-CU-Overview.png
ADDED
![]() |
Git LFS Details
|
assets/AIM-CU-Overview.xml
ADDED
The diff for this file is too large to render.
See raw diff
|
|
assets/ui.png
ADDED
![]() |
Git LFS Details
|
docs/build/html/_sources/index.rst.txt
CHANGED
@@ -8,40 +8,83 @@ AIM-CU documentation
|
|
8 |
|
9 |
A CUSUM-based tool for AI Monitoring
|
10 |
|
11 |
-
|
|
|
|
|
|
|
|
|
12 |
|
13 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
14 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
Code execution
|
17 |
-
|
18 |
Clone AIM-CU repository.
|
19 |
|
20 |
.. code-block:: shell
|
21 |
|
22 |
-
|
23 |
|
24 |
Run the following commands to install required dependencies (Python = 3.10 is used).
|
25 |
|
26 |
.. code-block:: shell
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
Run AIM-CU.
|
34 |
|
35 |
.. code-block:: shell
|
36 |
|
37 |
-
|
|
|
38 |
|
39 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
40 |
|
|
|
|
|
|
|
|
|
41 |
Demo
|
42 |
-
|
43 |
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button.
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
.. toctree::
|
46 |
:maxdepth: 2
|
47 |
:caption: Contents:
|
@@ -49,4 +92,8 @@ AIM-CU can also be run through the demo available at https://huggingface.co/spac
|
|
49 |
ref_method
|
50 |
ref_cusum
|
51 |
ref_theoretical
|
52 |
-
ref_utils
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
A CUSUM-based tool for AI Monitoring
|
10 |
|
11 |
+
Monitoring a clinically deployed AI device to detect performance drift is an essential step to ensure the safety and effectiveness of AI.
|
12 |
+
|
13 |
+
AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU).
|
14 |
+
|
15 |
+
AIM-CU computes:
|
16 |
|
17 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
18 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
19 |
|
20 |
+
System setup
|
21 |
+
------------
|
22 |
+
Make sure R is installed in the system. Instructions for linux (the below setup is only performed in linux):
|
23 |
+
|
24 |
+
.. code-block:: shell
|
25 |
+
|
26 |
+
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
|
27 |
+
add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
|
28 |
+
apt-get install -y --no-install-recommends r-base r-base-dev
|
29 |
+
|
30 |
+
# setup R configs
|
31 |
+
echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile
|
32 |
+
Rscript -e "install.packages('ggplot2')"
|
33 |
+
Rscript -e "install.packages('hexbin')"
|
34 |
+
Rscript -e "install.packages('lazyeval')"
|
35 |
+
Rscript -e "install.packages('cusumcharter')"
|
36 |
+
Rscript -e "install.packages('RcppCNPy')"
|
37 |
+
Rscript -e "install.packages('spc')"
|
38 |
+
|
39 |
Code execution
|
40 |
+
--------------
|
41 |
Clone AIM-CU repository.
|
42 |
|
43 |
.. code-block:: shell
|
44 |
|
45 |
+
git clone https://github.com/DIDSR/AIM-CU.git
|
46 |
|
47 |
Run the following commands to install required dependencies (Python = 3.10 is used).
|
48 |
|
49 |
.. code-block:: shell
|
50 |
|
51 |
+
apt-get -y install python3
|
52 |
+
apt-get -y install pip
|
53 |
+
cd AIM-CU
|
54 |
+
pip install -r requirements.txt
|
55 |
|
56 |
Run AIM-CU.
|
57 |
|
58 |
.. code-block:: shell
|
59 |
|
60 |
+
cd src/package
|
61 |
+
python3 app.py
|
62 |
|
63 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
64 |
|
65 |
+
Example code execution
|
66 |
+
----------------------
|
67 |
+
Example code can be run in a Jupyter Notebook after opening it with ``jupyter notebook`` command from ``/src/package/`` directory. The tool is designed to used through UI, not from console.
|
68 |
+
|
69 |
Demo
|
70 |
+
----
|
71 |
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button.
|
72 |
|
73 |
+
Usability
|
74 |
+
---------
|
75 |
+
* Example AI output CSV file is available as `config/spec-60-60.csv <config/spec-60-60.csv>`_ to be uploaded in monitoring phase.
|
76 |
+
|
77 |
+
* Workflow instruction to run the tool is available at bottom-left of UI.
|
78 |
+
|
79 |
+
* Sample UI output is available at `assets/ui.png <assets/ui.png>`_.
|
80 |
+
|
81 |
+
* Setting ``control:save_figure`` to ``true`` from `config.toml <config/config.toml>`_ will save tables and plots in `figure/ <figure/>`_.
|
82 |
+
|
83 |
+
* Running AIM-CU does not take time longer than a few seconds, and it does not require GPU.
|
84 |
+
|
85 |
+
AIM-CU
|
86 |
+
------
|
87 |
+
|
88 |
.. toctree::
|
89 |
:maxdepth: 2
|
90 |
:caption: Contents:
|
|
|
92 |
ref_method
|
93 |
ref_cusum
|
94 |
ref_theoretical
|
95 |
+
ref_utils
|
96 |
+
|
97 |
+
Disclaimer
|
98 |
+
----------
|
99 |
+
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
docs/build/html/index.html
CHANGED
@@ -36,11 +36,31 @@
|
|
36 |
<section id="aim-cu-documentation">
|
37 |
<h1>AIM-CU documentation<a class="headerlink" href="#aim-cu-documentation" title="Link to this heading">¶</a></h1>
|
38 |
<p>A CUSUM-based tool for AI Monitoring</p>
|
39 |
-
<p>
|
|
|
|
|
40 |
<ul class="simple">
|
41 |
<li><p>The parameter choices for change-point detection based on an acceptable false alarm rate</p></li>
|
42 |
<li><p>Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.</p></li>
|
43 |
</ul>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
44 |
<section id="code-execution">
|
45 |
<h2>Code execution<a class="headerlink" href="#code-execution" title="Link to this heading">¶</a></h2>
|
46 |
<p>Clone AIM-CU repository.</p>
|
@@ -55,14 +75,32 @@ pip<span class="w"> </span>install<span class="w"> </span>-r<span class="w"> </s
|
|
55 |
</pre></div>
|
56 |
</div>
|
57 |
<p>Run AIM-CU.</p>
|
58 |
-
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>
|
|
|
59 |
</pre></div>
|
60 |
</div>
|
61 |
<p>Open the URL <a class="reference external" href="http://0.0.0.0:7860">http://0.0.0.0:7860</a> that is running the AIM-CU locally.</p>
|
62 |
</section>
|
|
|
|
|
|
|
|
|
63 |
<section id="demo">
|
64 |
<h2>Demo<a class="headerlink" href="#demo" title="Link to this heading">¶</a></h2>
|
65 |
<p>AIM-CU can also be run through the demo available at <a class="reference external" href="https://huggingface.co/spaces/didsr/AIM-CU">https://huggingface.co/spaces/didsr/AIM-CU</a>. If Space is paused, click on Restart button.</p>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
66 |
<div class="toctree-wrapper compound">
|
67 |
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
|
68 |
<ul>
|
@@ -91,6 +129,10 @@ pip<span class="w"> </span>install<span class="w"> </span>-r<span class="w"> </s
|
|
91 |
</ul>
|
92 |
</div>
|
93 |
</section>
|
|
|
|
|
|
|
|
|
94 |
</section>
|
95 |
|
96 |
|
|
|
36 |
<section id="aim-cu-documentation">
|
37 |
<h1>AIM-CU documentation<a class="headerlink" href="#aim-cu-documentation" title="Link to this heading">¶</a></h1>
|
38 |
<p>A CUSUM-based tool for AI Monitoring</p>
|
39 |
+
<p>Monitoring a clinically deployed AI device to detect performance drift is an essential step to ensure the safety and effectiveness of AI.</p>
|
40 |
+
<p>AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU).</p>
|
41 |
+
<p>AIM-CU computes:</p>
|
42 |
<ul class="simple">
|
43 |
<li><p>The parameter choices for change-point detection based on an acceptable false alarm rate</p></li>
|
44 |
<li><p>Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.</p></li>
|
45 |
</ul>
|
46 |
+
<section id="system-setup">
|
47 |
+
<h2>System setup<a class="headerlink" href="#system-setup" title="Link to this heading">¶</a></h2>
|
48 |
+
<p>Make sure R is installed in the system. Instructions for linux (the below setup is only performed in linux):</p>
|
49 |
+
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span>wget<span class="w"> </span>-qO-<span class="w"> </span>https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc<span class="w"> </span><span class="p">|</span><span class="w"> </span>tee<span class="w"> </span>-a<span class="w"> </span>/etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
|
50 |
+
add-apt-repository<span class="w"> </span><span class="s2">"deb https://cloud.r-project.org/bin/linux/ubuntu </span><span class="k">$(</span>lsb_release<span class="w"> </span>-cs<span class="k">)</span><span class="s2">-cran40/"</span>
|
51 |
+
apt-get<span class="w"> </span>install<span class="w"> </span>-y<span class="w"> </span>--no-install-recommends<span class="w"> </span>r-base<span class="w"> </span>r-base-dev
|
52 |
+
|
53 |
+
<span class="c1"># setup R configs</span>
|
54 |
+
<span class="nb">echo</span><span class="w"> </span><span class="s2">"r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);"</span><span class="w"> </span>><span class="w"> </span>~/.Rprofile
|
55 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('ggplot2')"</span>
|
56 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('hexbin')"</span>
|
57 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('lazyeval')"</span>
|
58 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('cusumcharter')"</span>
|
59 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('RcppCNPy')"</span>
|
60 |
+
Rscript<span class="w"> </span>-e<span class="w"> </span><span class="s2">"install.packages('spc')"</span>
|
61 |
+
</pre></div>
|
62 |
+
</div>
|
63 |
+
</section>
|
64 |
<section id="code-execution">
|
65 |
<h2>Code execution<a class="headerlink" href="#code-execution" title="Link to this heading">¶</a></h2>
|
66 |
<p>Clone AIM-CU repository.</p>
|
|
|
75 |
</pre></div>
|
76 |
</div>
|
77 |
<p>Run AIM-CU.</p>
|
78 |
+
<div class="highlight-shell notranslate"><div class="highlight"><pre><span></span><span class="nb">cd</span><span class="w"> </span>src/package
|
79 |
+
python3<span class="w"> </span>app.py
|
80 |
</pre></div>
|
81 |
</div>
|
82 |
<p>Open the URL <a class="reference external" href="http://0.0.0.0:7860">http://0.0.0.0:7860</a> that is running the AIM-CU locally.</p>
|
83 |
</section>
|
84 |
+
<section id="example-code-execution">
|
85 |
+
<h2>Example code execution<a class="headerlink" href="#example-code-execution" title="Link to this heading">¶</a></h2>
|
86 |
+
<p>Example code can be run in a Jupyter Notebook after opening it with <code class="docutils literal notranslate"><span class="pre">jupyter</span> <span class="pre">notebook</span></code> command from <code class="docutils literal notranslate"><span class="pre">/src/package/</span></code> directory. The tool is designed to used through UI, not from console.</p>
|
87 |
+
</section>
|
88 |
<section id="demo">
|
89 |
<h2>Demo<a class="headerlink" href="#demo" title="Link to this heading">¶</a></h2>
|
90 |
<p>AIM-CU can also be run through the demo available at <a class="reference external" href="https://huggingface.co/spaces/didsr/AIM-CU">https://huggingface.co/spaces/didsr/AIM-CU</a>. If Space is paused, click on Restart button.</p>
|
91 |
+
</section>
|
92 |
+
<section id="usability">
|
93 |
+
<h2>Usability<a class="headerlink" href="#usability" title="Link to this heading">¶</a></h2>
|
94 |
+
<ul class="simple">
|
95 |
+
<li><p>Example AI output CSV file is available as <a class="reference external" href="config/spec-60-60.csv">config/spec-60-60.csv</a> to be uploaded in monitoring phase.</p></li>
|
96 |
+
<li><p>Workflow instruction to run the tool is available at bottom-left of UI.</p></li>
|
97 |
+
<li><p>Sample UI output is available at <a class="reference external" href="assets/ui.png">assets/ui.png</a>.</p></li>
|
98 |
+
<li><p>Setting <code class="docutils literal notranslate"><span class="pre">control:save_figure</span></code> to <code class="docutils literal notranslate"><span class="pre">true</span></code> from <a class="reference external" href="config/config.toml">config.toml</a> will save tables and plots in <a class="reference external" href="figure/">figure/</a>.</p></li>
|
99 |
+
<li><p>Running AIM-CU does not take time longer than a few seconds, and it does not require GPU.</p></li>
|
100 |
+
</ul>
|
101 |
+
</section>
|
102 |
+
<section id="aim-cu">
|
103 |
+
<h2>AIM-CU<a class="headerlink" href="#aim-cu" title="Link to this heading">¶</a></h2>
|
104 |
<div class="toctree-wrapper compound">
|
105 |
<p class="caption" role="heading"><span class="caption-text">Contents:</span></p>
|
106 |
<ul>
|
|
|
129 |
</ul>
|
130 |
</div>
|
131 |
</section>
|
132 |
+
<section id="disclaimer">
|
133 |
+
<h2>Disclaimer<a class="headerlink" href="#disclaimer" title="Link to this heading">¶</a></h2>
|
134 |
+
<p>This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.</p>
|
135 |
+
</section>
|
136 |
</section>
|
137 |
|
138 |
|
docs/build/html/searchindex.js
CHANGED
@@ -1 +1 @@
|
|
1 |
-
Search.setIndex({"alltitles": {"AIM-CU documentation": [[0, null]], "ARLTheoretical": [[3, null]], "CUSUM": [[1, null]], "CUSUM chart": [[2, "cusum-chart"]], "CUSUM parameters": [[2, "cusum-parameters"], [2, "id1"]], "Code execution": [[0, "code-execution"]], "Contents:": [[0, null]], "Demo": [[0, "demo"]], "Methods": [[2, null]], "Utils": [[4, null]]}, "docnames": ["index", "ref_cusum", "ref_method", "ref_theoretical", "ref_utils"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst", "ref_cusum.rst", "ref_method.rst", "ref_theoretical.rst", "ref_utils.rst"], "indexentries": {
|
|
|
1 |
+
Search.setIndex({"alltitles": {"AIM-CU": [[0, "aim-cu"]], "AIM-CU documentation": [[0, null]], "ARLTheoretical": [[3, null]], "CUSUM": [[1, null]], "CUSUM chart": [[2, "cusum-chart"]], "CUSUM parameters": [[2, "cusum-parameters"], [2, "id1"]], "Code execution": [[0, "code-execution"]], "Contents:": [[0, null]], "Demo": [[0, "demo"]], "Disclaimer": [[0, "disclaimer"]], "Example code execution": [[0, "example-code-execution"]], "Methods": [[2, null]], "System setup": [[0, "system-setup"]], "Usability": [[0, "usability"]], "Utils": [[4, null]]}, "docnames": ["index", "ref_cusum", "ref_method", "ref_theoretical", "ref_utils"], "envversion": {"sphinx": 64, "sphinx.domains.c": 3, "sphinx.domains.changeset": 1, "sphinx.domains.citation": 1, "sphinx.domains.cpp": 9, "sphinx.domains.index": 1, "sphinx.domains.javascript": 3, "sphinx.domains.math": 2, "sphinx.domains.python": 4, "sphinx.domains.rst": 2, "sphinx.domains.std": 2}, "filenames": ["index.rst", "ref_cusum.rst", "ref_method.rst", "ref_theoretical.rst", "ref_utils.rst"], "indexentries": {}, "objects": {"package": [[3, 0, 0, "-", "ARLTheoretical"], [1, 0, 0, "-", "cusum"], [4, 0, 0, "-", "utils"]], "package.ARLTheoretical": [[3, 1, 1, "", "get_ARL_1"], [3, 1, 1, "", "get_ARL_1_h_mu1_k"], [3, 1, 1, "", "get_ref_value"], [3, 1, 1, "", "get_ref_value_k"]], "package.cusum": [[1, 2, 1, "", "CUSUM"]], "package.cusum.CUSUM": [[1, 3, 1, "", "change_detection"], [1, 3, 1, "", "compute_cusum"], [1, 3, 1, "", "initialize"], [1, 3, 1, "", "plot_cusum_plotly"], [1, 3, 1, "", "plot_input_metric_plotly"], [1, 3, 1, "", "plot_input_metric_plotly_raw"], [1, 3, 1, "", "set_df_metric_csv"], [1, 3, 1, "", "set_df_metric_default"], [1, 3, 1, "", "set_init_stats"], [1, 3, 1, "", "set_timeline"]], "package.utils": [[4, 1, 1, "", "get_greattable_as_html"], [4, 1, 1, "", "populate_summary_table_ARL0_k"], [4, 1, 1, "", "populate_summary_table_ARL1_k"]]}, "objnames": {"0": ["py", "module", "Python module"], "1": ["py", "function", "Python function"], "2": ["py", "class", "Python class"], "3": ["py", "method", "Python method"]}, "objtypes": {"0": "py:module", "1": "py:function", "2": "py:class", "3": "py:method"}, "terms": {"0": [0, 1, 2], "1": 2, "10": 0, "105": 0, "17": 0, "3": 0, "30": 1, "4": [1, 2], "5": [1, 2], "60": 0, "7860": 0, "A": [0, 1, 2], "If": 0, "In": 1, "The": [0, 2], "To": 2, "_": 2, "about": 0, "accept": 0, "accumul": 2, "across": 1, "add": 0, "administr": 0, "advantag": 0, "after": 0, "ai": [0, 1], "alarm": 0, "along": 3, "also": 0, "although": 0, "an": [0, 1], "ani": 0, "app": 0, "apt": 0, "ar": [0, 1, 2], "arl0": [3, 4], "arl1": [3, 4], "arl_0": [2, 3], "arl_1": [2, 3], "arltheoret": [0, 4], "asc": 0, "ask": 0, "asset": 0, "assign": 1, "assum": 0, "author": [1, 3], "avail": 0, "awai": 2, "ax": 1, "base": 0, "bear": 0, "been": 0, "befor": 2, "being": 2, "below": 0, "between": 4, "bin": 0, "bottom": 0, "button": 0, "c": 0, "calcul": [1, 2, 3], "can": 0, "cd": 0, "chang": [0, 1, 2], "change_detect": 1, "characterist": 0, "charg": 0, "chart": 0, "choic": [0, 2], "class": 1, "click": 0, "clinic": 0, "clone": 0, "cloud": 0, "co": 0, "com": 0, "comma": 1, "command": 0, "compil": 0, "comput": [0, 1, 2], "compute_cusum": 1, "confer": 0, "config": 0, "configur": 1, "consid": 1, "consol": 0, "control": [0, 1, 2], "copi": 0, "copyright": 0, "cours": 0, "cran": 0, "cran40": 0, "cran_ubuntu_kei": 0, "csv": [0, 1], "cumul": [0, 1, 2], "cusum": 0, "cusumchart": 0, "d": [0, 2], "dai": 1, "data": [1, 3, 4], "data_csv": 1, "datafram": [1, 3, 4], "deal": 0, "deb": 0, "decis": 0, "default": [1, 2], "delai": [0, 3], "denot": 2, "depend": 0, "deploi": 0, "deriv": 0, "descript": 2, "design": 0, "detect": [0, 1, 2, 3], "determin": 2, "dev": 0, "develop": 0, "deviat": [1, 2], "devic": 0, "df": 4, "dict_arl0_k": [3, 4], "dictionari": [3, 4], "didsr": 0, "differ": [2, 4], "dimension": 1, "directori": 0, "displac": 0, "distribut": 0, "do": 0, "doe": 0, "domain": 0, "drift": [0, 2], "drug": 0, "duti": 0, "e": [0, 2], "echo": 0, "effect": 0, "employe": 0, "endors": 0, "ensur": 0, "essenti": 0, "estim": 0, "etc": 0, "exampl": 1, "express": 0, "fals": [0, 2], "fda": 0, "feder": 0, "few": 0, "figur": [0, 1], "file": [0, 1], "float": [1, 3, 4], "follow": 0, "food": 0, "format": 4, "free": 0, "freeli": 0, "from": [0, 2, 4], "function": 1, "furnish": 0, "further": 0, "get": [0, 3, 4], "get_arl_1": [0, 3], "get_arl_1_h_mu1_k": [0, 3], "get_greattable_as_html": [0, 4], "get_ref_valu": [0, 3], "get_ref_value_k": [0, 3], "getopt": 0, "ggplot2": 0, "git": 0, "github": 0, "given": [0, 3], "go": 1, "govern": 0, "gpg": 0, "gpu": 0, "grant": 0, "graph": 1, "great_tabl": 4, "gt": 4, "guarante": 0, "h": [2, 3, 4], "handl": 4, "hat": 2, "have": 0, "herebi": 0, "hexbin": 0, "hi": 2, "html": 4, "http": 0, "huggingfac": 0, "i": [0, 1, 2, 3], "impli": 0, "includ": 0, "individu": 2, "init_dai": 1, "initi": 1, "input": 1, "instal": 0, "instruct": 0, "int": 1, "intend": 3, "interest": [1, 2], "its": [0, 1, 4], "jupyt": 0, "k": [1, 2, 3, 4], "label": 1, "lazyev": 0, "left": 0, "let": 2, "limit": [0, 2], "linux": 0, "list": [1, 3], "list_arl_0": 3, "lo": 2, "local": 0, "longer": 0, "lsb_releas": 0, "magnitud": [1, 2], "make": 0, "map": 4, "marutter_pubkei": 0, "max": 2, "mean": [1, 2, 3], "merg": 0, "method": 0, "metric": [0, 1, 2], "modifi": 0, "monitor": [0, 1, 2], "mu": 2, "mu1": 3, "mu_": 2, "mu_0": 1, "multiindex": 4, "ndarrai": 1, "neg": [1, 2], "none": 1, "normal": [1, 2, 3, 4], "normalized_ref_valu": 1, "normalized_threshold": 1, "notebook": 0, "notic": 0, "np": 1, "number": [1, 2], "object": 1, "observ": [1, 2], "obtain": 0, "offici": 0, "one": [1, 2], "onli": 0, "open": 0, "oper": 4, "option": [0, 1], "ordereddict": [3, 4], "org": 0, "other": 0, "output": [0, 1], "packag": [0, 1, 3, 4], "panda": 4, "paramet": [0, 1, 3, 4], "parti": 0, "paus": 0, "pd": [3, 4], "perform": [0, 1, 2], "permiss": 0, "permit": 0, "person": 0, "phase": [0, 1], "pip": 0, "plot": [0, 1], "plot_cusum_plotli": 1, "plot_input_metric_plotli": 1, "plot_input_metric_plotly_raw": 1, "plotli": 1, "png": 0, "point": 0, "popul": 4, "populate_summary_table_arl0_k": [0, 4], "populate_summary_table_arl1_k": [0, 4], "posit": [1, 2], "prathapan": [1, 3], "pre_change_dai": 1, "process": [1, 2], "project": 0, "protect": 0, "provid": [1, 3], "public": 0, "publish": 0, "pursuant": 0, "py": 0, "python": 0, "python3": 0, "qo": 0, "qualiti": 0, "quantiti": 2, "r": 0, "rate": 0, "rcppcnpy": 0, "read": 1, "recommend": 0, "redistribut": 0, "refer": [1, 2, 3], "regulatori": 0, "relat": [1, 2], "reliabl": 0, "rendera": 4, "repo": 0, "repositori": 0, "requir": 0, "respect": 4, "respons": 0, "restart": 0, "restrict": 0, "return": [1, 3, 4], "right": 0, "rprofil": 0, "rscript": 0, "run": 0, "s_": 2, "s_hi": 2, "s_lo": 2, "safeti": 0, "sampl": 0, "save": 0, "save_figur": 0, "scatter": 1, "scheme": 2, "second": 0, "section": 0, "sell": 0, "separ": 1, "set": [0, 1], "set_df_metric_csv": 1, "set_df_metric_default": 1, "set_init_stat": 1, "set_timelin": 1, "shift": 3, "shift_in_mean": 3, "side": 2, "sigma_": 2, "signal": 2, "smriti": [1, 3], "so": 0, "softwar": 0, "some": 0, "sourc": 0, "space": 0, "spc": 0, "spec": 0, "specif": 4, "src": 0, "stabl": 1, "standard": [1, 2], "state": 0, "statist": 0, "step": 0, "structur": 1, "subject": 0, "sublicens": 0, "sum": [0, 1, 2], "summary_table_df_arl0_k": 4, "summary_table_df_arl1_k": 4, "sure": 0, "tabl": [0, 3, 4], "take": 0, "target": [0, 2], "tee": 0, "textfileread": 1, "than": 0, "thei": 0, "thi": [0, 2], "those": 0, "threshold": [1, 2, 3, 4], "through": 0, "time": [0, 2], "timelin": 1, "titl": 0, "toml": 0, "tool": 0, "true": [0, 2], "trust": 0, "tupl": [1, 3], "two": [1, 2], "txt": 0, "type": [1, 3, 4], "u": 0, "ubuntu": 0, "ui": 0, "unit": [0, 1, 2], "upload": 0, "url": 0, "us": [0, 1], "util": 0, "valu": [1, 2, 3, 4], "version": 0, "wa": 0, "wai": 0, "we": 0, "wget": 0, "whatsoev": 0, "when": [1, 2], "where": [2, 3], "which": 2, "whom": 0, "without": 0, "work": 0, "workflow": 0, "x": 1, "x_d": 2, "y": 0, "\u03bc_in": 2, "\u03c3_in": 2}, "titles": ["AIM-CU documentation", "CUSUM", "Methods", "ARLTheoretical", "Utils"], "titleterms": {"aim": 0, "arltheoret": 3, "chart": 2, "code": 0, "content": 0, "cu": 0, "cusum": [1, 2], "demo": 0, "disclaim": 0, "document": 0, "exampl": 0, "execut": 0, "method": 2, "paramet": 2, "setup": 0, "system": 0, "usabl": 0, "util": 4}})
|
docs/build/latex/aim-cu.pdf
CHANGED
@@ -1,3 +1,3 @@
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
-
oid sha256:
|
3 |
-
size
|
|
|
1 |
version https://git-lfs.github.com/spec/v1
|
2 |
+
oid sha256:43d5c4317b6206ef1cbbecf90ef47516a795e6fccecd683b267962e9cb3c6c64
|
3 |
+
size 242546
|
docs/source/index.rst
CHANGED
@@ -8,40 +8,83 @@ AIM-CU documentation
|
|
8 |
|
9 |
A CUSUM-based tool for AI Monitoring
|
10 |
|
11 |
-
|
|
|
|
|
|
|
|
|
12 |
|
13 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
14 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
15 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
16 |
Code execution
|
17 |
-
|
18 |
Clone AIM-CU repository.
|
19 |
|
20 |
.. code-block:: shell
|
21 |
|
22 |
-
|
23 |
|
24 |
Run the following commands to install required dependencies (Python = 3.10 is used).
|
25 |
|
26 |
.. code-block:: shell
|
27 |
|
28 |
-
|
29 |
-
|
30 |
-
|
31 |
-
|
32 |
|
33 |
Run AIM-CU.
|
34 |
|
35 |
.. code-block:: shell
|
36 |
|
37 |
-
|
|
|
38 |
|
39 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
40 |
|
|
|
|
|
|
|
|
|
41 |
Demo
|
42 |
-
|
43 |
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button.
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
.. toctree::
|
46 |
:maxdepth: 2
|
47 |
:caption: Contents:
|
@@ -49,4 +92,8 @@ AIM-CU can also be run through the demo available at https://huggingface.co/spac
|
|
49 |
ref_method
|
50 |
ref_cusum
|
51 |
ref_theoretical
|
52 |
-
ref_utils
|
|
|
|
|
|
|
|
|
|
8 |
|
9 |
A CUSUM-based tool for AI Monitoring
|
10 |
|
11 |
+
Monitoring a clinically deployed AI device to detect performance drift is an essential step to ensure the safety and effectiveness of AI.
|
12 |
+
|
13 |
+
AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU).
|
14 |
+
|
15 |
+
AIM-CU computes:
|
16 |
|
17 |
* The parameter choices for change-point detection based on an acceptable false alarm rate
|
18 |
* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.
|
19 |
|
20 |
+
System setup
|
21 |
+
------------
|
22 |
+
Make sure R is installed in the system. Instructions for linux (the below setup is only performed in linux):
|
23 |
+
|
24 |
+
.. code-block:: shell
|
25 |
+
|
26 |
+
wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc
|
27 |
+
add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/"
|
28 |
+
apt-get install -y --no-install-recommends r-base r-base-dev
|
29 |
+
|
30 |
+
# setup R configs
|
31 |
+
echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile
|
32 |
+
Rscript -e "install.packages('ggplot2')"
|
33 |
+
Rscript -e "install.packages('hexbin')"
|
34 |
+
Rscript -e "install.packages('lazyeval')"
|
35 |
+
Rscript -e "install.packages('cusumcharter')"
|
36 |
+
Rscript -e "install.packages('RcppCNPy')"
|
37 |
+
Rscript -e "install.packages('spc')"
|
38 |
+
|
39 |
Code execution
|
40 |
+
--------------
|
41 |
Clone AIM-CU repository.
|
42 |
|
43 |
.. code-block:: shell
|
44 |
|
45 |
+
git clone https://github.com/DIDSR/AIM-CU.git
|
46 |
|
47 |
Run the following commands to install required dependencies (Python = 3.10 is used).
|
48 |
|
49 |
.. code-block:: shell
|
50 |
|
51 |
+
apt-get -y install python3
|
52 |
+
apt-get -y install pip
|
53 |
+
cd AIM-CU
|
54 |
+
pip install -r requirements.txt
|
55 |
|
56 |
Run AIM-CU.
|
57 |
|
58 |
.. code-block:: shell
|
59 |
|
60 |
+
cd src/package
|
61 |
+
python3 app.py
|
62 |
|
63 |
Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.
|
64 |
|
65 |
+
Example code execution
|
66 |
+
----------------------
|
67 |
+
Example code can be run in a Jupyter Notebook after opening it with ``jupyter notebook`` command from ``/src/package/`` directory. The tool is designed to used through UI, not from console.
|
68 |
+
|
69 |
Demo
|
70 |
+
----
|
71 |
AIM-CU can also be run through the demo available at https://huggingface.co/spaces/didsr/AIM-CU. If Space is paused, click on Restart button.
|
72 |
|
73 |
+
Usability
|
74 |
+
---------
|
75 |
+
* Example AI output CSV file is available as `config/spec-60-60.csv <config/spec-60-60.csv>`_ to be uploaded in monitoring phase.
|
76 |
+
|
77 |
+
* Workflow instruction to run the tool is available at bottom-left of UI.
|
78 |
+
|
79 |
+
* Sample UI output is available at `assets/ui.png <assets/ui.png>`_.
|
80 |
+
|
81 |
+
* Setting ``control:save_figure`` to ``true`` from `config.toml <config/config.toml>`_ will save tables and plots in `figure/ <figure/>`_.
|
82 |
+
|
83 |
+
* Running AIM-CU does not take time longer than a few seconds, and it does not require GPU.
|
84 |
+
|
85 |
+
AIM-CU
|
86 |
+
------
|
87 |
+
|
88 |
.. toctree::
|
89 |
:maxdepth: 2
|
90 |
:caption: Contents:
|
|
|
92 |
ref_method
|
93 |
ref_cusum
|
94 |
ref_theoretical
|
95 |
+
ref_utils
|
96 |
+
|
97 |
+
Disclaimer
|
98 |
+
----------
|
99 |
+
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
figure/fig_plot_average_metric.png
ADDED
![]() |
Git LFS Details
|
figure/fig_plot_cusum_chart.png
ADDED
![]() |
Git LFS Details
|
figure/fig_plot_data_distribution.png
ADDED
![]() |
Git LFS Details
|
figure/fig_table_h_arl0_k.png
ADDED
![]() |
figure/fig_table_h_k_arl1.png
ADDED
![]() |
Git LFS Details
|
src/package/ARLTheoretical.py
CHANGED
@@ -129,7 +129,7 @@ def get_ARL_1(
|
|
129 |
utils = rpackages.importr("utils")
|
130 |
spc = rpackages.importr("spc")
|
131 |
# select a mirror for R packages
|
132 |
-
utils.chooseCRANmirror(ind=1) # select the first mirror in the list
|
133 |
|
134 |
# R package names
|
135 |
packnames = ("ggplot2", "hexbin", "lazyeval", "cusumcharter", "RcppCNPy", "spc")
|
|
|
129 |
utils = rpackages.importr("utils")
|
130 |
spc = rpackages.importr("spc")
|
131 |
# select a mirror for R packages
|
132 |
+
# utils.chooseCRANmirror(ind=1) # select the first mirror in the list
|
133 |
|
134 |
# R package names
|
135 |
packnames = ("ggplot2", "hexbin", "lazyeval", "cusumcharter", "RcppCNPy", "spc")
|
src/package/__pycache__/ARLTheoretical.cpython-310.pyc
CHANGED
Binary files a/src/package/__pycache__/ARLTheoretical.cpython-310.pyc and b/src/package/__pycache__/ARLTheoretical.cpython-310.pyc differ
|
|
src/package/__pycache__/cusum.cpython-310.pyc
CHANGED
Binary files a/src/package/__pycache__/cusum.cpython-310.pyc and b/src/package/__pycache__/cusum.cpython-310.pyc differ
|
|
src/package/__pycache__/utils.cpython-310.pyc
CHANGED
Binary files a/src/package/__pycache__/utils.cpython-310.pyc and b/src/package/__pycache__/utils.cpython-310.pyc differ
|
|
src/package/app.py
CHANGED
@@ -1,5 +1,8 @@
|
|
1 |
"""
|
2 |
Gradio user interface for AIM-CU
|
|
|
|
|
|
|
3 |
"""
|
4 |
|
5 |
import os
|
@@ -21,11 +24,11 @@ def set_init_days(
|
|
21 |
file_csv_metric: gr.File, init_days: str
|
22 |
) -> tuple[float, float, go.Figure]:
|
23 |
"""
|
24 |
-
Set
|
25 |
|
26 |
Args:
|
27 |
file_csv_metric (gr.File): CSV file with metric data
|
28 |
-
init_days (str):
|
29 |
|
30 |
Returns:
|
31 |
tuple[float, float, go.Figure]: In-control mean and standard deviation, and observation data plot.
|
@@ -174,7 +177,7 @@ with gr.Blocks(
|
|
174 |
with gr.Row():
|
175 |
with gr.Column():
|
176 |
gr.Markdown(f"""
|
177 |
-
###
|
178 |
""") # noqa: F541
|
179 |
|
180 |
gr.Markdown(f"""
|
@@ -183,12 +186,12 @@ with gr.Blocks(
|
|
183 |
|
184 |
# load the CSV file with specifities across days
|
185 |
csv_file_metric = gr.File(
|
186 |
-
label="Upload the AI output",
|
187 |
)
|
188 |
|
189 |
with gr.Row():
|
190 |
with gr.Column():
|
191 |
-
init_days = gr.Textbox(label="
|
192 |
with gr.Column():
|
193 |
button_calculate_incontrol_params = gr.Button(
|
194 |
"Calculate parameters"
|
@@ -271,8 +274,8 @@ with gr.Blocks(
|
|
271 |
gr.Markdown(f"""
|
272 |
### Workflow:
|
273 |
Phase I:
|
274 |
-
- Upload the AI output.
|
275 |
-
- Enter
|
276 |
- Calculate parameters.
|
277 |
- Check parameter choices in Phase 1, for Phase 2. (optional)
|
278 |
|
@@ -286,7 +289,7 @@ with gr.Blocks(
|
|
286 |
)
|
287 |
with gr.Column():
|
288 |
gr.Markdown(f"""
|
289 |
-
###
|
290 |
Performance drift detection plots, pre- and post-change distribution with respect to the performance drift detected.
|
291 |
""") # noqa: F541
|
292 |
|
|
|
1 |
"""
|
2 |
Gradio user interface for AIM-CU
|
3 |
+
|
4 |
+
Disclaimer:
|
5 |
+
This software and documentation was developed at the Food and Drug Administration (FDA) by employees of the Federal Government in the course of their official duties. Pursuant to Title 17, Section 105 of the United States Code, this work is not subject to copyright protection and is in the public domain. Permission is hereby granted, free of charge, to any person obtaining a copy of the Software, to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, or sell copies of the Software or derivatives, and to permit persons to whom the Software is furnished to do so. FDA assumes no responsibility whatsoever for use by other parties of the Software, its source code, documentation or compiled executables, and makes no guarantees, expressed or implied, about its quality, reliability, or any other characteristic. Further, use of this code in no way implies endorsement by the FDA or confers any advantage in regulatory decisions. Although this software can be redistributed and/or modified freely, we ask that any derivative works bear some notice that they are derived from it, and any modified versions bear some notice that they have been modified.
|
6 |
"""
|
7 |
|
8 |
import os
|
|
|
24 |
file_csv_metric: gr.File, init_days: str
|
25 |
) -> tuple[float, float, go.Figure]:
|
26 |
"""
|
27 |
+
Set number of baseline observations and get in-control mean and standard deviation.
|
28 |
|
29 |
Args:
|
30 |
file_csv_metric (gr.File): CSV file with metric data
|
31 |
+
init_days (str): Number of baseline observations to calculate in-control mean and standard deviation
|
32 |
|
33 |
Returns:
|
34 |
tuple[float, float, go.Figure]: In-control mean and standard deviation, and observation data plot.
|
|
|
177 |
with gr.Row():
|
178 |
with gr.Column():
|
179 |
gr.Markdown(f"""
|
180 |
+
### Initialization:
|
181 |
""") # noqa: F541
|
182 |
|
183 |
gr.Markdown(f"""
|
|
|
186 |
|
187 |
# load the CSV file with specifities across days
|
188 |
csv_file_metric = gr.File(
|
189 |
+
label="Upload the AI output (CSV file)",
|
190 |
)
|
191 |
|
192 |
with gr.Row():
|
193 |
with gr.Column():
|
194 |
+
init_days = gr.Textbox(label="Number of baseline observations", placeholder="30")
|
195 |
with gr.Column():
|
196 |
button_calculate_incontrol_params = gr.Button(
|
197 |
"Calculate parameters"
|
|
|
274 |
gr.Markdown(f"""
|
275 |
### Workflow:
|
276 |
Phase I:
|
277 |
+
- Upload the AI output (CSV file).
|
278 |
+
- Enter number of baseline observations.
|
279 |
- Calculate parameters.
|
280 |
- Check parameter choices in Phase 1, for Phase 2. (optional)
|
281 |
|
|
|
289 |
)
|
290 |
with gr.Column():
|
291 |
gr.Markdown(f"""
|
292 |
+
### Monitoring:
|
293 |
Performance drift detection plots, pre- and post-change distribution with respect to the performance drift detected.
|
294 |
""") # noqa: F541
|
295 |
|
src/package/cusum.py
CHANGED
@@ -60,10 +60,10 @@ class CUSUM:
|
|
60 |
|
61 |
def set_init_stats(self, init_days: int) -> None:
|
62 |
"""
|
63 |
-
Use
|
64 |
|
65 |
Args:
|
66 |
-
init_days (int, optional):
|
67 |
"""
|
68 |
self.init_days = init_days
|
69 |
|
@@ -171,7 +171,7 @@ class CUSUM:
|
|
171 |
normalized_ref_value (float, optional): Normalized reference value for detecting a unit standard deviation change in mean of the process. Defaults to 0.5.
|
172 |
normalized_threshold (float, optional): Normalized threshold. Defaults to 4.
|
173 |
"""
|
174 |
-
self.pre_change_days = self.init_days # This is the
|
175 |
|
176 |
ref_val = normalized_ref_value
|
177 |
control_limit = normalized_threshold
|
@@ -313,7 +313,7 @@ class CUSUM:
|
|
313 |
fig.add_vrect(
|
314 |
x0=0,
|
315 |
x1=self.init_days,
|
316 |
-
annotation_text="
|
317 |
annotation_position="top right",
|
318 |
fillcolor="palegreen",
|
319 |
opacity=0.25,
|
@@ -326,7 +326,7 @@ class CUSUM:
|
|
326 |
"font": {"size": font_size_title, "weight": "bold"},
|
327 |
},
|
328 |
xaxis_title={
|
329 |
-
"text": "
|
330 |
"font": {"size": font_size_legend, "weight": "bold"},
|
331 |
},
|
332 |
yaxis_title={
|
@@ -361,13 +361,7 @@ class CUSUM:
|
|
361 |
y2 = self.data[self.pre_change_days : self.total_days]
|
362 |
mean_y2 = np.mean(y2)
|
363 |
|
364 |
-
fig =
|
365 |
-
rows=1,
|
366 |
-
cols=2,
|
367 |
-
column_widths=[0.7, 0.3],
|
368 |
-
shared_yaxes=True,
|
369 |
-
horizontal_spacing=0.02,
|
370 |
-
)
|
371 |
|
372 |
font_size_title = 20
|
373 |
font_size_legend = 18
|
@@ -382,8 +376,6 @@ class CUSUM:
|
|
382 |
marker=dict(color="darkturquoise", size=10),
|
383 |
opacity=0.4,
|
384 |
),
|
385 |
-
row=1,
|
386 |
-
col=1,
|
387 |
)
|
388 |
fig.add_trace(
|
389 |
go.Scatter(
|
@@ -394,8 +386,6 @@ class CUSUM:
|
|
394 |
marker=dict(color="coral", size=10),
|
395 |
opacity=0.4,
|
396 |
),
|
397 |
-
row=1,
|
398 |
-
col=1,
|
399 |
)
|
400 |
|
401 |
# add horizontal lines
|
@@ -407,8 +397,6 @@ class CUSUM:
|
|
407 |
name="In-control mean",
|
408 |
line=dict(color="darkturquoise", dash="dash"),
|
409 |
),
|
410 |
-
row=1,
|
411 |
-
col=1,
|
412 |
)
|
413 |
fig.add_trace(
|
414 |
go.Scatter(
|
@@ -418,8 +406,6 @@ class CUSUM:
|
|
418 |
name="Out-of-control mean",
|
419 |
line=dict(color="coral", dash="dash"),
|
420 |
),
|
421 |
-
row=1,
|
422 |
-
col=1,
|
423 |
)
|
424 |
|
425 |
# add vertical line
|
@@ -432,17 +418,15 @@ class CUSUM:
|
|
432 |
line=dict(color="grey", dash="dash"),
|
433 |
# textfont=dict(size=18)
|
434 |
),
|
435 |
-
row=1,
|
436 |
-
col=1,
|
437 |
)
|
438 |
|
439 |
fig.update_layout(
|
440 |
title={
|
441 |
-
"text": "Pre- and post-change observations
|
442 |
"font": {"size": font_size_title, "weight": "bold"},
|
443 |
},
|
444 |
xaxis_title={
|
445 |
-
"text": "
|
446 |
"font": {"size": font_size_legend, "weight": "bold"},
|
447 |
},
|
448 |
yaxis_title={
|
@@ -458,64 +442,64 @@ class CUSUM:
|
|
458 |
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
|
459 |
)
|
460 |
|
461 |
-
# add histogram (like marginal histogram)
|
462 |
-
nbinsx = 15 # 6
|
463 |
-
|
464 |
-
# add subplots
|
465 |
-
fig.add_trace(
|
466 |
-
|
467 |
-
|
468 |
-
|
469 |
-
|
470 |
-
|
471 |
-
|
472 |
-
|
473 |
-
|
474 |
-
|
475 |
-
|
476 |
-
|
477 |
-
)
|
478 |
-
|
479 |
-
fig.add_trace(
|
480 |
-
|
481 |
-
|
482 |
-
|
483 |
-
|
484 |
-
|
485 |
-
|
486 |
-
|
487 |
-
|
488 |
-
|
489 |
-
|
490 |
-
|
491 |
-
)
|
492 |
-
|
493 |
-
fig.add_trace(
|
494 |
-
|
495 |
-
|
496 |
-
|
497 |
-
|
498 |
-
|
499 |
-
|
500 |
-
|
501 |
-
|
502 |
-
|
503 |
-
|
504 |
-
|
505 |
-
|
506 |
-
|
507 |
-
)
|
508 |
-
|
509 |
-
fig.update_xaxes(
|
510 |
-
|
511 |
-
|
512 |
-
|
513 |
-
|
514 |
-
|
515 |
-
)
|
516 |
-
|
517 |
-
# update layout
|
518 |
-
fig.update_layout(barmode="overlay")
|
519 |
|
520 |
if self.config["control"]["save_figure"] == "true":
|
521 |
fig.write_image(
|
@@ -525,9 +509,9 @@ class CUSUM:
|
|
525 |
"../../", self.config["path_output"]["path_figure"]
|
526 |
)
|
527 |
),
|
528 |
-
"
|
529 |
),
|
530 |
-
scale=
|
531 |
)
|
532 |
print(
|
533 |
"Created",
|
@@ -537,7 +521,7 @@ class CUSUM:
|
|
537 |
"../../", self.config["path_output"]["path_figure"]
|
538 |
)
|
539 |
),
|
540 |
-
"
|
541 |
),
|
542 |
)
|
543 |
|
@@ -555,14 +539,13 @@ class CUSUM:
|
|
555 |
font_size_title = 20
|
556 |
font_size_legend = 18
|
557 |
|
558 |
-
# add subplots
|
559 |
fig.add_trace(
|
560 |
go.Scatter(
|
561 |
x=list(range(len(self.S_hi))),
|
562 |
y=self.S_hi / self.in_std,
|
563 |
mode="lines",
|
564 |
name=f"""Positive changes (S<sub>hi</sub>)""",
|
565 |
-
marker=dict(color="
|
566 |
)
|
567 |
)
|
568 |
fig.add_trace(
|
@@ -582,21 +565,7 @@ class CUSUM:
|
|
582 |
y=[self.H / self.in_std, self.H / self.in_std],
|
583 |
mode="lines",
|
584 |
name="Threshold (h)",
|
585 |
-
line=dict(color="
|
586 |
-
)
|
587 |
-
)
|
588 |
-
|
589 |
-
# add vertical line
|
590 |
-
fig.add_trace(
|
591 |
-
go.Scatter(
|
592 |
-
x=[self.pre_change_days, self.pre_change_days],
|
593 |
-
y=[
|
594 |
-
0,
|
595 |
-
np.max(self.S_lo / self.in_std),
|
596 |
-
],
|
597 |
-
mode="lines",
|
598 |
-
name="Change-point",
|
599 |
-
line=dict(color="grey", dash="dash"),
|
600 |
)
|
601 |
)
|
602 |
|
@@ -606,7 +575,7 @@ class CUSUM:
|
|
606 |
"font": {"size": font_size_title, "weight": "bold"},
|
607 |
},
|
608 |
xaxis_title={
|
609 |
-
"text": "
|
610 |
"font": {"size": font_size_legend, "weight": "bold"},
|
611 |
},
|
612 |
yaxis_title={
|
@@ -616,7 +585,28 @@ class CUSUM:
|
|
616 |
xaxis=dict(dtick=20),
|
617 |
)
|
618 |
|
619 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
620 |
|
621 |
fig.update_layout(
|
622 |
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
|
@@ -630,9 +620,9 @@ class CUSUM:
|
|
630 |
"../../", self.config["path_output"]["path_figure"]
|
631 |
)
|
632 |
),
|
633 |
-
"
|
634 |
),
|
635 |
-
scale=
|
636 |
)
|
637 |
print(
|
638 |
"Created",
|
@@ -642,7 +632,7 @@ class CUSUM:
|
|
642 |
"../../", self.config["path_output"]["path_figure"]
|
643 |
)
|
644 |
),
|
645 |
-
"
|
646 |
),
|
647 |
)
|
648 |
|
|
|
60 |
|
61 |
def set_init_stats(self, init_days: int) -> None:
|
62 |
"""
|
63 |
+
Use number of baseline observations to calculate in-control mean and standard deviation.
|
64 |
|
65 |
Args:
|
66 |
+
init_days (int, optional): Number of baseline observations when observations are considered stable. Defaults to 30.
|
67 |
"""
|
68 |
self.init_days = init_days
|
69 |
|
|
|
171 |
normalized_ref_value (float, optional): Normalized reference value for detecting a unit standard deviation change in mean of the process. Defaults to 0.5.
|
172 |
normalized_threshold (float, optional): Normalized threshold. Defaults to 4.
|
173 |
"""
|
174 |
+
self.pre_change_days = self.init_days # This is the number of baseline observations that we assume to be in-control - user enters or default = 30
|
175 |
|
176 |
ref_val = normalized_ref_value
|
177 |
control_limit = normalized_threshold
|
|
|
313 |
fig.add_vrect(
|
314 |
x0=0,
|
315 |
x1=self.init_days,
|
316 |
+
annotation_text="Baseline observations",
|
317 |
annotation_position="top right",
|
318 |
fillcolor="palegreen",
|
319 |
opacity=0.25,
|
|
|
326 |
"font": {"size": font_size_title, "weight": "bold"},
|
327 |
},
|
328 |
xaxis_title={
|
329 |
+
"text": "Time",
|
330 |
"font": {"size": font_size_legend, "weight": "bold"},
|
331 |
},
|
332 |
yaxis_title={
|
|
|
361 |
y2 = self.data[self.pre_change_days : self.total_days]
|
362 |
mean_y2 = np.mean(y2)
|
363 |
|
364 |
+
fig = go.Figure()
|
|
|
|
|
|
|
|
|
|
|
|
|
365 |
|
366 |
font_size_title = 20
|
367 |
font_size_legend = 18
|
|
|
376 |
marker=dict(color="darkturquoise", size=10),
|
377 |
opacity=0.4,
|
378 |
),
|
|
|
|
|
379 |
)
|
380 |
fig.add_trace(
|
381 |
go.Scatter(
|
|
|
386 |
marker=dict(color="coral", size=10),
|
387 |
opacity=0.4,
|
388 |
),
|
|
|
|
|
389 |
)
|
390 |
|
391 |
# add horizontal lines
|
|
|
397 |
name="In-control mean",
|
398 |
line=dict(color="darkturquoise", dash="dash"),
|
399 |
),
|
|
|
|
|
400 |
)
|
401 |
fig.add_trace(
|
402 |
go.Scatter(
|
|
|
406 |
name="Out-of-control mean",
|
407 |
line=dict(color="coral", dash="dash"),
|
408 |
),
|
|
|
|
|
409 |
)
|
410 |
|
411 |
# add vertical line
|
|
|
418 |
line=dict(color="grey", dash="dash"),
|
419 |
# textfont=dict(size=18)
|
420 |
),
|
|
|
|
|
421 |
)
|
422 |
|
423 |
fig.update_layout(
|
424 |
title={
|
425 |
+
"text": "Pre- and post-change observations",
|
426 |
"font": {"size": font_size_title, "weight": "bold"},
|
427 |
},
|
428 |
xaxis_title={
|
429 |
+
"text": "Time",
|
430 |
"font": {"size": font_size_legend, "weight": "bold"},
|
431 |
},
|
432 |
yaxis_title={
|
|
|
442 |
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
|
443 |
)
|
444 |
|
445 |
+
# # add histogram (like marginal histogram)
|
446 |
+
# nbinsx = 15 # 6
|
447 |
+
|
448 |
+
# # add subplots
|
449 |
+
# fig.add_trace(
|
450 |
+
# go.Histogram(
|
451 |
+
# y=self.data[: self.pre_change_days],
|
452 |
+
# nbinsy=nbinsx,
|
453 |
+
# # name=f"""Pre-change S<sub>p</sub>""",
|
454 |
+
# showlegend=False,
|
455 |
+
# marker=dict(color="mediumturquoise"),
|
456 |
+
# opacity=0.4,
|
457 |
+
# orientation="h",
|
458 |
+
# ),
|
459 |
+
# row=1,
|
460 |
+
# col=2,
|
461 |
+
# )
|
462 |
+
|
463 |
+
# fig.add_trace(
|
464 |
+
# go.Histogram(
|
465 |
+
# y=self.data[self.pre_change_days : self.total_days],
|
466 |
+
# nbinsy=nbinsx,
|
467 |
+
# # name=f"""Post-change S<sub>p</sub>""",
|
468 |
+
# showlegend=False,
|
469 |
+
# marker=dict(color="coral"),
|
470 |
+
# opacity=0.4,
|
471 |
+
# orientation="h",
|
472 |
+
# ),
|
473 |
+
# row=1,
|
474 |
+
# col=2,
|
475 |
+
# )
|
476 |
+
|
477 |
+
# fig.add_trace(
|
478 |
+
# go.Scatter(
|
479 |
+
# x=[0, 20], # [! y_max can should be used]
|
480 |
+
# y=[
|
481 |
+
# np.mean(self.data[: self.pre_change_days]),
|
482 |
+
# np.mean(self.data[: self.pre_change_days]),
|
483 |
+
# ],
|
484 |
+
# mode="lines",
|
485 |
+
# # name="Reference mean",
|
486 |
+
# showlegend=False,
|
487 |
+
# line=dict(color="mediumturquoise", dash="dash"),
|
488 |
+
# ),
|
489 |
+
# row=1,
|
490 |
+
# col=2,
|
491 |
+
# )
|
492 |
+
|
493 |
+
# fig.update_xaxes(
|
494 |
+
# title_text="Count",
|
495 |
+
# title_font_size=font_size_legend,
|
496 |
+
# title_font_weight="bold",
|
497 |
+
# row=1,
|
498 |
+
# col=2,
|
499 |
+
# )
|
500 |
+
|
501 |
+
# # update layout
|
502 |
+
# fig.update_layout(barmode="overlay")
|
503 |
|
504 |
if self.config["control"]["save_figure"] == "true":
|
505 |
fig.write_image(
|
|
|
509 |
"../../", self.config["path_output"]["path_figure"]
|
510 |
)
|
511 |
),
|
512 |
+
"fig_plot_data_distribution.png",
|
513 |
),
|
514 |
+
scale=6,
|
515 |
)
|
516 |
print(
|
517 |
"Created",
|
|
|
521 |
"../../", self.config["path_output"]["path_figure"]
|
522 |
)
|
523 |
),
|
524 |
+
"fig_plot_data_distribution.png",
|
525 |
),
|
526 |
)
|
527 |
|
|
|
539 |
font_size_title = 20
|
540 |
font_size_legend = 18
|
541 |
|
|
|
542 |
fig.add_trace(
|
543 |
go.Scatter(
|
544 |
x=list(range(len(self.S_hi))),
|
545 |
y=self.S_hi / self.in_std,
|
546 |
mode="lines",
|
547 |
name=f"""Positive changes (S<sub>hi</sub>)""",
|
548 |
+
marker=dict(color="rgb(0, 209, 209)", size=10),
|
549 |
)
|
550 |
)
|
551 |
fig.add_trace(
|
|
|
565 |
y=[self.H / self.in_std, self.H / self.in_std],
|
566 |
mode="lines",
|
567 |
name="Threshold (h)",
|
568 |
+
line=dict(color="rgb(250, 0, 125)", dash="dash"),
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
569 |
)
|
570 |
)
|
571 |
|
|
|
575 |
"font": {"size": font_size_title, "weight": "bold"},
|
576 |
},
|
577 |
xaxis_title={
|
578 |
+
"text": "Time",
|
579 |
"font": {"size": font_size_legend, "weight": "bold"},
|
580 |
},
|
581 |
yaxis_title={
|
|
|
585 |
xaxis=dict(dtick=20),
|
586 |
)
|
587 |
|
588 |
+
|
589 |
+
fig.add_shape(
|
590 |
+
type="rect",
|
591 |
+
x0=0, x1=60,
|
592 |
+
y0=0, y1=1, # use relative values (0 to 1) for full y-range
|
593 |
+
xref="x", yref="paper", # "paper" for full plot height
|
594 |
+
fillcolor=self.config["color"]["blue_005"],
|
595 |
+
opacity=0.8,
|
596 |
+
layer="below",
|
597 |
+
line_width=0,
|
598 |
+
)
|
599 |
+
|
600 |
+
fig.add_shape(
|
601 |
+
type="rect",
|
602 |
+
x0=60, x1=len(self.S_lo), # x1=1 means extend to right edge of plot (paper coordinates)
|
603 |
+
y0=0, y1=1,
|
604 |
+
xref="x", yref="paper",
|
605 |
+
fillcolor="rgb(253, 243, 235)",
|
606 |
+
opacity=0.8,
|
607 |
+
layer="below",
|
608 |
+
line_width=0,
|
609 |
+
)
|
610 |
|
611 |
fig.update_layout(
|
612 |
legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1)
|
|
|
620 |
"../../", self.config["path_output"]["path_figure"]
|
621 |
)
|
622 |
),
|
623 |
+
"fig_plot_cusum_chart.png",
|
624 |
),
|
625 |
+
scale=6,
|
626 |
)
|
627 |
print(
|
628 |
"Created",
|
|
|
632 |
"../../", self.config["path_output"]["path_figure"]
|
633 |
)
|
634 |
),
|
635 |
+
"fig_plot_cusum_chart.png",
|
636 |
),
|
637 |
)
|
638 |
|
src/package/example_AIM_CU.ipynb
CHANGED
The diff for this file is too large to render.
See raw diff
|
|
src/package/utils.py
CHANGED
@@ -59,7 +59,7 @@ def populate_summary_table_ARL0_k(summary_table_df_ARL0_k: pd.DataFrame, h) -> g
|
|
59 |
table_great_table_ARL0_k.save(
|
60 |
os.path.abspath(
|
61 |
os.path.join(
|
62 |
-
"../../", config["path_output"]["path_figure"], "
|
63 |
)
|
64 |
),
|
65 |
scale=3,
|
@@ -69,7 +69,7 @@ def populate_summary_table_ARL0_k(summary_table_df_ARL0_k: pd.DataFrame, h) -> g
|
|
69 |
"Created",
|
70 |
os.path.abspath(
|
71 |
os.path.join(
|
72 |
-
"../../", config["path_output"]["path_figure"], "
|
73 |
)
|
74 |
),
|
75 |
)
|
@@ -127,7 +127,7 @@ def populate_summary_table_ARL1_k(
|
|
127 |
table_great_table_ARL1_k.save(
|
128 |
os.path.abspath(
|
129 |
os.path.join(
|
130 |
-
"../../", config["path_output"]["path_figure"], "
|
131 |
)
|
132 |
),
|
133 |
scale=3,
|
@@ -137,7 +137,7 @@ def populate_summary_table_ARL1_k(
|
|
137 |
"Created",
|
138 |
os.path.abspath(
|
139 |
os.path.join(
|
140 |
-
"../../", config["path_output"]["path_figure"], "
|
141 |
)
|
142 |
),
|
143 |
)
|
|
|
59 |
table_great_table_ARL0_k.save(
|
60 |
os.path.abspath(
|
61 |
os.path.join(
|
62 |
+
"../../", config["path_output"]["path_figure"], "fig_table_h_arl0_k.png"
|
63 |
)
|
64 |
),
|
65 |
scale=3,
|
|
|
69 |
"Created",
|
70 |
os.path.abspath(
|
71 |
os.path.join(
|
72 |
+
"../../", config["path_output"]["path_figure"], "fig_table_h_arl0_k.png"
|
73 |
)
|
74 |
),
|
75 |
)
|
|
|
127 |
table_great_table_ARL1_k.save(
|
128 |
os.path.abspath(
|
129 |
os.path.join(
|
130 |
+
"../../", config["path_output"]["path_figure"], "fig_table_h_k_arl1.png"
|
131 |
)
|
132 |
),
|
133 |
scale=3,
|
|
|
137 |
"Created",
|
138 |
os.path.abspath(
|
139 |
os.path.join(
|
140 |
+
"../../", config["path_output"]["path_figure"], "fig_table_h_k_arl1.png"
|
141 |
)
|
142 |
),
|
143 |
)
|
tests/test.py
CHANGED
@@ -23,6 +23,7 @@ class TestCUSUM(unittest.TestCase):
|
|
23 |
|
24 |
def test_cusum(self):
|
25 |
obj_cusum = CUSUM()
|
|
|
26 |
|
27 |
path_file_config = os.path.abspath("../config/config.toml")
|
28 |
with open(os.path.abspath(path_file_config), "rb") as file_config:
|
@@ -30,26 +31,28 @@ class TestCUSUM(unittest.TestCase):
|
|
30 |
|
31 |
ref_value = 0.5
|
32 |
normalized_threshold = 4
|
33 |
-
pre_change_days = 60
|
34 |
|
35 |
obj_cusum.df_metric = pd.read_csv(os.path.abspath("../config/spec-60-60.csv"))
|
36 |
obj_cusum.data = obj_cusum.df_metric[obj_cusum.df_metric.columns[1]].to_numpy()
|
37 |
obj_cusum.set_timeline(obj_cusum.data)
|
38 |
|
|
|
|
|
|
|
|
|
39 |
obj_cusum.change_detection(
|
40 |
-
pre_change_days=pre_change_days,
|
41 |
normalized_ref_value=ref_value,
|
42 |
normalized_threshold=normalized_threshold,
|
43 |
)
|
44 |
|
45 |
self.assertEqual(
|
46 |
-
obj_cusum.S_lo[-1], 2.
|
47 |
)
|
48 |
|
49 |
def test_rpy2(self):
|
50 |
arl_1 = get_ARL_1_h_mu1_k(h=4, k=0.2996, mu1=1.2)
|
51 |
|
52 |
-
self.assertEqual(arl_1, 4.
|
53 |
|
54 |
|
55 |
if __name__ == "__main__":
|
|
|
23 |
|
24 |
def test_cusum(self):
|
25 |
obj_cusum = CUSUM()
|
26 |
+
# obj_cusum.initialize()
|
27 |
|
28 |
path_file_config = os.path.abspath("../config/config.toml")
|
29 |
with open(os.path.abspath(path_file_config), "rb") as file_config:
|
|
|
31 |
|
32 |
ref_value = 0.5
|
33 |
normalized_threshold = 4
|
|
|
34 |
|
35 |
obj_cusum.df_metric = pd.read_csv(os.path.abspath("../config/spec-60-60.csv"))
|
36 |
obj_cusum.data = obj_cusum.df_metric[obj_cusum.df_metric.columns[1]].to_numpy()
|
37 |
obj_cusum.set_timeline(obj_cusum.data)
|
38 |
|
39 |
+
# Set initial days and get in-control mean and standard deviation
|
40 |
+
obj_cusum.set_init_stats(init_days=30)
|
41 |
+
|
42 |
+
# Detects a change in the process
|
43 |
obj_cusum.change_detection(
|
|
|
44 |
normalized_ref_value=ref_value,
|
45 |
normalized_threshold=normalized_threshold,
|
46 |
)
|
47 |
|
48 |
self.assertEqual(
|
49 |
+
obj_cusum.S_lo[-1], 2.6, "Cumulative (negative) sum does not match."
|
50 |
)
|
51 |
|
52 |
def test_rpy2(self):
|
53 |
arl_1 = get_ARL_1_h_mu1_k(h=4, k=0.2996, mu1=1.2)
|
54 |
|
55 |
+
self.assertEqual(arl_1, 4.43, "Package rpy2 is not working properly")
|
56 |
|
57 |
|
58 |
if __name__ == "__main__":
|