diff --git a/.gitattributes b/.gitattributes index a6344aac8c09253b3b630fb776ae94478aa0275b..a737638ea6add4452b644ee0dd0d3669fb171642 100644 --- a/.gitattributes +++ b/.gitattributes @@ -33,3 +33,5 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text *.zip filter=lfs diff=lfs merge=lfs -text *.zst filter=lfs diff=lfs merge=lfs -text *tfevents* filter=lfs diff=lfs merge=lfs -text +assets/AIM-CU-Overview.drawio.png filter=lfs diff=lfs merge=lfs -text +docs/build/latex/aim-cu.pdf filter=lfs diff=lfs merge=lfs -text diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000000000000000000000000000000000..4df45eb4f7c7b8ed5da2bdcfdac6363620e0360f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,27 @@ +FROM ubuntu:22.04 + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt-get update && apt-get install -y software-properties-common dirmngr wget + +RUN apt-get update && apt-get install -y python3 python3-distutils python3-dev +RUN wget https://bootstrap.pypa.io/get-pip.py && python3 get-pip.py + +RUN wget -qO- https://cloud.r-project.org/bin/linux/ubuntu/marutter_pubkey.asc | tee -a /etc/apt/trusted.gpg.d/cran_ubuntu_key.asc +RUN add-apt-repository "deb https://cloud.r-project.org/bin/linux/ubuntu $(lsb_release -cs)-cran40/" +RUN apt-get install -y --no-install-recommends r-base r-base-dev + +# setup R configs +RUN echo "r <- getOption('repos'); r['CRAN'] <- 'http://cran.us.r-project.org'; options(repos = r);" > ~/.Rprofile +RUN Rscript -e "install.packages('ggplot2')" +RUN Rscript -e "install.packages('hexbin')" +RUN Rscript -e "install.packages('lazyeval')" +RUN Rscript -e "install.packages('cusumcharter')" +RUN Rscript -e "install.packages('RcppCNPy')" +RUN Rscript -e "install.packages('spc')" + +WORKDIR /app/src/package +COPY . /app/ + +RUN pip install --no-cache-dir --upgrade -r /app/requirements.txt + +CMD ["python3", "app.py"] \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..0e259d42c996742e9e3cba14c677129b2c1b6311 --- /dev/null +++ b/LICENSE @@ -0,0 +1,121 @@ +Creative Commons Legal Code + +CC0 1.0 Universal + + CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE + LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN + ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS + INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES + REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS + PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM + THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED + HEREUNDER. + +Statement of Purpose + +The laws of most jurisdictions throughout the world automatically confer +exclusive Copyright and Related Rights (defined below) upon the creator +and subsequent owner(s) (each and all, an "owner") of an original work of +authorship and/or a database (each, a "Work"). + +Certain owners wish to permanently relinquish those rights to a Work for +the purpose of contributing to a commons of creative, cultural and +scientific works ("Commons") that the public can reliably and without fear +of later claims of infringement build upon, modify, incorporate in other +works, reuse and redistribute as freely as possible in any form whatsoever +and for any purposes, including without limitation commercial purposes. +These owners may contribute to the Commons to promote the ideal of a free +culture and the further production of creative, cultural and scientific +works, or to gain reputation or greater distribution for their Work in +part through the use and efforts of others. + +For these and/or other purposes and motivations, and without any +expectation of additional consideration or compensation, the person +associating CC0 with a Work (the "Affirmer"), to the extent that he or she +is an owner of Copyright and Related Rights in the Work, voluntarily +elects to apply CC0 to the Work and publicly distribute the Work under its +terms, with knowledge of his or her Copyright and Related Rights in the +Work and the meaning and intended legal effect of CC0 on those rights. + +1. Copyright and Related Rights. A Work made available under CC0 may be +protected by copyright and related or neighboring rights ("Copyright and +Related Rights"). Copyright and Related Rights include, but are not +limited to, the following: + + i. the right to reproduce, adapt, distribute, perform, display, + communicate, and translate a Work; + ii. moral rights retained by the original author(s) and/or performer(s); +iii. publicity and privacy rights pertaining to a person's image or + likeness depicted in a Work; + iv. rights protecting against unfair competition in regards to a Work, + subject to the limitations in paragraph 4(a), below; + v. rights protecting the extraction, dissemination, use and reuse of data + in a Work; + vi. database rights (such as those arising under Directive 96/9/EC of the + European Parliament and of the Council of 11 March 1996 on the legal + protection of databases, and under any national implementation + thereof, including any amended or successor version of such + directive); and +vii. other similar, equivalent or corresponding rights throughout the + world based on applicable law or treaty, and any national + implementations thereof. + +2. Waiver. To the greatest extent permitted by, but not in contravention +of, applicable law, Affirmer hereby overtly, fully, permanently, +irrevocably and unconditionally waives, abandons, and surrenders all of +Affirmer's Copyright and Related Rights and associated claims and causes +of action, whether now known or unknown (including existing as well as +future claims and causes of action), in the Work (i) in all territories +worldwide, (ii) for the maximum duration provided by applicable law or +treaty (including future time extensions), (iii) in any current or future +medium and for any number of copies, and (iv) for any purpose whatsoever, +including without limitation commercial, advertising or promotional +purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each +member of the public at large and to the detriment of Affirmer's heirs and +successors, fully intending that such Waiver shall not be subject to +revocation, rescission, cancellation, termination, or any other legal or +equitable action to disrupt the quiet enjoyment of the Work by the public +as contemplated by Affirmer's express Statement of Purpose. + +3. Public License Fallback. Should any part of the Waiver for any reason +be judged legally invalid or ineffective under applicable law, then the +Waiver shall be preserved to the maximum extent permitted taking into +account Affirmer's express Statement of Purpose. In addition, to the +extent the Waiver is so judged Affirmer hereby grants to each affected +person a royalty-free, non transferable, non sublicensable, non exclusive, +irrevocable and unconditional license to exercise Affirmer's Copyright and +Related Rights in the Work (i) in all territories worldwide, (ii) for the +maximum duration provided by applicable law or treaty (including future +time extensions), (iii) in any current or future medium and for any number +of copies, and (iv) for any purpose whatsoever, including without +limitation commercial, advertising or promotional purposes (the +"License"). The License shall be deemed effective as of the date CC0 was +applied by Affirmer to the Work. Should any part of the License for any +reason be judged legally invalid or ineffective under applicable law, such +partial invalidity or ineffectiveness shall not invalidate the remainder +of the License, and in such case Affirmer hereby affirms that he or she +will not (i) exercise any of his or her remaining Copyright and Related +Rights in the Work or (ii) assert any associated claims and causes of +action with respect to the Work, in either case contrary to Affirmer's +express Statement of Purpose. + +4. Limitations and Disclaimers. + + a. No trademark or patent rights held by Affirmer are waived, abandoned, + surrendered, licensed or otherwise affected by this document. + b. Affirmer offers the Work as-is and makes no representations or + warranties of any kind concerning the Work, express, implied, + statutory or otherwise, including without limitation warranties of + title, merchantability, fitness for a particular purpose, non + infringement, or the absence of latent or other defects, accuracy, or + the present or absence of errors, whether or not discoverable, all to + the greatest extent permissible under applicable law. + c. Affirmer disclaims responsibility for clearing rights of other persons + that may apply to the Work or any use thereof, including without + limitation any person's Copyright and Related Rights in the Work. + Further, Affirmer disclaims responsibility for obtaining any necessary + consents, permissions or other rights required for any use of the + Work. + d. Affirmer understands and acknowledges that Creative Commons is not a + party to this document and has no duty or obligation with respect to + this CC0 or use of the Work. diff --git a/README.rst b/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..06565f759438168c1e80a3798d17a04ad2399335 --- /dev/null +++ b/README.rst @@ -0,0 +1,64 @@ +AIM-CU : A CUSUM-based tool for AI Monitoring +====== + +.. image:: assets/AIM-CU-Overview.drawio.png + :width: 800 + :align: center + :alt: AIM-CU flowchart + +Monitoring a clinically deployed AI device to detect performance drift is an essential step to +ensure the safety and effectiveness of AI. + +AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU). +AIM-CU computes: + +* The parameter choices for change-point detection based on an acceptable false alarm rate +* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices. + +Code execution +-------------- +Clone AIM-CU repository. + +.. code-block:: shell + + git clone https://github.com/DIDSR/AIM-CU.git + +Run the following commands to install required dependencies (Python = 3.10 is used). + +.. code-block:: shell + + apt-get -y install python3 + apt-get -y install pip + cd AIM-CU + pip install -r requirements.txt + +Run AIM-CU. + +.. code-block:: shell + + python3 app.py + +Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally. + +Example code execution +---------------------- +Example code can be run in a Jupyter Notebook after opening it with ``jupyter notebook`` command from ``/src/package`` directory. + +Demo +---- +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. + +Related References +------------------ +* 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, "Detecting performance drift in AI models for medical image analysis using CUSUM chart" (Journal Draft in-progress 2025) + +* Prathapan, S., Sahiner, B., Kadia, D., and Samala, R.K. 2025, AIM-CU: A statistical tool for AI Monitoring. In Medical Imaging 2025: Computer-Aided Diagnosis. SPIE. (Accepted) + +* Prathapan, S., Samala, R.K., Hadjiyski, N., D’Haese, P.F., Maldonado, F., Nguyen, P., Yesha, Y. and Sahiner, B., 2024, April. Quantifying input data drift in medical machine learning models by detecting change-points in time-series data. In Medical Imaging 2024: Computer-Aided Diagnosis (Vol. 12927, pp. 67-76). SPIE. https://doi.org/10.1117/12.3008771 + +* 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) + + +Disclaimer +---------- +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. diff --git a/assets/AIM-CU-Overview.drawio.png b/assets/AIM-CU-Overview.drawio.png new file mode 100644 index 0000000000000000000000000000000000000000..6b706d60fd2321bf1b21f91b6b036fea965e6701 --- /dev/null +++ b/assets/AIM-CU-Overview.drawio.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9a833bf26041308d91f66125c1f05c13280e86f1822d0d23a4148a127fc43599 +size 377113 diff --git a/assets/AIM-CU-Overview.drawio.xml b/assets/AIM-CU-Overview.drawio.xml new file mode 100644 index 0000000000000000000000000000000000000000..d4c54ea9ccb63a7722db1452745cd8c31d90f00c --- /dev/null +++ b/assets/AIM-CU-Overview.drawio.xml @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/assets/params.csv b/assets/params.csv new file mode 100644 index 0000000000000000000000000000000000000000..d19fa46b74419cbaf07828db2d9b6709b0359644 --- /dev/null +++ b/assets/params.csv @@ -0,0 +1,9 @@ +Parameter,Description +μ_in,"The mean of the performance metric when the process is in-control, i.e., when there is no performance drift" +ARL_0,Number of observations before the control chart signals a false detection +σ_in,The in-control standard deviation of the metric +ARL_1,Number of observations before the control chart signals a true detection +k,"The normalized reference value, which is related to the magnitude of change that one is interested in detecting. k = 0.5 is the default choice for detecting a unit standard deviation change" +S_hi,Cumulative sum of positive changes in the metric +h,The normalized threshold or control limit (default =4). This threshold determines when the control chart signals a detection +S_lo,Cumulative sum of negative changes in the metric \ No newline at end of file diff --git a/config/config.toml b/config/config.toml new file mode 100644 index 0000000000000000000000000000000000000000..bb5b5c00c3731f1df16e848a03c7dcbc5f88b2c4 --- /dev/null +++ b/config/config.toml @@ -0,0 +1,42 @@ +# paths to input files +[path_input] +path_df_metric = "config/spec-60-60.csv" + +# paths to output files +[path_output] +path_figure = "figure/" + +# primary colors +[color] +blue_005 = "#F3F9FC" +blue_020 = "#D0E4F0" +blue_040 = "#A3CAE1" +blue_060 = "#77B0D2" +blue_080 = "#4F96C4" +blue_100 = "#007CBA" + +# controls +[control] +save_figure = "false" + +# CUSUM parameters +[params_cusum] +list_ARL_0 = [50, 100, 150, 200, 300, 400, 500, 1000] +shift_in_mean = [ + 0.1, + 0.2, + 0.3, + 0.4, + 0.5, + 0.6, + 0.7, + 0.8, + 0.9, + 1.0, + 1.1, + 1.2, + 1.3, + 1.4, + 1.5, + 1.6, +] diff --git a/config/spec-60-60.csv b/config/spec-60-60.csv new file mode 100644 index 0000000000000000000000000000000000000000..778a036f4e4bf5ea18315ab4903900c26e139648 --- /dev/null +++ b/config/spec-60-60.csv @@ -0,0 +1,121 @@ +x,y +0,0.8426395939086294 +1,0.8913043478260869 +2,0.8826530612244898 +3,0.8308457711442786 +4,0.7679558011049724 +5,0.8444444444444444 +6,0.8306878306878307 +7,0.8308457711442786 +8,0.8936170212765957 +9,0.8138297872340425 +10,0.7747252747252747 +11,0.8052631578947368 +12,0.8090452261306532 +13,0.8317757009345794 +14,0.8958333333333334 +15,0.8306878306878307 +16,0.8556701030927835 +17,0.8387096774193549 +18,0.7894736842105263 +19,0.8563829787234043 +20,0.8186813186813187 +21,0.8306878306878307 +22,0.7918781725888325 +23,0.8823529411764706 +24,0.8737373737373737 +25,0.8666666666666667 +26,0.8518518518518519 +27,0.8659217877094972 +28,0.8232044198895028 +29,0.8764044943820225 +30,0.8167539267015707 +31,0.8478260869565217 +32,0.8363636363636363 +33,0.797752808988764 +34,0.8309859154929577 +35,0.875 +36,0.8 +37,0.8608247422680413 +38,0.8288770053475936 +39,0.8556149732620321 +40,0.8153846153846154 +41,0.859375 +42,0.8324607329842932 +43,0.9043062200956937 +44,0.8279569892473119 +45,0.8197674418604651 +46,0.7795698924731183 +47,0.8135593220338984 +48,0.8481675392670157 +49,0.8134715025906736 +50,0.7864583333333334 +51,0.8548387096774194 +52,0.8370786516853933 +53,0.7157360406091371 +54,0.8324607329842932 +55,0.8296703296703297 +56,0.8844221105527639 +57,0.7884615384615384 +58,0.935 +59,0.8840579710144928 +60,0.75 +61,0.8324607329842932 +62,0.7939698492462312 +63,0.7272727272727273 +64,0.8284313725490197 +65,0.7692307692307693 +66,0.8010204081632653 +67,0.8235294117647058 +68,0.7277486910994765 +69,0.775 +70,0.8361581920903954 +71,0.7959183673469388 +72,0.8489583333333334 +73,0.8465346534653465 +74,0.812807881773399 +75,0.7475247524752475 +76,0.8491620111731844 +77,0.6989247311827957 +78,0.7967914438502673 +79,0.7236180904522613 +80,0.746031746031746 +81,0.7371428571428571 +82,0.7839195979899497 +83,0.7921348314606742 +84,0.8258706467661692 +85,0.8121827411167513 +86,0.8258426966292135 +87,0.7675675675675676 +88,0.6666666666666666 +89,0.7872340425531915 +90,0.8325123152709359 +91,0.8247422680412371 +92,0.7619047619047619 +93,0.7967032967032966 +94,0.867816091954023 +95,0.8010471204188482 +96,0.625 +97,0.7684210526315789 +98,0.7409326424870466 +99,0.7593582887700535 +100,0.8041237113402062 +101,0.8160919540229885 +102,0.803030303030303 +103,0.6898395721925134 +104,0.7037037037037037 +105,0.8219895287958116 +106,0.8153846153846154 +107,0.712707182320442 +108,0.7548076923076923 +109,0.8258426966292135 +110,0.8 +111,0.7444444444444445 +112,0.7604166666666666 +113,0.7446808510638298 +114,0.7845303867403315 +115,0.7616279069767442 +116,0.7525773195876289 +117,0.7213930348258707 +118,0.8222222222222222 +119,0.817258883248731 diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..d0c3cbf1020d5c292abdedf27627c6abe25e2293 --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,20 @@ +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line, and also +# from the environment for the first two. +SPHINXOPTS ?= +SPHINXBUILD ?= sphinx-build +SOURCEDIR = source +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/docs/README.rst b/docs/README.rst new file mode 100644 index 0000000000000000000000000000000000000000..321509067bf78284b96c8053b52229773bdf7c7b --- /dev/null +++ b/docs/README.rst @@ -0,0 +1,26 @@ +Documentation +============= + +Read the documentation +---------------------- +Access the documentation from `index.html `_ + +Generate Sphinx documentation +----------------------------- +Run the below command from ``/src/package``. + +HTML format: + +.. code-block:: shell + + sphinx-build -M html ../../docs/source ../../docs/build --fail-on-warning + +As a PDF file: + +Required: Install latex - ``sudo apt-get install texlive-full`` + +.. code-block:: shell + + sphinx-build -M latexpdf ../../docs/source ../../docs/build --fail-on-warning + +Access it from `aim-cu.pdf `_ \ No newline at end of file diff --git a/docs/build/doctrees/environment.pickle b/docs/build/doctrees/environment.pickle new file mode 100644 index 0000000000000000000000000000000000000000..fbad7193c81c10c9966ec7016f6247b7f2b5126c --- /dev/null +++ b/docs/build/doctrees/environment.pickle @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:73a5f70cee490be573c5c2a1614594bb93b5aa232863c9f4004a876906fc4d13 +size 34605 diff --git a/docs/build/doctrees/index.doctree b/docs/build/doctrees/index.doctree new file mode 100644 index 0000000000000000000000000000000000000000..40a546567209beb621c74c6c4f74d7c9d32b4209 Binary files /dev/null and b/docs/build/doctrees/index.doctree differ diff --git a/docs/build/doctrees/ref_cusum.doctree b/docs/build/doctrees/ref_cusum.doctree new file mode 100644 index 0000000000000000000000000000000000000000..79491e984daefd871fb18a0800c56c90d12ef366 Binary files /dev/null and b/docs/build/doctrees/ref_cusum.doctree differ diff --git a/docs/build/doctrees/ref_method.doctree b/docs/build/doctrees/ref_method.doctree new file mode 100644 index 0000000000000000000000000000000000000000..137959a1e9c0e3f70337bd2b5c0870a9f2e9ec4e Binary files /dev/null and b/docs/build/doctrees/ref_method.doctree differ diff --git a/docs/build/doctrees/ref_theoretical.doctree b/docs/build/doctrees/ref_theoretical.doctree new file mode 100644 index 0000000000000000000000000000000000000000..8a5372ffb90273edfc90f61ca1bd57a9bbd0b076 Binary files /dev/null and b/docs/build/doctrees/ref_theoretical.doctree differ diff --git a/docs/build/doctrees/ref_utils.doctree b/docs/build/doctrees/ref_utils.doctree new file mode 100644 index 0000000000000000000000000000000000000000..4f5aac802d52f5b7147590f955d8c59515c04aa4 Binary files /dev/null and b/docs/build/doctrees/ref_utils.doctree differ diff --git a/docs/build/html/.buildinfo b/docs/build/html/.buildinfo new file mode 100644 index 0000000000000000000000000000000000000000..799adb032123a382ffbc148b996689c6dc5f79e2 --- /dev/null +++ b/docs/build/html/.buildinfo @@ -0,0 +1,4 @@ +# Sphinx build info version 1 +# This file records the configuration used when building these files. When it is not found, a full rebuild will be done. +config: d98e84fc2d439aaf1e5c362e015e369c +tags: 645f666f9bcd5a90fca523b33c5a78b7 diff --git a/docs/build/html/_sources/index.rst.txt b/docs/build/html/_sources/index.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..bcea0f64f0b1a5804fda25694d2447acf2c2ee12 --- /dev/null +++ b/docs/build/html/_sources/index.rst.txt @@ -0,0 +1,52 @@ +.. AIM-CU documentation master file, created by + sphinx-quickstart on Wed Nov 27 09:59:49 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +AIM-CU documentation +==================== + +A CUSUM-based tool for AI Monitoring + +AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU). AIM-CU computes: + +* The parameter choices for change-point detection based on an acceptable false alarm rate +* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices. + +Code execution +------------------ +Clone AIM-CU repository. + +.. code-block:: shell + + git clone https://github.com/DIDSR/AIM-CU.git + +Run the following commands to install required dependencies (Python = 3.10 is used). + +.. code-block:: shell + + apt-get -y install python3 + apt-get -y install pip + cd AIM-CU + pip install -r requirements.txt + +Run AIM-CU. + +.. code-block:: shell + + python3 app.py + +Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally. + +Demo +------------------ +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. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + ref_method + ref_cusum + ref_theoretical + ref_utils \ No newline at end of file diff --git a/docs/build/html/_sources/ref_cusum.rst.txt b/docs/build/html/_sources/ref_cusum.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..1d643a3359ce74c9756d3b4a5ae1d51d59cc4c29 --- /dev/null +++ b/docs/build/html/_sources/ref_cusum.rst.txt @@ -0,0 +1,5 @@ +CUSUM +===== + +.. automodule:: package.cusum + :members: \ No newline at end of file diff --git a/docs/build/html/_sources/ref_method.rst.txt b/docs/build/html/_sources/ref_method.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..dc977457222b6c074ef7bd843f8ac8a4f27d537e --- /dev/null +++ b/docs/build/html/_sources/ref_method.rst.txt @@ -0,0 +1,32 @@ +Methods +======= + +CUSUM parameters +---------------- + +.. csv-table:: CUSUM parameters + :file: ../../assets/params.csv + :header-rows: 1 + +CUSUM chart +----------- + +A two-sided CUSUM control chart computes the cumulative differences or +deviations of individual observations from the target mean (or +in-control mean, :math:`\mu_{in}`). The positive and negative cumulative +sums are calculated: + +.. math:: + + \\ S_{hi}(d) = max(0, S_{hi}(d-1) + x_d - \hat{\mu}_{in} - K) + \\ S_{lo}(d) = max(0, S_{lo}(d-1) - x_d + \hat{\mu}_{in} - K) + +where *d* denotes a unit of time, :math:`x_d` is the value of quantity +being monitored at time :math:`d`, :math:`\hat{\mu}_{in}` is the +in-control mean of :math:`x_d`, and :math:`K` is a "reference value" +related to the magnitude of change that one is interested in detecting. +:math:`S_{hi}` and :math:`S_{lo}` are the cumulative sum of positive and +negative changes. To detect a change in the observed values from the +in-control mean, the CUSUM scheme accumulates deviations that are +:math:`K` units away from the in-control mean. Let :math:`\sigma_{in}` +denote the in-control standard deviation of :math:`x_d`. \ No newline at end of file diff --git a/docs/build/html/_sources/ref_theoretical.rst.txt b/docs/build/html/_sources/ref_theoretical.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..3fc8048e19a2ef49d4393e40b2b77d2f2d5d52f6 --- /dev/null +++ b/docs/build/html/_sources/ref_theoretical.rst.txt @@ -0,0 +1,5 @@ +ARLTheoretical +============== + +.. automodule:: package.ARLTheoretical + :members: \ No newline at end of file diff --git a/docs/build/html/_sources/ref_utils.rst.txt b/docs/build/html/_sources/ref_utils.rst.txt new file mode 100644 index 0000000000000000000000000000000000000000..7eeb201a370e1cbdc0bb5200b5c761899a99cb54 --- /dev/null +++ b/docs/build/html/_sources/ref_utils.rst.txt @@ -0,0 +1,5 @@ +Utils +===== + +.. automodule:: package.utils + :members: \ No newline at end of file diff --git a/docs/build/html/_static/alabaster.css b/docs/build/html/_static/alabaster.css new file mode 100644 index 0000000000000000000000000000000000000000..d3207606f3c5605e03a8ca0a7cfb32206a14ad1e --- /dev/null +++ b/docs/build/html/_static/alabaster.css @@ -0,0 +1,663 @@ +/* -- page layout ----------------------------------------------------------- */ + +body { + font-family: Georgia, serif; + font-size: 17px; + background-color: #fff; + color: #000; + margin: 0; + padding: 0; +} + + +div.document { + width: 1200px; + margin: 30px auto 0 auto; +} + +div.documentwrapper { + float: left; + width: 100%; +} + +div.bodywrapper { + margin: 0 0 0 300px; +} + +div.sphinxsidebar { + width: 300px; + font-size: 14px; + line-height: 1.5; +} + +hr { + border: 1px solid #B1B4B6; +} + +div.body { + background-color: #fff; + color: #3E4349; + padding: 0 30px 0 30px; +} + +div.body > .section { + text-align: left; +} + +div.footer { + width: 1200px; + margin: 20px auto 30px auto; + font-size: 14px; + color: #888; + text-align: right; +} + +div.footer a { + color: #888; +} + +p.caption { + font-family: inherit; + font-size: inherit; +} + + +div.relations { + display: none; +} + + +div.sphinxsidebar { + max-height: 100%; + overflow-y: auto; +} + +div.sphinxsidebar a { + color: #444; + text-decoration: none; + border-bottom: 1px dotted #999; +} + +div.sphinxsidebar a:hover { + border-bottom: 1px solid #999; +} + +div.sphinxsidebarwrapper { + padding: 18px 10px; +} + +div.sphinxsidebarwrapper p.logo { + padding: 0; + margin: -10px 0 0 0px; + text-align: center; +} + +div.sphinxsidebarwrapper h1.logo { + margin-top: -10px; + text-align: center; + margin-bottom: 5px; + text-align: left; +} + +div.sphinxsidebarwrapper h1.logo-name { + margin-top: 0px; +} + +div.sphinxsidebarwrapper p.blurb { + margin-top: 0; + font-style: normal; +} + +div.sphinxsidebar h3, +div.sphinxsidebar h4 { + font-family: Georgia, serif; + color: #444; + font-size: 24px; + font-weight: normal; + margin: 0 0 5px 0; + padding: 0; +} + +div.sphinxsidebar h4 { + font-size: 20px; +} + +div.sphinxsidebar h3 a { + color: #444; +} + +div.sphinxsidebar p.logo a, +div.sphinxsidebar h3 a, +div.sphinxsidebar p.logo a:hover, +div.sphinxsidebar h3 a:hover { + border: none; +} + +div.sphinxsidebar p { + color: #555; + margin: 10px 0; +} + +div.sphinxsidebar ul { + margin: 10px 0; + padding: 0; + color: #000; +} + +div.sphinxsidebar ul li.toctree-l1 > a { + font-size: 120%; +} + +div.sphinxsidebar ul li.toctree-l2 > a { + font-size: 110%; +} + +div.sphinxsidebar input { + border: 1px solid #CCC; + font-family: Georgia, serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox { + margin: 1em 0; +} + +div.sphinxsidebar .search > div { + display: table-cell; +} + +div.sphinxsidebar hr { + border: none; + height: 1px; + color: #AAA; + background: #AAA; + + text-align: left; + margin-left: 0; + width: 50%; +} + +div.sphinxsidebar .badge { + border-bottom: none; +} + +div.sphinxsidebar .badge:hover { + border-bottom: none; +} + +/* To address an issue with donation coming after search */ +div.sphinxsidebar h3.donation { + margin-top: 10px; +} + +/* -- body styles ----------------------------------------------------------- */ + +a { + color: #004B6B; + text-decoration: underline; +} + +a:hover { + color: #6D4100; + text-decoration: underline; +} + +div.body h1, +div.body h2, +div.body h3, +div.body h4, +div.body h5, +div.body h6 { + font-family: Georgia, serif; + font-weight: normal; + margin: 30px 0px 10px 0px; + padding: 0; +} + +div.body h1 { margin-top: 0; padding-top: 0; font-size: 240%; } +div.body h2 { font-size: 180%; } +div.body h3 { font-size: 150%; } +div.body h4 { font-size: 130%; } +div.body h5 { font-size: 100%; } +div.body h6 { font-size: 100%; } + +a.headerlink { + color: #DDD; + padding: 0 4px; + text-decoration: none; +} + +a.headerlink:hover { + color: #444; + background: #EAEAEA; +} + +div.body p, div.body dd, div.body li { + line-height: 1.4em; +} + +div.admonition { + margin: 20px 0px; + padding: 10px 30px; + background-color: #EEE; + border: 1px solid #CCC; +} + +div.admonition tt.xref, div.admonition code.xref, div.admonition a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fafafa; +} + +div.admonition p.admonition-title { + font-family: Georgia, serif; + font-weight: normal; + font-size: 24px; + margin: 0 0 10px 0; + padding: 0; + line-height: 1; +} + +div.admonition p.last { + margin-bottom: 0; +} + +dt:target, .highlight { + background: #FAF3E8; +} + +div.warning { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.danger { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.error { + background-color: #FCC; + border: 1px solid #FAA; + -moz-box-shadow: 2px 2px 4px #D52C2C; + -webkit-box-shadow: 2px 2px 4px #D52C2C; + box-shadow: 2px 2px 4px #D52C2C; +} + +div.caution { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.attention { + background-color: #FCC; + border: 1px solid #FAA; +} + +div.important { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.note { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.tip { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.hint { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.seealso { + background-color: #EEE; + border: 1px solid #CCC; +} + +div.topic { + background-color: #EEE; +} + +p.admonition-title { + display: inline; +} + +p.admonition-title:after { + content: ":"; +} + +pre, tt, code { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; + font-size: 0.9em; +} + +.hll { + background-color: #FFC; + margin: 0 -12px; + padding: 0 12px; + display: block; +} + +img.screenshot { +} + +tt.descname, tt.descclassname, code.descname, code.descclassname { + font-size: 0.95em; +} + +tt.descname, code.descname { + padding-right: 0.08em; +} + +img.screenshot { + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils { + border: 1px solid #888; + -moz-box-shadow: 2px 2px 4px #EEE; + -webkit-box-shadow: 2px 2px 4px #EEE; + box-shadow: 2px 2px 4px #EEE; +} + +table.docutils td, table.docutils th { + border: 1px solid #888; + padding: 0.25em 0.7em; +} + +table.field-list, table.footnote { + border: none; + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + +table.footnote { + margin: 15px 0; + width: 100%; + border: 1px solid #EEE; + background: #FDFDFD; + font-size: 0.9em; +} + +table.footnote + table.footnote { + margin-top: -15px; + border-top: none; +} + +table.field-list th { + padding: 0 0.8em 0 0; +} + +table.field-list td { + padding: 0; +} + +table.field-list p { + margin-bottom: 0.8em; +} + +/* Cloned from + * https://github.com/sphinx-doc/sphinx/commit/ef60dbfce09286b20b7385333d63a60321784e68 + */ +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +table.footnote td.label { + width: .1px; + padding: 0.3em 0 0.3em 0.5em; +} + +table.footnote td { + padding: 0.3em 0.5em; +} + +dl { + margin-left: 0; + margin-right: 0; + margin-top: 0; + padding: 0; +} + +dl dd { + margin-left: 30px; +} + +blockquote { + margin: 0 0 0 30px; + padding: 0; +} + +ul, ol { + /* Matches the 30px from the narrow-screen "li > ul" selector below */ + margin: 10px 0 10px 30px; + padding: 0; +} + +pre { + background: unset; + padding: 7px 30px; + margin: 15px 0px; + line-height: 1.3em; +} + +div.viewcode-block:target { + background: #ffd; +} + +dl pre, blockquote pre, li pre { + margin-left: 0; + padding-left: 30px; +} + +tt, code { + background-color: #ecf0f3; + color: #222; + /* padding: 1px 2px; */ +} + +tt.xref, code.xref, a tt { + background-color: #FBFBFB; + border-bottom: 1px solid #fff; +} + +a.reference { + text-decoration: none; + border-bottom: 1px dotted #004B6B; +} + +a.reference:hover { + border-bottom: 1px solid #6D4100; +} + +/* Don't put an underline on images */ +a.image-reference, a.image-reference:hover { + border-bottom: none; +} + +a.footnote-reference { + text-decoration: none; + font-size: 0.7em; + vertical-align: top; + border-bottom: 1px dotted #004B6B; +} + +a.footnote-reference:hover { + border-bottom: 1px solid #6D4100; +} + +a:hover tt, a:hover code { + background: #EEE; +} + +@media screen and (max-width: 1200px) { + + body { + margin: 0; + padding: 20px 30px; + } + + div.documentwrapper { + float: none; + background: #fff; + margin-left: 0; + margin-top: 0; + margin-right: 0; + margin-bottom: 0; + } + + div.sphinxsidebar { + display: block; + float: none; + width: unset; + margin: 50px -30px -20px -30px; + padding: 10px 20px; + background: #333; + color: #FFF; + } + + div.sphinxsidebar h3, div.sphinxsidebar h4, div.sphinxsidebar p, + div.sphinxsidebar h3 a { + color: #fff; + } + + div.sphinxsidebar a { + color: #AAA; + } + + div.sphinxsidebar p.logo { + display: none; + } + + div.document { + width: 100%; + margin: 0; + } + + div.footer { + display: none; + } + + div.bodywrapper { + margin: 0; + } + + div.body { + min-height: 0; + min-width: auto; /* fixes width on small screens, breaks .hll */ + padding: 0; + } + + .hll { + /* "fixes" the breakage */ + width: max-content; + } + + .rtd_doc_footer { + display: none; + } + + .document { + width: auto; + } + + .footer { + width: auto; + } + + .github { + display: none; + } + + ul { + margin-left: 0; + } + + li > ul { + /* Matches the 30px from the "ul, ol" selector above */ + margin-left: 30px; + } +} + + +/* misc. */ + +.revsys-inline { + display: none!important; +} + +/* Hide ugly table cell borders in ..bibliography:: directive output */ +table.docutils.citation, table.docutils.citation td, table.docutils.citation th { + border: none; + /* Below needed in some edge cases; if not applied, bottom shadows appear */ + -moz-box-shadow: none; + -webkit-box-shadow: none; + box-shadow: none; +} + + +/* relbar */ + +.related { + line-height: 30px; + width: 100%; + font-size: 0.9rem; +} + +.related.top { + border-bottom: 1px solid #EEE; + margin-bottom: 20px; +} + +.related.bottom { + border-top: 1px solid #EEE; +} + +.related ul { + padding: 0; + margin: 0; + list-style: none; +} + +.related li { + display: inline; +} + +nav#rellinks { + float: right; +} + +nav#rellinks li+li:before { + content: "|"; +} + +nav#breadcrumbs li+li:before { + content: "\00BB"; +} + +/* Hide certain items when printing */ +@media print { + div.related { + display: none; + } +} + +img.github { + position: absolute; + top: 0; + border: 0; + right: 0; +} \ No newline at end of file diff --git a/docs/build/html/_static/basic.css b/docs/build/html/_static/basic.css new file mode 100644 index 0000000000000000000000000000000000000000..41a2f96ef5ea9d3db14a214b48d2f2d7ad4b0a96 --- /dev/null +++ b/docs/build/html/_static/basic.css @@ -0,0 +1,914 @@ +/* + * Sphinx stylesheet -- basic theme. + */ + +/* -- main layout ----------------------------------------------------------- */ + +div.clearer { + clear: both; +} + +div.section::after { + display: block; + content: ''; + clear: left; +} + +/* -- relbar ---------------------------------------------------------------- */ + +div.related { + width: 100%; + font-size: 90%; +} + +div.related h3 { + display: none; +} + +div.related ul { + margin: 0; + padding: 0 0 0 10px; + list-style: none; +} + +div.related li { + display: inline; +} + +div.related li.right { + float: right; + margin-right: 5px; +} + +/* -- sidebar --------------------------------------------------------------- */ + +div.sphinxsidebarwrapper { + padding: 10px 5px 0 10px; +} + +div.sphinxsidebar { + float: left; + width: 230px; + margin-left: -100%; + font-size: 90%; + word-wrap: break-word; + overflow-wrap : break-word; +} + +div.sphinxsidebar ul { + list-style: none; +} + +div.sphinxsidebar ul ul, +div.sphinxsidebar ul.want-points { + margin-left: 20px; + list-style: square; +} + +div.sphinxsidebar ul ul { + margin-top: 0; + margin-bottom: 0; +} + +div.sphinxsidebar form { + margin-top: 10px; +} + +div.sphinxsidebar input { + border: 1px solid #98dbcc; + font-family: sans-serif; + font-size: 1em; +} + +div.sphinxsidebar #searchbox form.search { + overflow: hidden; +} + +div.sphinxsidebar #searchbox input[type="text"] { + float: left; + width: 80%; + padding: 0.25em; + box-sizing: border-box; +} + +div.sphinxsidebar #searchbox input[type="submit"] { + float: left; + width: 20%; + border-left: none; + padding: 0.25em; + box-sizing: border-box; +} + + +img { + border: 0; + max-width: 100%; +} + +/* -- search page ----------------------------------------------------------- */ + +ul.search { + margin-top: 10px; +} + +ul.search li { + padding: 5px 0; +} + +ul.search li a { + font-weight: bold; +} + +ul.search li p.context { + color: #888; + margin: 2px 0 0 30px; + text-align: left; +} + +ul.keywordmatches li.goodmatch a { + font-weight: bold; +} + +/* -- index page ------------------------------------------------------------ */ + +table.contentstable { + width: 90%; + margin-left: auto; + margin-right: auto; +} + +table.contentstable p.biglink { + line-height: 150%; +} + +a.biglink { + font-size: 1.3em; +} + +span.linkdescr { + font-style: italic; + padding-top: 5px; + font-size: 90%; +} + +/* -- general index --------------------------------------------------------- */ + +table.indextable { + width: 100%; +} + +table.indextable td { + text-align: left; + vertical-align: top; +} + +table.indextable ul { + margin-top: 0; + margin-bottom: 0; + list-style-type: none; +} + +table.indextable > tbody > tr > td > ul { + padding-left: 0em; +} + +table.indextable tr.pcap { + height: 10px; +} + +table.indextable tr.cap { + margin-top: 10px; + background-color: #f2f2f2; +} + +img.toggler { + margin-right: 3px; + margin-top: 3px; + cursor: pointer; +} + +div.modindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +div.genindex-jumpbox { + border-top: 1px solid #ddd; + border-bottom: 1px solid #ddd; + margin: 1em 0 1em 0; + padding: 0.4em; +} + +/* -- domain module index --------------------------------------------------- */ + +table.modindextable td { + padding: 2px; + border-collapse: collapse; +} + +/* -- general body styles --------------------------------------------------- */ + +div.body { + min-width: inherit; + max-width: auto; +} + +div.body p, div.body dd, div.body li, div.body blockquote { + -moz-hyphens: auto; + -ms-hyphens: auto; + -webkit-hyphens: auto; + hyphens: auto; +} + +a.headerlink { + visibility: hidden; +} + +a:visited { + color: #551A8B; +} + +h1:hover > a.headerlink, +h2:hover > a.headerlink, +h3:hover > a.headerlink, +h4:hover > a.headerlink, +h5:hover > a.headerlink, +h6:hover > a.headerlink, +dt:hover > a.headerlink, +caption:hover > a.headerlink, +p.caption:hover > a.headerlink, +div.code-block-caption:hover > a.headerlink { + visibility: visible; +} + +div.body p.caption { + text-align: inherit; +} + +div.body td { + text-align: left; +} + +.first { + margin-top: 0 !important; +} + +p.rubric { + margin-top: 30px; + font-weight: bold; +} + +img.align-left, figure.align-left, .figure.align-left, object.align-left { + clear: left; + float: left; + margin-right: 1em; +} + +img.align-right, figure.align-right, .figure.align-right, object.align-right { + clear: right; + float: right; + margin-left: 1em; +} + +img.align-center, figure.align-center, .figure.align-center, object.align-center { + display: block; + margin-left: auto; + margin-right: auto; +} + +img.align-default, figure.align-default, .figure.align-default { + display: block; + margin-left: auto; + margin-right: auto; +} + +.align-left { + text-align: left; +} + +.align-center { + text-align: center; +} + +.align-default { + text-align: center; +} + +.align-right { + text-align: right; +} + +/* -- sidebars -------------------------------------------------------------- */ + +div.sidebar, +aside.sidebar { + margin: 0 0 0.5em 1em; + border: 1px solid #ddb; + padding: 7px; + background-color: #ffe; + width: 40%; + float: right; + clear: right; + overflow-x: auto; +} + +p.sidebar-title { + font-weight: bold; +} + +nav.contents, +aside.topic, +div.admonition, div.topic, blockquote { + clear: left; +} + +/* -- topics ---------------------------------------------------------------- */ + +nav.contents, +aside.topic, +div.topic { + border: 1px solid #ccc; + padding: 7px; + margin: 10px 0 10px 0; +} + +p.topic-title { + font-size: 1.1em; + font-weight: bold; + margin-top: 10px; +} + +/* -- admonitions ----------------------------------------------------------- */ + +div.admonition { + margin-top: 10px; + margin-bottom: 10px; + padding: 7px; +} + +div.admonition dt { + font-weight: bold; +} + +p.admonition-title { + margin: 0px 10px 5px 0px; + font-weight: bold; +} + +div.body p.centered { + text-align: center; + margin-top: 25px; +} + +/* -- content of sidebars/topics/admonitions -------------------------------- */ + +div.sidebar > :last-child, +aside.sidebar > :last-child, +nav.contents > :last-child, +aside.topic > :last-child, +div.topic > :last-child, +div.admonition > :last-child { + margin-bottom: 0; +} + +div.sidebar::after, +aside.sidebar::after, +nav.contents::after, +aside.topic::after, +div.topic::after, +div.admonition::after, +blockquote::after { + display: block; + content: ''; + clear: both; +} + +/* -- tables ---------------------------------------------------------------- */ + +table.docutils { + margin-top: 10px; + margin-bottom: 10px; + border: 0; + border-collapse: collapse; +} + +table.align-center { + margin-left: auto; + margin-right: auto; +} + +table.align-default { + margin-left: auto; + margin-right: auto; +} + +table caption span.caption-number { + font-style: italic; +} + +table caption span.caption-text { +} + +table.docutils td, table.docutils th { + padding: 1px 8px 1px 5px; + border-top: 0; + border-left: 0; + border-right: 0; + border-bottom: 1px solid #aaa; +} + +th { + text-align: left; + padding-right: 5px; +} + +table.citation { + border-left: solid 1px gray; + margin-left: 1px; +} + +table.citation td { + border-bottom: none; +} + +th > :first-child, +td > :first-child { + margin-top: 0px; +} + +th > :last-child, +td > :last-child { + margin-bottom: 0px; +} + +/* -- figures --------------------------------------------------------------- */ + +div.figure, figure { + margin: 0.5em; + padding: 0.5em; +} + +div.figure p.caption, figcaption { + padding: 0.3em; +} + +div.figure p.caption span.caption-number, +figcaption span.caption-number { + font-style: italic; +} + +div.figure p.caption span.caption-text, +figcaption span.caption-text { +} + +/* -- field list styles ----------------------------------------------------- */ + +table.field-list td, table.field-list th { + border: 0 !important; +} + +.field-list ul { + margin: 0; + padding-left: 1em; +} + +.field-list p { + margin: 0; +} + +.field-name { + -moz-hyphens: manual; + -ms-hyphens: manual; + -webkit-hyphens: manual; + hyphens: manual; +} + +/* -- hlist styles ---------------------------------------------------------- */ + +table.hlist { + margin: 1em 0; +} + +table.hlist td { + vertical-align: top; +} + +/* -- object description styles --------------------------------------------- */ + +.sig { + font-family: 'Consolas', 'Menlo', 'DejaVu Sans Mono', 'Bitstream Vera Sans Mono', monospace; +} + +.sig-name, code.descname { + background-color: transparent; + font-weight: bold; +} + +.sig-name { + font-size: 1.1em; +} + +code.descname { + font-size: 1.2em; +} + +.sig-prename, code.descclassname { + background-color: transparent; +} + +.optional { + font-size: 1.3em; +} + +.sig-paren { + font-size: larger; +} + +.sig-param.n { + font-style: italic; +} + +/* C++ specific styling */ + +.sig-inline.c-texpr, +.sig-inline.cpp-texpr { + font-family: unset; +} + +.sig.c .k, .sig.c .kt, +.sig.cpp .k, .sig.cpp .kt { + color: #0033B3; +} + +.sig.c .m, +.sig.cpp .m { + color: #1750EB; +} + +.sig.c .s, .sig.c .sc, +.sig.cpp .s, .sig.cpp .sc { + color: #067D17; +} + + +/* -- other body styles ----------------------------------------------------- */ + +ol.arabic { + list-style: decimal; +} + +ol.loweralpha { + list-style: lower-alpha; +} + +ol.upperalpha { + list-style: upper-alpha; +} + +ol.lowerroman { + list-style: lower-roman; +} + +ol.upperroman { + list-style: upper-roman; +} + +:not(li) > ol > li:first-child > :first-child, +:not(li) > ul > li:first-child > :first-child { + margin-top: 0px; +} + +:not(li) > ol > li:last-child > :last-child, +:not(li) > ul > li:last-child > :last-child { + margin-bottom: 0px; +} + +ol.simple ol p, +ol.simple ul p, +ul.simple ol p, +ul.simple ul p { + margin-top: 0; +} + +ol.simple > li:not(:first-child) > p, +ul.simple > li:not(:first-child) > p { + margin-top: 0; +} + +ol.simple p, +ul.simple p { + margin-bottom: 0; +} + +aside.footnote > span, +div.citation > span { + float: left; +} +aside.footnote > span:last-of-type, +div.citation > span:last-of-type { + padding-right: 0.5em; +} +aside.footnote > p { + margin-left: 2em; +} +div.citation > p { + margin-left: 4em; +} +aside.footnote > p:last-of-type, +div.citation > p:last-of-type { + margin-bottom: 0em; +} +aside.footnote > p:last-of-type:after, +div.citation > p:last-of-type:after { + content: ""; + clear: both; +} + +dl.field-list { + display: grid; + grid-template-columns: fit-content(30%) auto; +} + +dl.field-list > dt { + font-weight: bold; + word-break: break-word; + padding-left: 0.5em; + padding-right: 5px; +} + +dl.field-list > dd { + padding-left: 0.5em; + margin-top: 0em; + margin-left: 0em; + margin-bottom: 0em; +} + +dl { + margin-bottom: 15px; +} + +dd > :first-child { + margin-top: 0px; +} + +dd ul, dd table { + margin-bottom: 10px; +} + +dd { + margin-top: 3px; + margin-bottom: 10px; + margin-left: 30px; +} + +.sig dd { + margin-top: 0px; + margin-bottom: 0px; +} + +.sig dl { + margin-top: 0px; + margin-bottom: 0px; +} + +dl > dd:last-child, +dl > dd:last-child > :last-child { + margin-bottom: 0; +} + +dt:target, span.highlighted { + background-color: #fbe54e; +} + +rect.highlighted { + fill: #fbe54e; +} + +dl.glossary dt { + font-weight: bold; + font-size: 1.1em; +} + +.versionmodified { + font-style: italic; +} + +.system-message { + background-color: #fda; + padding: 5px; + border: 3px solid red; +} + +.footnote:target { + background-color: #ffa; +} + +.line-block { + display: block; + margin-top: 1em; + margin-bottom: 1em; +} + +.line-block .line-block { + margin-top: 0; + margin-bottom: 0; + margin-left: 1.5em; +} + +.guilabel, .menuselection { + font-family: sans-serif; +} + +.accelerator { + text-decoration: underline; +} + +.classifier { + font-style: oblique; +} + +.classifier:before { + font-style: normal; + margin: 0 0.5em; + content: ":"; + display: inline-block; +} + +abbr, acronym { + border-bottom: dotted 1px; + cursor: help; +} + +.translated { + background-color: rgba(207, 255, 207, 0.2) +} + +.untranslated { + background-color: rgba(255, 207, 207, 0.2) +} + +/* -- code displays --------------------------------------------------------- */ + +pre { + overflow: auto; + overflow-y: hidden; /* fixes display issues on Chrome browsers */ +} + +pre, div[class*="highlight-"] { + clear: both; +} + +span.pre { + -moz-hyphens: none; + -ms-hyphens: none; + -webkit-hyphens: none; + hyphens: none; + white-space: nowrap; +} + +div[class*="highlight-"] { + margin: 1em 0; +} + +td.linenos pre { + border: 0; + background-color: transparent; + color: #aaa; +} + +table.highlighttable { + display: block; +} + +table.highlighttable tbody { + display: block; +} + +table.highlighttable tr { + display: flex; +} + +table.highlighttable td { + margin: 0; + padding: 0; +} + +table.highlighttable td.linenos { + padding-right: 0.5em; +} + +table.highlighttable td.code { + flex: 1; + overflow: hidden; +} + +.highlight .hll { + display: block; +} + +div.highlight pre, +table.highlighttable pre { + margin: 0; +} + +div.code-block-caption + div { + margin-top: 0; +} + +div.code-block-caption { + margin-top: 1em; + padding: 2px 5px; + font-size: small; +} + +div.code-block-caption code { + background-color: transparent; +} + +table.highlighttable td.linenos, +span.linenos, +div.highlight span.gp { /* gp: Generic.Prompt */ + user-select: none; + -webkit-user-select: text; /* Safari fallback only */ + -webkit-user-select: none; /* Chrome/Safari */ + -moz-user-select: none; /* Firefox */ + -ms-user-select: none; /* IE10+ */ +} + +div.code-block-caption span.caption-number { + padding: 0.1em 0.3em; + font-style: italic; +} + +div.code-block-caption span.caption-text { +} + +div.literal-block-wrapper { + margin: 1em 0; +} + +code.xref, a code { + background-color: transparent; + font-weight: bold; +} + +h1 code, h2 code, h3 code, h4 code, h5 code, h6 code { + background-color: transparent; +} + +.viewcode-link { + float: right; +} + +.viewcode-back { + float: right; + font-family: sans-serif; +} + +div.viewcode-block:target { + margin: -1px -10px; + padding: 0 10px; +} + +/* -- math display ---------------------------------------------------------- */ + +img.math { + vertical-align: middle; +} + +div.body div.math p { + text-align: center; +} + +span.eqno { + float: right; +} + +span.eqno a.headerlink { + position: absolute; + z-index: 1; +} + +div.math:hover a.headerlink { + visibility: visible; +} + +/* -- printout stylesheet --------------------------------------------------- */ + +@media print { + div.document, + div.documentwrapper, + div.bodywrapper { + margin: 0 !important; + width: 100%; + } + + div.sphinxsidebar, + div.related, + div.footer, + #top-link { + display: none; + } +} \ No newline at end of file diff --git a/docs/build/html/_static/custom.css b/docs/build/html/_static/custom.css new file mode 100644 index 0000000000000000000000000000000000000000..2a924f1d6a8bc930c5296bdb2d5c2d3e39b04a1c --- /dev/null +++ b/docs/build/html/_static/custom.css @@ -0,0 +1 @@ +/* This file intentionally left blank. */ diff --git a/docs/build/html/_static/doctools.js b/docs/build/html/_static/doctools.js new file mode 100644 index 0000000000000000000000000000000000000000..0398ebb9f03db6e89df8022033b81923c82112fa --- /dev/null +++ b/docs/build/html/_static/doctools.js @@ -0,0 +1,149 @@ +/* + * Base JavaScript utilities for all Sphinx HTML documentation. + */ +"use strict"; + +const BLACKLISTED_KEY_CONTROL_ELEMENTS = new Set([ + "TEXTAREA", + "INPUT", + "SELECT", + "BUTTON", +]); + +const _ready = (callback) => { + if (document.readyState !== "loading") { + callback(); + } else { + document.addEventListener("DOMContentLoaded", callback); + } +}; + +/** + * Small JavaScript module for the documentation. + */ +const Documentation = { + init: () => { + Documentation.initDomainIndexTable(); + Documentation.initOnKeyListeners(); + }, + + /** + * i18n support + */ + TRANSLATIONS: {}, + PLURAL_EXPR: (n) => (n === 1 ? 0 : 1), + LOCALE: "unknown", + + // gettext and ngettext don't access this so that the functions + // can safely bound to a different name (_ = Documentation.gettext) + gettext: (string) => { + const translated = Documentation.TRANSLATIONS[string]; + switch (typeof translated) { + case "undefined": + return string; // no translation + case "string": + return translated; // translation exists + default: + return translated[0]; // (singular, plural) translation tuple exists + } + }, + + ngettext: (singular, plural, n) => { + const translated = Documentation.TRANSLATIONS[singular]; + if (typeof translated !== "undefined") + return translated[Documentation.PLURAL_EXPR(n)]; + return n === 1 ? singular : plural; + }, + + addTranslations: (catalog) => { + Object.assign(Documentation.TRANSLATIONS, catalog.messages); + Documentation.PLURAL_EXPR = new Function( + "n", + `return (${catalog.plural_expr})` + ); + Documentation.LOCALE = catalog.locale; + }, + + /** + * helper function to focus on search bar + */ + focusSearchBar: () => { + document.querySelectorAll("input[name=q]")[0]?.focus(); + }, + + /** + * Initialise the domain index toggle buttons + */ + initDomainIndexTable: () => { + const toggler = (el) => { + const idNumber = el.id.substr(7); + const toggledRows = document.querySelectorAll(`tr.cg-${idNumber}`); + if (el.src.substr(-9) === "minus.png") { + el.src = `${el.src.substr(0, el.src.length - 9)}plus.png`; + toggledRows.forEach((el) => (el.style.display = "none")); + } else { + el.src = `${el.src.substr(0, el.src.length - 8)}minus.png`; + toggledRows.forEach((el) => (el.style.display = "")); + } + }; + + const togglerElements = document.querySelectorAll("img.toggler"); + togglerElements.forEach((el) => + el.addEventListener("click", (event) => toggler(event.currentTarget)) + ); + togglerElements.forEach((el) => (el.style.display = "")); + if (DOCUMENTATION_OPTIONS.COLLAPSE_INDEX) togglerElements.forEach(toggler); + }, + + initOnKeyListeners: () => { + // only install a listener if it is really needed + if ( + !DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS && + !DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS + ) + return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.altKey || event.ctrlKey || event.metaKey) return; + + if (!event.shiftKey) { + switch (event.key) { + case "ArrowLeft": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const prevLink = document.querySelector('link[rel="prev"]'); + if (prevLink && prevLink.href) { + window.location.href = prevLink.href; + event.preventDefault(); + } + break; + case "ArrowRight": + if (!DOCUMENTATION_OPTIONS.NAVIGATION_WITH_KEYS) break; + + const nextLink = document.querySelector('link[rel="next"]'); + if (nextLink && nextLink.href) { + window.location.href = nextLink.href; + event.preventDefault(); + } + break; + } + } + + // some keyboard layouts may need Shift to get / + switch (event.key) { + case "/": + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) break; + Documentation.focusSearchBar(); + event.preventDefault(); + } + }); + }, +}; + +// quick alias for translations +const _ = Documentation.gettext; + +_ready(Documentation.init); diff --git a/docs/build/html/_static/documentation_options.js b/docs/build/html/_static/documentation_options.js new file mode 100644 index 0000000000000000000000000000000000000000..89435bb41ad217e5e5f81a327e3da5f34c80bccc --- /dev/null +++ b/docs/build/html/_static/documentation_options.js @@ -0,0 +1,13 @@ +const DOCUMENTATION_OPTIONS = { + VERSION: '1.0.0', + LANGUAGE: 'en', + COLLAPSE_INDEX: false, + BUILDER: 'html', + FILE_SUFFIX: '.html', + LINK_SUFFIX: '.html', + HAS_SOURCE: true, + SOURCELINK_SUFFIX: '.txt', + NAVIGATION_WITH_KEYS: false, + SHOW_SEARCH_SUMMARY: true, + ENABLE_SEARCH_SHORTCUTS: true, +}; \ No newline at end of file diff --git a/docs/build/html/_static/file.png b/docs/build/html/_static/file.png new file mode 100644 index 0000000000000000000000000000000000000000..a858a410e4faa62ce324d814e4b816fff83a6fb3 Binary files /dev/null and b/docs/build/html/_static/file.png differ diff --git a/docs/build/html/_static/github-banner.svg b/docs/build/html/_static/github-banner.svg new file mode 100644 index 0000000000000000000000000000000000000000..c47d9dc0cdc8e7b73b7274b07ac70e79437455ca --- /dev/null +++ b/docs/build/html/_static/github-banner.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/docs/build/html/_static/language_data.js b/docs/build/html/_static/language_data.js new file mode 100644 index 0000000000000000000000000000000000000000..c7fe6c6fafad656c3aa8bea99e39386ad603b964 --- /dev/null +++ b/docs/build/html/_static/language_data.js @@ -0,0 +1,192 @@ +/* + * This script contains the language-specific data used by searchtools.js, + * namely the list of stopwords, stemmer, scorer and splitter. + */ + +var stopwords = ["a", "and", "are", "as", "at", "be", "but", "by", "for", "if", "in", "into", "is", "it", "near", "no", "not", "of", "on", "or", "such", "that", "the", "their", "then", "there", "these", "they", "this", "to", "was", "will", "with"]; + + +/* Non-minified version is copied as a separate JS file, if available */ + +/** + * Porter Stemmer + */ +var Stemmer = function() { + + var step2list = { + ational: 'ate', + tional: 'tion', + enci: 'ence', + anci: 'ance', + izer: 'ize', + bli: 'ble', + alli: 'al', + entli: 'ent', + eli: 'e', + ousli: 'ous', + ization: 'ize', + ation: 'ate', + ator: 'ate', + alism: 'al', + iveness: 'ive', + fulness: 'ful', + ousness: 'ous', + aliti: 'al', + iviti: 'ive', + biliti: 'ble', + logi: 'log' + }; + + var step3list = { + icate: 'ic', + ative: '', + alize: 'al', + iciti: 'ic', + ical: 'ic', + ful: '', + ness: '' + }; + + var c = "[^aeiou]"; // consonant + var v = "[aeiouy]"; // vowel + var C = c + "[^aeiouy]*"; // consonant sequence + var V = v + "[aeiou]*"; // vowel sequence + + var mgr0 = "^(" + C + ")?" + V + C; // [C]VC... is m>0 + var meq1 = "^(" + C + ")?" + V + C + "(" + V + ")?$"; // [C]VC[V] is m=1 + var mgr1 = "^(" + C + ")?" + V + C + V + C; // [C]VCVC... is m>1 + var s_v = "^(" + C + ")?" + v; // vowel in stem + + this.stemWord = function (w) { + var stem; + var suffix; + var firstch; + var origword = w; + + if (w.length < 3) + return w; + + var re; + var re2; + var re3; + var re4; + + firstch = w.substr(0,1); + if (firstch == "y") + w = firstch.toUpperCase() + w.substr(1); + + // Step 1a + re = /^(.+?)(ss|i)es$/; + re2 = /^(.+?)([^s])s$/; + + if (re.test(w)) + w = w.replace(re,"$1$2"); + else if (re2.test(w)) + w = w.replace(re2,"$1$2"); + + // Step 1b + re = /^(.+?)eed$/; + re2 = /^(.+?)(ed|ing)$/; + if (re.test(w)) { + var fp = re.exec(w); + re = new RegExp(mgr0); + if (re.test(fp[1])) { + re = /.$/; + w = w.replace(re,""); + } + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1]; + re2 = new RegExp(s_v); + if (re2.test(stem)) { + w = stem; + re2 = /(at|bl|iz)$/; + re3 = new RegExp("([^aeiouylsz])\\1$"); + re4 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re2.test(w)) + w = w + "e"; + else if (re3.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + else if (re4.test(w)) + w = w + "e"; + } + } + + // Step 1c + re = /^(.+?)y$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(s_v); + if (re.test(stem)) + w = stem + "i"; + } + + // Step 2 + re = /^(.+?)(ational|tional|enci|anci|izer|bli|alli|entli|eli|ousli|ization|ation|ator|alism|iveness|fulness|ousness|aliti|iviti|biliti|logi)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step2list[suffix]; + } + + // Step 3 + re = /^(.+?)(icate|ative|alize|iciti|ical|ful|ness)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + suffix = fp[2]; + re = new RegExp(mgr0); + if (re.test(stem)) + w = stem + step3list[suffix]; + } + + // Step 4 + re = /^(.+?)(al|ance|ence|er|ic|able|ible|ant|ement|ment|ent|ou|ism|ate|iti|ous|ive|ize)$/; + re2 = /^(.+?)(s|t)(ion)$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + if (re.test(stem)) + w = stem; + } + else if (re2.test(w)) { + var fp = re2.exec(w); + stem = fp[1] + fp[2]; + re2 = new RegExp(mgr1); + if (re2.test(stem)) + w = stem; + } + + // Step 5 + re = /^(.+?)e$/; + if (re.test(w)) { + var fp = re.exec(w); + stem = fp[1]; + re = new RegExp(mgr1); + re2 = new RegExp(meq1); + re3 = new RegExp("^" + C + v + "[^aeiouwxy]$"); + if (re.test(stem) || (re2.test(stem) && !(re3.test(stem)))) + w = stem; + } + re = /ll$/; + re2 = new RegExp(mgr1); + if (re.test(w) && re2.test(w)) { + re = /.$/; + w = w.replace(re,""); + } + + // and turn initial Y back to y + if (firstch == "y") + w = firstch.toLowerCase() + w.substr(1); + return w; + } +} + diff --git a/docs/build/html/_static/minus.png b/docs/build/html/_static/minus.png new file mode 100644 index 0000000000000000000000000000000000000000..d96755fdaf8bb2214971e0db9c1fd3077d7c419d Binary files /dev/null and b/docs/build/html/_static/minus.png differ diff --git a/docs/build/html/_static/plus.png b/docs/build/html/_static/plus.png new file mode 100644 index 0000000000000000000000000000000000000000..7107cec93a979b9a5f64843235a16651d563ce2d Binary files /dev/null and b/docs/build/html/_static/plus.png differ diff --git a/docs/build/html/_static/pygments.css b/docs/build/html/_static/pygments.css new file mode 100644 index 0000000000000000000000000000000000000000..9392ddcb46058ce1d7bb9f93a62080d46f06ca40 --- /dev/null +++ b/docs/build/html/_static/pygments.css @@ -0,0 +1,84 @@ +pre { line-height: 125%; } +td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; } +td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; } +.highlight .hll { background-color: #ffffcc } +.highlight { background: #f8f8f8; } +.highlight .c { color: #8F5902; font-style: italic } /* Comment */ +.highlight .err { color: #A40000; border: 1px solid #EF2929 } /* Error */ +.highlight .g { color: #000 } /* Generic */ +.highlight .k { color: #004461; font-weight: bold } /* Keyword */ +.highlight .l { color: #000 } /* Literal */ +.highlight .n { color: #000 } /* Name */ +.highlight .o { color: #582800 } /* Operator */ +.highlight .x { color: #000 } /* Other */ +.highlight .p { color: #000; font-weight: bold } /* Punctuation */ +.highlight .ch { color: #8F5902; font-style: italic } /* Comment.Hashbang */ +.highlight .cm { color: #8F5902; font-style: italic } /* Comment.Multiline */ +.highlight .cp { color: #8F5902 } /* Comment.Preproc */ +.highlight .cpf { color: #8F5902; font-style: italic } /* Comment.PreprocFile */ +.highlight .c1 { color: #8F5902; font-style: italic } /* Comment.Single */ +.highlight .cs { color: #8F5902; font-style: italic } /* Comment.Special */ +.highlight .gd { color: #A40000 } /* Generic.Deleted */ +.highlight .ge { color: #000; font-style: italic } /* Generic.Emph */ +.highlight .ges { color: #000 } /* Generic.EmphStrong */ +.highlight .gr { color: #EF2929 } /* Generic.Error */ +.highlight .gh { color: #000080; font-weight: bold } /* Generic.Heading */ +.highlight .gi { color: #00A000 } /* Generic.Inserted */ +.highlight .go { color: #888 } /* Generic.Output */ +.highlight .gp { color: #745334 } /* Generic.Prompt */ +.highlight .gs { color: #000; font-weight: bold } /* Generic.Strong */ +.highlight .gu { color: #800080; font-weight: bold } /* Generic.Subheading */ +.highlight .gt { color: #A40000; font-weight: bold } /* Generic.Traceback */ +.highlight .kc { color: #004461; font-weight: bold } /* Keyword.Constant */ +.highlight .kd { color: #004461; font-weight: bold } /* Keyword.Declaration */ +.highlight .kn { color: #004461; font-weight: bold } /* Keyword.Namespace */ +.highlight .kp { color: #004461; font-weight: bold } /* Keyword.Pseudo */ +.highlight .kr { color: #004461; font-weight: bold } /* Keyword.Reserved */ +.highlight .kt { color: #004461; font-weight: bold } /* Keyword.Type */ +.highlight .ld { color: #000 } /* Literal.Date */ +.highlight .m { color: #900 } /* Literal.Number */ +.highlight .s { color: #4E9A06 } /* Literal.String */ +.highlight .na { color: #C4A000 } /* Name.Attribute */ +.highlight .nb { color: #004461 } /* Name.Builtin */ +.highlight .nc { color: #000 } /* Name.Class */ +.highlight .no { color: #000 } /* Name.Constant */ +.highlight .nd { color: #888 } /* Name.Decorator */ +.highlight .ni { color: #CE5C00 } /* Name.Entity */ +.highlight .ne { color: #C00; font-weight: bold } /* Name.Exception */ +.highlight .nf { color: #000 } /* Name.Function */ +.highlight .nl { color: #F57900 } /* Name.Label */ +.highlight .nn { color: #000 } /* Name.Namespace */ +.highlight .nx { color: #000 } /* Name.Other */ +.highlight .py { color: #000 } /* Name.Property */ +.highlight .nt { color: #004461; font-weight: bold } /* Name.Tag */ +.highlight .nv { color: #000 } /* Name.Variable */ +.highlight .ow { color: #004461; font-weight: bold } /* Operator.Word */ +.highlight .pm { color: #000; font-weight: bold } /* Punctuation.Marker */ +.highlight .w { color: #F8F8F8 } /* Text.Whitespace */ +.highlight .mb { color: #900 } /* Literal.Number.Bin */ +.highlight .mf { color: #900 } /* Literal.Number.Float */ +.highlight .mh { color: #900 } /* Literal.Number.Hex */ +.highlight .mi { color: #900 } /* Literal.Number.Integer */ +.highlight .mo { color: #900 } /* Literal.Number.Oct */ +.highlight .sa { color: #4E9A06 } /* Literal.String.Affix */ +.highlight .sb { color: #4E9A06 } /* Literal.String.Backtick */ +.highlight .sc { color: #4E9A06 } /* Literal.String.Char */ +.highlight .dl { color: #4E9A06 } /* Literal.String.Delimiter */ +.highlight .sd { color: #8F5902; font-style: italic } /* Literal.String.Doc */ +.highlight .s2 { color: #4E9A06 } /* Literal.String.Double */ +.highlight .se { color: #4E9A06 } /* Literal.String.Escape */ +.highlight .sh { color: #4E9A06 } /* Literal.String.Heredoc */ +.highlight .si { color: #4E9A06 } /* Literal.String.Interpol */ +.highlight .sx { color: #4E9A06 } /* Literal.String.Other */ +.highlight .sr { color: #4E9A06 } /* Literal.String.Regex */ +.highlight .s1 { color: #4E9A06 } /* Literal.String.Single */ +.highlight .ss { color: #4E9A06 } /* Literal.String.Symbol */ +.highlight .bp { color: #3465A4 } /* Name.Builtin.Pseudo */ +.highlight .fm { color: #000 } /* Name.Function.Magic */ +.highlight .vc { color: #000 } /* Name.Variable.Class */ +.highlight .vg { color: #000 } /* Name.Variable.Global */ +.highlight .vi { color: #000 } /* Name.Variable.Instance */ +.highlight .vm { color: #000 } /* Name.Variable.Magic */ +.highlight .il { color: #900 } /* Literal.Number.Integer.Long */ \ No newline at end of file diff --git a/docs/build/html/_static/searchtools.js b/docs/build/html/_static/searchtools.js new file mode 100644 index 0000000000000000000000000000000000000000..2c774d17aff4b1efe084b91c7feea0c5e88acf4f --- /dev/null +++ b/docs/build/html/_static/searchtools.js @@ -0,0 +1,632 @@ +/* + * Sphinx JavaScript utilities for the full-text search. + */ +"use strict"; + +/** + * Simple result scoring code. + */ +if (typeof Scorer === "undefined") { + var Scorer = { + // Implement the following function to further tweak the score for each result + // The function takes a result array [docname, title, anchor, descr, score, filename] + // and returns the new score. + /* + score: result => { + const [docname, title, anchor, descr, score, filename, kind] = result + return score + }, + */ + + // query matches the full name of an object + objNameMatch: 11, + // or matches in the last dotted part of the object name + objPartialMatch: 6, + // Additive scores depending on the priority of the object + objPrio: { + 0: 15, // used to be importantResults + 1: 5, // used to be objectResults + 2: -5, // used to be unimportantResults + }, + // Used when the priority is not in the mapping. + objPrioDefault: 0, + + // query found in title + title: 15, + partialTitle: 7, + // query found in terms + term: 5, + partialTerm: 2, + }; +} + +// Global search result kind enum, used by themes to style search results. +class SearchResultKind { + static get index() { return "index"; } + static get object() { return "object"; } + static get text() { return "text"; } + static get title() { return "title"; } +} + +const _removeChildren = (element) => { + while (element && element.lastChild) element.removeChild(element.lastChild); +}; + +/** + * See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions#escaping + */ +const _escapeRegExp = (string) => + string.replace(/[.*+\-?^${}()|[\]\\]/g, "\\$&"); // $& means the whole matched string + +const _displayItem = (item, searchTerms, highlightTerms) => { + const docBuilder = DOCUMENTATION_OPTIONS.BUILDER; + const docFileSuffix = DOCUMENTATION_OPTIONS.FILE_SUFFIX; + const docLinkSuffix = DOCUMENTATION_OPTIONS.LINK_SUFFIX; + const showSearchSummary = DOCUMENTATION_OPTIONS.SHOW_SEARCH_SUMMARY; + const contentRoot = document.documentElement.dataset.content_root; + + const [docName, title, anchor, descr, score, _filename, kind] = item; + + let listItem = document.createElement("li"); + // Add a class representing the item's type: + // can be used by a theme's CSS selector for styling + // See SearchResultKind for the class names. + listItem.classList.add(`kind-${kind}`); + let requestUrl; + let linkUrl; + if (docBuilder === "dirhtml") { + // dirhtml builder + let dirname = docName + "/"; + if (dirname.match(/\/index\/$/)) + dirname = dirname.substring(0, dirname.length - 6); + else if (dirname === "index/") dirname = ""; + requestUrl = contentRoot + dirname; + linkUrl = requestUrl; + } else { + // normal html builders + requestUrl = contentRoot + docName + docFileSuffix; + linkUrl = docName + docLinkSuffix; + } + let linkEl = listItem.appendChild(document.createElement("a")); + linkEl.href = linkUrl + anchor; + linkEl.dataset.score = score; + linkEl.innerHTML = title; + if (descr) { + listItem.appendChild(document.createElement("span")).innerHTML = + " (" + descr + ")"; + // highlight search terms in the description + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + } + else if (showSearchSummary) + fetch(requestUrl) + .then((responseData) => responseData.text()) + .then((data) => { + if (data) + listItem.appendChild( + Search.makeSearchSummary(data, searchTerms, anchor) + ); + // highlight search terms in the summary + if (SPHINX_HIGHLIGHT_ENABLED) // set in sphinx_highlight.js + highlightTerms.forEach((term) => _highlightText(listItem, term, "highlighted")); + }); + Search.output.appendChild(listItem); +}; +const _finishSearch = (resultCount) => { + Search.stopPulse(); + Search.title.innerText = _("Search Results"); + if (!resultCount) + Search.status.innerText = Documentation.gettext( + "Your search did not match any documents. Please make sure that all words are spelled correctly and that you've selected enough categories." + ); + else + Search.status.innerText = Documentation.ngettext( + "Search finished, found one page matching the search query.", + "Search finished, found ${resultCount} pages matching the search query.", + resultCount, + ).replace('${resultCount}', resultCount); +}; +const _displayNextItem = ( + results, + resultCount, + searchTerms, + highlightTerms, +) => { + // results left, load the summary and display it + // this is intended to be dynamic (don't sub resultsCount) + if (results.length) { + _displayItem(results.pop(), searchTerms, highlightTerms); + setTimeout( + () => _displayNextItem(results, resultCount, searchTerms, highlightTerms), + 5 + ); + } + // search finished, update title and status message + else _finishSearch(resultCount); +}; +// Helper function used by query() to order search results. +// Each input is an array of [docname, title, anchor, descr, score, filename, kind]. +// Order the results by score (in opposite order of appearance, since the +// `_displayNextItem` function uses pop() to retrieve items) and then alphabetically. +const _orderResultsByScoreThenName = (a, b) => { + const leftScore = a[4]; + const rightScore = b[4]; + if (leftScore === rightScore) { + // same score: sort alphabetically + const leftTitle = a[1].toLowerCase(); + const rightTitle = b[1].toLowerCase(); + if (leftTitle === rightTitle) return 0; + return leftTitle > rightTitle ? -1 : 1; // inverted is intentional + } + return leftScore > rightScore ? 1 : -1; +}; + +/** + * Default splitQuery function. Can be overridden in ``sphinx.search`` with a + * custom function per language. + * + * The regular expression works by splitting the string on consecutive characters + * that are not Unicode letters, numbers, underscores, or emoji characters. + * This is the same as ``\W+`` in Python, preserving the surrogate pair area. + */ +if (typeof splitQuery === "undefined") { + var splitQuery = (query) => query + .split(/[^\p{Letter}\p{Number}_\p{Emoji_Presentation}]+/gu) + .filter(term => term) // remove remaining empty strings +} + +/** + * Search Module + */ +const Search = { + _index: null, + _queued_query: null, + _pulse_status: -1, + + htmlToText: (htmlString, anchor) => { + const htmlElement = new DOMParser().parseFromString(htmlString, 'text/html'); + for (const removalQuery of [".headerlink", "script", "style"]) { + htmlElement.querySelectorAll(removalQuery).forEach((el) => { el.remove() }); + } + if (anchor) { + const anchorContent = htmlElement.querySelector(`[role="main"] ${anchor}`); + if (anchorContent) return anchorContent.textContent; + + console.warn( + `Anchored content block not found. Sphinx search tries to obtain it via DOM query '[role=main] ${anchor}'. Check your theme or template.` + ); + } + + // if anchor not specified or not found, fall back to main content + const docContent = htmlElement.querySelector('[role="main"]'); + if (docContent) return docContent.textContent; + + console.warn( + "Content block not found. Sphinx search tries to obtain it via DOM query '[role=main]'. Check your theme or template." + ); + return ""; + }, + + init: () => { + const query = new URLSearchParams(window.location.search).get("q"); + document + .querySelectorAll('input[name="q"]') + .forEach((el) => (el.value = query)); + if (query) Search.performSearch(query); + }, + + loadIndex: (url) => + (document.body.appendChild(document.createElement("script")).src = url), + + setIndex: (index) => { + Search._index = index; + if (Search._queued_query !== null) { + const query = Search._queued_query; + Search._queued_query = null; + Search.query(query); + } + }, + + hasIndex: () => Search._index !== null, + + deferQuery: (query) => (Search._queued_query = query), + + stopPulse: () => (Search._pulse_status = -1), + + startPulse: () => { + if (Search._pulse_status >= 0) return; + + const pulse = () => { + Search._pulse_status = (Search._pulse_status + 1) % 4; + Search.dots.innerText = ".".repeat(Search._pulse_status); + if (Search._pulse_status >= 0) window.setTimeout(pulse, 500); + }; + pulse(); + }, + + /** + * perform a search for something (or wait until index is loaded) + */ + performSearch: (query) => { + // create the required interface elements + const searchText = document.createElement("h2"); + searchText.textContent = _("Searching"); + const searchSummary = document.createElement("p"); + searchSummary.classList.add("search-summary"); + searchSummary.innerText = ""; + const searchList = document.createElement("ul"); + searchList.setAttribute("role", "list"); + searchList.classList.add("search"); + + const out = document.getElementById("search-results"); + Search.title = out.appendChild(searchText); + Search.dots = Search.title.appendChild(document.createElement("span")); + Search.status = out.appendChild(searchSummary); + Search.output = out.appendChild(searchList); + + const searchProgress = document.getElementById("search-progress"); + // Some themes don't use the search progress node + if (searchProgress) { + searchProgress.innerText = _("Preparing search..."); + } + Search.startPulse(); + + // index already loaded, the browser was quick! + if (Search.hasIndex()) Search.query(query); + else Search.deferQuery(query); + }, + + _parseQuery: (query) => { + // stem the search terms and add them to the correct list + const stemmer = new Stemmer(); + const searchTerms = new Set(); + const excludedTerms = new Set(); + const highlightTerms = new Set(); + const objectTerms = new Set(splitQuery(query.toLowerCase().trim())); + splitQuery(query.trim()).forEach((queryTerm) => { + const queryTermLower = queryTerm.toLowerCase(); + + // maybe skip this "word" + // stopwords array is from language_data.js + if ( + stopwords.indexOf(queryTermLower) !== -1 || + queryTerm.match(/^\d+$/) + ) + return; + + // stem the word + let word = stemmer.stemWord(queryTermLower); + // select the correct list + if (word[0] === "-") excludedTerms.add(word.substr(1)); + else { + searchTerms.add(word); + highlightTerms.add(queryTermLower); + } + }); + + if (SPHINX_HIGHLIGHT_ENABLED) { // set in sphinx_highlight.js + localStorage.setItem("sphinx_highlight_terms", [...highlightTerms].join(" ")) + } + + // console.debug("SEARCH: searching for:"); + // console.info("required: ", [...searchTerms]); + // console.info("excluded: ", [...excludedTerms]); + + return [query, searchTerms, excludedTerms, highlightTerms, objectTerms]; + }, + + /** + * execute search (requires search index to be loaded) + */ + _performSearch: (query, searchTerms, excludedTerms, highlightTerms, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + const allTitles = Search._index.alltitles; + const indexEntries = Search._index.indexentries; + + // Collect multiple result groups to be sorted separately and then ordered. + // Each is an array of [docname, title, anchor, descr, score, filename, kind]. + const normalResults = []; + const nonMainIndexResults = []; + + _removeChildren(document.getElementById("search-progress")); + + const queryLower = query.toLowerCase().trim(); + for (const [title, foundTitles] of Object.entries(allTitles)) { + if (title.toLowerCase().trim().includes(queryLower) && (queryLower.length >= title.length/2)) { + for (const [file, id] of foundTitles) { + const score = Math.round(Scorer.title * queryLower.length / title.length); + const boost = titles[file] === title ? 1 : 0; // add a boost for document titles + normalResults.push([ + docNames[file], + titles[file] !== title ? `${titles[file]} > ${title}` : title, + id !== null ? "#" + id : "", + null, + score + boost, + filenames[file], + SearchResultKind.title, + ]); + } + } + } + + // search for explicit entries in index directives + for (const [entry, foundEntries] of Object.entries(indexEntries)) { + if (entry.includes(queryLower) && (queryLower.length >= entry.length/2)) { + for (const [file, id, isMain] of foundEntries) { + const score = Math.round(100 * queryLower.length / entry.length); + const result = [ + docNames[file], + titles[file], + id ? "#" + id : "", + null, + score, + filenames[file], + SearchResultKind.index, + ]; + if (isMain) { + normalResults.push(result); + } else { + nonMainIndexResults.push(result); + } + } + } + } + + // lookup as object + objectTerms.forEach((term) => + normalResults.push(...Search.performObjectSearch(term, objectTerms)) + ); + + // lookup as search terms in fulltext + normalResults.push(...Search.performTermsSearch(searchTerms, excludedTerms)); + + // let the scorer override scores with a custom scoring function + if (Scorer.score) { + normalResults.forEach((item) => (item[4] = Scorer.score(item))); + nonMainIndexResults.forEach((item) => (item[4] = Scorer.score(item))); + } + + // Sort each group of results by score and then alphabetically by name. + normalResults.sort(_orderResultsByScoreThenName); + nonMainIndexResults.sort(_orderResultsByScoreThenName); + + // Combine the result groups in (reverse) order. + // Non-main index entries are typically arbitrary cross-references, + // so display them after other results. + let results = [...nonMainIndexResults, ...normalResults]; + + // remove duplicate search results + // note the reversing of results, so that in the case of duplicates, the highest-scoring entry is kept + let seen = new Set(); + results = results.reverse().reduce((acc, result) => { + let resultStr = result.slice(0, 4).concat([result[5]]).map(v => String(v)).join(','); + if (!seen.has(resultStr)) { + acc.push(result); + seen.add(resultStr); + } + return acc; + }, []); + + return results.reverse(); + }, + + query: (query) => { + const [searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms] = Search._parseQuery(query); + const results = Search._performSearch(searchQuery, searchTerms, excludedTerms, highlightTerms, objectTerms); + + // for debugging + //Search.lastresults = results.slice(); // a copy + // console.info("search results:", Search.lastresults); + + // print the results + _displayNextItem(results, results.length, searchTerms, highlightTerms); + }, + + /** + * search for object names + */ + performObjectSearch: (object, objectTerms) => { + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const objects = Search._index.objects; + const objNames = Search._index.objnames; + const titles = Search._index.titles; + + const results = []; + + const objectSearchCallback = (prefix, match) => { + const name = match[4] + const fullname = (prefix ? prefix + "." : "") + name; + const fullnameLower = fullname.toLowerCase(); + if (fullnameLower.indexOf(object) < 0) return; + + let score = 0; + const parts = fullnameLower.split("."); + + // check for different match types: exact matches of full name or + // "last name" (i.e. last dotted part) + if (fullnameLower === object || parts.slice(-1)[0] === object) + score += Scorer.objNameMatch; + else if (parts.slice(-1)[0].indexOf(object) > -1) + score += Scorer.objPartialMatch; // matches in last name + + const objName = objNames[match[1]][2]; + const title = titles[match[0]]; + + // If more than one term searched for, we require other words to be + // found in the name/title/description + const otherTerms = new Set(objectTerms); + otherTerms.delete(object); + if (otherTerms.size > 0) { + const haystack = `${prefix} ${name} ${objName} ${title}`.toLowerCase(); + if ( + [...otherTerms].some((otherTerm) => haystack.indexOf(otherTerm) < 0) + ) + return; + } + + let anchor = match[3]; + if (anchor === "") anchor = fullname; + else if (anchor === "-") anchor = objNames[match[1]][1] + "-" + fullname; + + const descr = objName + _(", in ") + title; + + // add custom score for some objects according to scorer + if (Scorer.objPrio.hasOwnProperty(match[2])) + score += Scorer.objPrio[match[2]]; + else score += Scorer.objPrioDefault; + + results.push([ + docNames[match[0]], + fullname, + "#" + anchor, + descr, + score, + filenames[match[0]], + SearchResultKind.object, + ]); + }; + Object.keys(objects).forEach((prefix) => + objects[prefix].forEach((array) => + objectSearchCallback(prefix, array) + ) + ); + return results; + }, + + /** + * search for full-text terms in the index + */ + performTermsSearch: (searchTerms, excludedTerms) => { + // prepare search + const terms = Search._index.terms; + const titleTerms = Search._index.titleterms; + const filenames = Search._index.filenames; + const docNames = Search._index.docnames; + const titles = Search._index.titles; + + const scoreMap = new Map(); + const fileMap = new Map(); + + // perform the search on the required terms + searchTerms.forEach((word) => { + const files = []; + const arr = [ + { files: terms[word], score: Scorer.term }, + { files: titleTerms[word], score: Scorer.title }, + ]; + // add support for partial matches + if (word.length > 2) { + const escapedWord = _escapeRegExp(word); + if (!terms.hasOwnProperty(word)) { + Object.keys(terms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: terms[term], score: Scorer.partialTerm }); + }); + } + if (!titleTerms.hasOwnProperty(word)) { + Object.keys(titleTerms).forEach((term) => { + if (term.match(escapedWord)) + arr.push({ files: titleTerms[term], score: Scorer.partialTitle }); + }); + } + } + + // no match but word was a required one + if (arr.every((record) => record.files === undefined)) return; + + // found search word in contents + arr.forEach((record) => { + if (record.files === undefined) return; + + let recordFiles = record.files; + if (recordFiles.length === undefined) recordFiles = [recordFiles]; + files.push(...recordFiles); + + // set score for the word in each file + recordFiles.forEach((file) => { + if (!scoreMap.has(file)) scoreMap.set(file, {}); + scoreMap.get(file)[word] = record.score; + }); + }); + + // create the mapping + files.forEach((file) => { + if (!fileMap.has(file)) fileMap.set(file, [word]); + else if (fileMap.get(file).indexOf(word) === -1) fileMap.get(file).push(word); + }); + }); + + // now check if the files don't contain excluded terms + const results = []; + for (const [file, wordList] of fileMap) { + // check if all requirements are matched + + // as search terms with length < 3 are discarded + const filteredTermCount = [...searchTerms].filter( + (term) => term.length > 2 + ).length; + if ( + wordList.length !== searchTerms.size && + wordList.length !== filteredTermCount + ) + continue; + + // ensure that none of the excluded terms is in the search result + if ( + [...excludedTerms].some( + (term) => + terms[term] === file || + titleTerms[term] === file || + (terms[term] || []).includes(file) || + (titleTerms[term] || []).includes(file) + ) + ) + break; + + // select one (max) score for the file. + const score = Math.max(...wordList.map((w) => scoreMap.get(file)[w])); + // add result to the result list + results.push([ + docNames[file], + titles[file], + "", + null, + score, + filenames[file], + SearchResultKind.text, + ]); + } + return results; + }, + + /** + * helper function to return a node containing the + * search summary for a given text. keywords is a list + * of stemmed words. + */ + makeSearchSummary: (htmlText, keywords, anchor) => { + const text = Search.htmlToText(htmlText, anchor); + if (text === "") return null; + + const textLower = text.toLowerCase(); + const actualStartPosition = [...keywords] + .map((k) => textLower.indexOf(k.toLowerCase())) + .filter((i) => i > -1) + .slice(-1)[0]; + const startWithContext = Math.max(actualStartPosition - 120, 0); + + const top = startWithContext === 0 ? "" : "..."; + const tail = startWithContext + 240 < text.length ? "..." : ""; + + let summary = document.createElement("p"); + summary.classList.add("context"); + summary.textContent = top + text.substr(startWithContext, 240).trim() + tail; + + return summary; + }, +}; + +_ready(Search.init); diff --git a/docs/build/html/_static/sphinx_highlight.js b/docs/build/html/_static/sphinx_highlight.js new file mode 100644 index 0000000000000000000000000000000000000000..8a96c69a1942318413af68fd459122b56edd8d69 --- /dev/null +++ b/docs/build/html/_static/sphinx_highlight.js @@ -0,0 +1,154 @@ +/* Highlighting utilities for Sphinx HTML documentation. */ +"use strict"; + +const SPHINX_HIGHLIGHT_ENABLED = true + +/** + * highlight a given string on a node by wrapping it in + * span elements with the given class name. + */ +const _highlight = (node, addItems, text, className) => { + if (node.nodeType === Node.TEXT_NODE) { + const val = node.nodeValue; + const parent = node.parentNode; + const pos = val.toLowerCase().indexOf(text); + if ( + pos >= 0 && + !parent.classList.contains(className) && + !parent.classList.contains("nohighlight") + ) { + let span; + + const closestNode = parent.closest("body, svg, foreignObject"); + const isInSVG = closestNode && closestNode.matches("svg"); + if (isInSVG) { + span = document.createElementNS("http://www.w3.org/2000/svg", "tspan"); + } else { + span = document.createElement("span"); + span.classList.add(className); + } + + span.appendChild(document.createTextNode(val.substr(pos, text.length))); + const rest = document.createTextNode(val.substr(pos + text.length)); + parent.insertBefore( + span, + parent.insertBefore( + rest, + node.nextSibling + ) + ); + node.nodeValue = val.substr(0, pos); + /* There may be more occurrences of search term in this node. So call this + * function recursively on the remaining fragment. + */ + _highlight(rest, addItems, text, className); + + if (isInSVG) { + const rect = document.createElementNS( + "http://www.w3.org/2000/svg", + "rect" + ); + const bbox = parent.getBBox(); + rect.x.baseVal.value = bbox.x; + rect.y.baseVal.value = bbox.y; + rect.width.baseVal.value = bbox.width; + rect.height.baseVal.value = bbox.height; + rect.setAttribute("class", className); + addItems.push({ parent: parent, target: rect }); + } + } + } else if (node.matches && !node.matches("button, select, textarea")) { + node.childNodes.forEach((el) => _highlight(el, addItems, text, className)); + } +}; +const _highlightText = (thisNode, text, className) => { + let addItems = []; + _highlight(thisNode, addItems, text, className); + addItems.forEach((obj) => + obj.parent.insertAdjacentElement("beforebegin", obj.target) + ); +}; + +/** + * Small JavaScript module for the documentation. + */ +const SphinxHighlight = { + + /** + * highlight the search words provided in localstorage in the text + */ + highlightSearchWords: () => { + if (!SPHINX_HIGHLIGHT_ENABLED) return; // bail if no highlight + + // get and clear terms from localstorage + const url = new URL(window.location); + const highlight = + localStorage.getItem("sphinx_highlight_terms") + || url.searchParams.get("highlight") + || ""; + localStorage.removeItem("sphinx_highlight_terms") + url.searchParams.delete("highlight"); + window.history.replaceState({}, "", url); + + // get individual terms from highlight string + const terms = highlight.toLowerCase().split(/\s+/).filter(x => x); + if (terms.length === 0) return; // nothing to do + + // There should never be more than one element matching "div.body" + const divBody = document.querySelectorAll("div.body"); + const body = divBody.length ? divBody[0] : document.querySelector("body"); + window.setTimeout(() => { + terms.forEach((term) => _highlightText(body, term, "highlighted")); + }, 10); + + const searchBox = document.getElementById("searchbox"); + if (searchBox === null) return; + searchBox.appendChild( + document + .createRange() + .createContextualFragment( + '" + ) + ); + }, + + /** + * helper function to hide the search marks again + */ + hideSearchWords: () => { + document + .querySelectorAll("#searchbox .highlight-link") + .forEach((el) => el.remove()); + document + .querySelectorAll("span.highlighted") + .forEach((el) => el.classList.remove("highlighted")); + localStorage.removeItem("sphinx_highlight_terms") + }, + + initEscapeListener: () => { + // only install a listener if it is really needed + if (!DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS) return; + + document.addEventListener("keydown", (event) => { + // bail for input elements + if (BLACKLISTED_KEY_CONTROL_ELEMENTS.has(document.activeElement.tagName)) return; + // bail with special keys + if (event.shiftKey || event.altKey || event.ctrlKey || event.metaKey) return; + if (DOCUMENTATION_OPTIONS.ENABLE_SEARCH_SHORTCUTS && (event.key === "Escape")) { + SphinxHighlight.hideSearchWords(); + event.preventDefault(); + } + }); + }, +}; + +_ready(() => { + /* Do not call highlightSearchWords() when we are on the search page. + * It will highlight words from the *previous* search query. + */ + if (typeof Search === "undefined") SphinxHighlight.highlightSearchWords(); + SphinxHighlight.initEscapeListener(); +}); diff --git a/docs/build/html/_static/tabs.css b/docs/build/html/_static/tabs.css new file mode 100644 index 0000000000000000000000000000000000000000..957ba60d6989db4103dd1d921ba291879b0544e1 --- /dev/null +++ b/docs/build/html/_static/tabs.css @@ -0,0 +1,89 @@ +.sphinx-tabs { + margin-bottom: 1rem; +} + +[role="tablist"] { + border-bottom: 1px solid #a0b3bf; +} + +.sphinx-tabs-tab { + position: relative; + font-family: Lato,'Helvetica Neue',Arial,Helvetica,sans-serif; + color: #1D5C87; + line-height: 24px; + margin: 0; + font-size: 16px; + font-weight: 400; + background-color: rgba(255, 255, 255, 0); + border-radius: 5px 5px 0 0; + border: 0; + padding: 1rem 1.5rem; + margin-bottom: 0; +} + +.sphinx-tabs-tab[aria-selected="true"] { + font-weight: 700; + border: 1px solid #a0b3bf; + border-bottom: 1px solid white; + margin: -1px; + background-color: white; +} + +.sphinx-tabs-tab:focus { + z-index: 1; + outline-offset: 1px; +} + +.sphinx-tabs-panel { + position: relative; + padding: 1rem; + border: 1px solid #a0b3bf; + margin: 0px -1px -1px -1px; + border-radius: 0 0 5px 5px; + border-top: 0; + background: white; +} + +.sphinx-tabs-panel.code-tab { + padding: 0.4rem; +} + +.sphinx-tab img { + margin-bottom: 24 px; +} + +/* Dark theme preference styling */ + +@media (prefers-color-scheme: dark) { + body[data-theme="auto"] .sphinx-tabs-panel { + color: white; + background-color: rgb(50, 50, 50); + } + + body[data-theme="auto"] .sphinx-tabs-tab { + color: white; + background-color: rgba(255, 255, 255, 0.05); + } + + body[data-theme="auto"] .sphinx-tabs-tab[aria-selected="true"] { + border-bottom: 1px solid rgb(50, 50, 50); + background-color: rgb(50, 50, 50); + } +} + +/* Explicit dark theme styling */ + +body[data-theme="dark"] .sphinx-tabs-panel { + color: white; + background-color: rgb(50, 50, 50); +} + +body[data-theme="dark"] .sphinx-tabs-tab { + color: white; + background-color: rgba(255, 255, 255, 0.05); +} + +body[data-theme="dark"] .sphinx-tabs-tab[aria-selected="true"] { + border-bottom: 2px solid rgb(50, 50, 50); + background-color: rgb(50, 50, 50); +} diff --git a/docs/build/html/_static/tabs.js b/docs/build/html/_static/tabs.js new file mode 100644 index 0000000000000000000000000000000000000000..48dc303c8c0165f4c8735d84bb8e09132d0edb58 --- /dev/null +++ b/docs/build/html/_static/tabs.js @@ -0,0 +1,145 @@ +try { + var session = window.sessionStorage || {}; +} catch (e) { + var session = {}; +} + +window.addEventListener("DOMContentLoaded", () => { + const allTabs = document.querySelectorAll('.sphinx-tabs-tab'); + const tabLists = document.querySelectorAll('[role="tablist"]'); + + allTabs.forEach(tab => { + tab.addEventListener("click", changeTabs); + }); + + tabLists.forEach(tabList => { + tabList.addEventListener("keydown", keyTabs); + }); + + // Restore group tab selection from session + const lastSelected = session.getItem('sphinx-tabs-last-selected'); + if (lastSelected != null) selectNamedTabs(lastSelected); +}); + +/** + * Key focus left and right between sibling elements using arrows + * @param {Node} e the element in focus when key was pressed + */ +function keyTabs(e) { + const tab = e.target; + let nextTab = null; + if (e.keyCode === 39 || e.keyCode === 37) { + tab.setAttribute("tabindex", -1); + // Move right + if (e.keyCode === 39) { + nextTab = tab.nextElementSibling; + if (nextTab === null) { + nextTab = tab.parentNode.firstElementChild; + } + // Move left + } else if (e.keyCode === 37) { + nextTab = tab.previousElementSibling; + if (nextTab === null) { + nextTab = tab.parentNode.lastElementChild; + } + } + } + + if (nextTab !== null) { + nextTab.setAttribute("tabindex", 0); + nextTab.focus(); + } +} + +/** + * Select or deselect clicked tab. If a group tab + * is selected, also select tab in other tabLists. + * @param {Node} e the element that was clicked + */ +function changeTabs(e) { + // Use this instead of the element that was clicked, in case it's a child + const notSelected = this.getAttribute("aria-selected") === "false"; + const positionBefore = this.parentNode.getBoundingClientRect().top; + const notClosable = !this.parentNode.classList.contains("closeable"); + + deselectTabList(this); + + if (notSelected || notClosable) { + selectTab(this); + const name = this.getAttribute("name"); + selectNamedTabs(name, this.id); + + if (this.classList.contains("group-tab")) { + // Persist during session + session.setItem('sphinx-tabs-last-selected', name); + } + } + + const positionAfter = this.parentNode.getBoundingClientRect().top; + const positionDelta = positionAfter - positionBefore; + // Scroll to offset content resizing + window.scrollTo(0, window.scrollY + positionDelta); +} + +/** + * Select tab and show associated panel. + * @param {Node} tab tab to select + */ +function selectTab(tab) { + tab.setAttribute("aria-selected", true); + + // Show the associated panel + document + .getElementById(tab.getAttribute("aria-controls")) + .removeAttribute("hidden"); +} + +/** + * Hide the panels associated with all tabs within the + * tablist containing this tab. + * @param {Node} tab a tab within the tablist to deselect + */ +function deselectTabList(tab) { + const parent = tab.parentNode; + const grandparent = parent.parentNode; + + Array.from(parent.children) + .forEach(t => t.setAttribute("aria-selected", false)); + + Array.from(grandparent.children) + .slice(1) // Skip tablist + .forEach(panel => panel.setAttribute("hidden", true)); +} + +/** + * Select grouped tabs with the same name, but no the tab + * with the given id. + * @param {Node} name name of grouped tab to be selected + * @param {Node} clickedId id of clicked tab + */ +function selectNamedTabs(name, clickedId=null) { + const groupedTabs = document.querySelectorAll(`.sphinx-tabs-tab[name="${name}"]`); + const tabLists = Array.from(groupedTabs).map(tab => tab.parentNode); + + tabLists + .forEach(tabList => { + // Don't want to change the tabList containing the clicked tab + const clickedTab = tabList.querySelector(`[id="${clickedId}"]`); + if (clickedTab === null ) { + // Select first tab with matching name + const tab = tabList.querySelector(`.sphinx-tabs-tab[name="${name}"]`); + deselectTabList(tab); + selectTab(tab); + } + }) +} + +if (typeof exports === 'undefined') { + exports = {}; +} + +exports.keyTabs = keyTabs; +exports.changeTabs = changeTabs; +exports.selectTab = selectTab; +exports.deselectTabList = deselectTabList; +exports.selectNamedTabs = selectNamedTabs; diff --git a/docs/build/html/genindex.html b/docs/build/html/genindex.html new file mode 100644 index 0000000000000000000000000000000000000000..f08e21c4942b0a14f8b0837327598ae56feac67f --- /dev/null +++ b/docs/build/html/genindex.html @@ -0,0 +1,231 @@ + + + + + + + Index — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + +
+ + +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/index.html b/docs/build/html/index.html new file mode 100644 index 0000000000000000000000000000000000000000..a9580630124171d9c9c8d51a3d42410f1c24a997 --- /dev/null +++ b/docs/build/html/index.html @@ -0,0 +1,173 @@ + + + + + + + + AIM-CU documentation — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

AIM-CU documentation

+

A CUSUM-based tool for AI Monitoring

+

AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU). AIM-CU computes:

+
    +
  • The parameter choices for change-point detection based on an acceptable false alarm rate

  • +
  • Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices.

  • +
+
+

Code execution

+

Clone AIM-CU repository.

+
git clone https://github.com/DIDSR/AIM-CU.git
+
+
+

Run the following commands to install required dependencies (Python = 3.10 is used).

+
apt-get -y install python3
+apt-get -y install pip
+cd AIM-CU
+pip install -r requirements.txt
+
+
+

Run AIM-CU.

+
python3 app.py
+
+
+

Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally.

+
+
+

Demo

+

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.

+ +
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/objects.inv b/docs/build/html/objects.inv new file mode 100644 index 0000000000000000000000000000000000000000..af4fb7fa9c5dda904fe10c7d25e01ba4361aacdf Binary files /dev/null and b/docs/build/html/objects.inv differ diff --git a/docs/build/html/py-modindex.html b/docs/build/html/py-modindex.html new file mode 100644 index 0000000000000000000000000000000000000000..44491e7a377957a28bab061072f18314a2a70427 --- /dev/null +++ b/docs/build/html/py-modindex.html @@ -0,0 +1,143 @@ + + + + + + + Python Module Index — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ + +

Python Module Index

+ +
+ p +
+ + + + + + + + + + + + + + + + +
 
+ p
+ package +
    + package.ARLTheoretical +
    + package.cusum +
    + package.utils +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/ref_cusum.html b/docs/build/html/ref_cusum.html new file mode 100644 index 0000000000000000000000000000000000000000..b8c71166d501304ed187443514f45a4e36283529 --- /dev/null +++ b/docs/build/html/ref_cusum.html @@ -0,0 +1,252 @@ + + + + + + + + CUSUM — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

CUSUM

+

Cumulative Sum (CUSUM)

+

@author: smriti.prathapan

+
+
+class package.cusum.CUSUM
+

CUSUM class and its functionalities.

+
+
+change_detection(normalized_ref_value: float = 0.5, normalized_threshold: float = 4) None
+

Detects a change in the process.

+
+
Parameters:
+
    +
  • pre_change_days (int) – Number of days for in-control phase.

  • +
  • normalized_ref_value (float, optional) – Normalized reference value for detecting a unit standard deviation change in mean of the process. Defaults to 0.5.

  • +
  • normalized_threshold (float, optional) – Normalized threshold. Defaults to 4.

  • +
+
+
+
+ +
+
+compute_cusum(x: list[float], mu_0: float, k: float) tuple[list[float], list[float], list[float]]
+

Compute CUSUM for the observations in x

+
+
Parameters:
+
    +
  • x (list[float]) – Performance metric to be monitored

  • +
  • mu_0 (float) – In-control mean of the observations/performance metric

  • +
  • k (float) – Reference value related to the magnitude of change that one is interested in detecting

  • +
+
+
Returns:
+

Positive cumulative sum, negative cumulative sum, and CUSUM

+
+
Return type:
+

tuple[list[float], list[float], list[float]]

+
+
+
+ +
+
+initialize() None
+

Initialize with the configuration file.

+
+ +
+
+plot_cusum_plotly() Figure
+

Plot CUSUM value using Plotly

+
+
Returns:
+

CUSUM plot using Plotly graph object.

+
+
Return type:
+

go.Figure

+
+
+
+ +
+
+plot_input_metric_plotly() Figure
+

Plot the input metric using Plotly.

+
+
Returns:
+

Scatter plot as Plotly graph object.

+
+
Return type:
+

go.Figure

+
+
+
+ +
+
+plot_input_metric_plotly_raw() Figure
+

Plot AI output using Plotly.

+
+
Returns:
+

Scatter plot as Plotly graph object.

+
+
Return type:
+

go.Figure

+
+
+
+ +
+
+set_df_metric_csv(data_csv: DataFrame) None
+

Assign the performance metric data to be used for CUSUM.

+
+
Parameters:
+

data_csv (DataFrame or TextFileReader) – A comma-separated values (csv) file is returned as two-dimensional data structure with labeled axes.

+
+
+
+ +
+
+set_df_metric_default() None
+

Read the provided performance metric data to be used for CUSUM for an example.

+
+ +
+
+set_init_stats(init_days: int) None
+

Use initial days to calculate in-control mean and standard deviation.

+
+
Parameters:
+

init_days (int, optional) – Initial days when observations are considered stable. Defaults to 30.

+
+
+
+ +
+
+set_timeline(data: ndarray) None
+

Set the timeline of observations.

+
+
Parameters:
+

data (np.ndarray) – Data of the metric values across the observations.

+
+
+
+ +
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/ref_method.html b/docs/build/html/ref_method.html new file mode 100644 index 0000000000000000000000000000000000000000..3b1428fa8ad0637f0685cecbd45f234a1a416d0f --- /dev/null +++ b/docs/build/html/ref_method.html @@ -0,0 +1,179 @@ + + + + + + + + Methods — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Methods

+
+

CUSUM parameters

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
CUSUM parameters

Parameter

Description

μ_in

The mean of the performance metric when the process is in-control, i.e., when there is no performance drift

ARL_0

Number of observations before the control chart signals a false detection

σ_in

The in-control standard deviation of the metric

ARL_1

Number of observations before the control chart signals a true detection

k

The normalized reference value, which is related to the magnitude of change that one is interested in detecting. k = 0.5 is the default choice for detecting a unit standard deviation change

S_hi

Cumulative sum of positive changes in the metric

h

The normalized threshold or control limit (default =4). This threshold determines when the control chart signals a detection

S_lo

Cumulative sum of negative changes in the metric

+
+
+

CUSUM chart

+

A two-sided CUSUM control chart computes the cumulative differences or +deviations of individual observations from the target mean (or +in-control mean, \(\mu_{in}\)). The positive and negative cumulative +sums are calculated:

+
+\[\begin{split}\\ S_{hi}(d) = max(0, S_{hi}(d-1) + x_d - \hat{\mu}_{in} - K) +\\ S_{lo}(d) = max(0, S_{lo}(d-1) - x_d + \hat{\mu}_{in} - K)\end{split}\]
+

where d denotes a unit of time, \(x_d\) is the value of quantity +being monitored at time \(d\), \(\hat{\mu}_{in}\) is the +in-control mean of \(x_d\), and \(K\) is a “reference value” +related to the magnitude of change that one is interested in detecting. +\(S_{hi}\) and \(S_{lo}\) are the cumulative sum of positive and +negative changes. To detect a change in the observed values from the +in-control mean, the CUSUM scheme accumulates deviations that are +\(K\) units away from the in-control mean. Let \(\sigma_{in}\) +denote the in-control standard deviation of \(x_d\).

+
+
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/ref_theoretical.html b/docs/build/html/ref_theoretical.html new file mode 100644 index 0000000000000000000000000000000000000000..f92e34c0649d589391dbafe4ab22d76a17f0ea34 --- /dev/null +++ b/docs/build/html/ref_theoretical.html @@ -0,0 +1,208 @@ + + + + + + + + ARLTheoretical — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

ARLTheoretical

+

ARLTheoretical

+

@author: smriti.prathapan

+
+
+package.ARLTheoretical.get_ARL_1(h: float, shift_in_mean: list[float], dict_ARL0_k: OrderedDict) DataFrame
+

Get the ARL1 along with k values.

+
+
Parameters:
+
    +
  • h (float) – Normalized threshold.

  • +
  • shift_in_mean (list[float]) – List of the values of shift in mean.

  • +
  • dict_ARL0_k (OrderedDict) – Data dictionary of ARL0 and k

  • +
+
+
Returns:
+

Table for ARL1 and k values.

+
+
Return type:
+

pd.DataFrame

+
+
+
+ +
+
+package.ARLTheoretical.get_ARL_1_h_mu1_k(h: float, k: float, mu1: float) float
+

Calculate ARL_1 with given Shift in Mean (mu1) and k.

+
+
Parameters:
+
    +
  • h (float) – Normalized threshold.

  • +
  • k (float) – Normalized reference value.

  • +
  • mu1 (float) – Intended shift in mean.

  • +
+
+
Returns:
+

Detection delay (ARL1).

+
+
Return type:
+

float

+
+
+
+ +
+
+package.ARLTheoretical.get_ref_value(h: float, list_ARL_0: list[float]) tuple[DataFrame, OrderedDict]
+

provides normalized reference values k for provided list of ARL0, given the value of normalized threshold h.

+
+
Parameters:
+
    +
  • h (float) – Normalized threshold.

  • +
  • list_ARL_0 (list) – List of ARL0 values.

  • +
+
+
Returns:
+

Dataframe of ARL0 and k, Data dictionary of ARL0 and k; where k is normalized reference value.

+
+
Return type:
+

tuple[pd.Dataframe, OrderedDict]

+
+
+
+ +
+
+package.ARLTheoretical.get_ref_value_k(h: float, ARL_0: float) float
+

Calculation for the reference value for given h and ARL_0.

+
+
Parameters:
+
    +
  • h (float) – Normalized threshold.

  • +
  • ARL_0 (float) – ARL0 value.

  • +
+
+
Returns:
+

Normalized reference value k.

+
+
Return type:
+

float

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/ref_utils.html b/docs/build/html/ref_utils.html new file mode 100644 index 0000000000000000000000000000000000000000..c0f3ba53f92c5698de3b5957adcf4a4b20dfd14a --- /dev/null +++ b/docs/build/html/ref_utils.html @@ -0,0 +1,180 @@ + + + + + + + + Utils — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +
+

Utils

+

Utilities to handle different operations

+
+
+package.utils.get_greattable_as_html(df: DataFrame) GT
+

Get the great_table as HTML from Pandas dataframe.

+
+
Parameters:
+

df (pd.DataFrame) – Dataframe to rendera as a table.

+
+
Returns:
+

Table in HTML format.

+
+
Return type:
+

gt.GT

+
+
+
+ +
+
+package.utils.populate_summary_table_ARL0_k(summary_table_df_ARL0_k: DataFrame, h) GT
+

Populate ARLTheoretical.summary_table_df_ARL0_k.

+
+
Parameters:
+
    +
  • summary_table_df_ARL0_k (pd.DataFrame) – Dataframe of ARL0 and its respective values of k.

  • +
  • h (float) – Normalized threshold.

  • +
+
+
Returns:
+

Table of ARL0 and k in HTML format.

+
+
Return type:
+

gt.GT

+
+
+
+ +
+
+package.utils.populate_summary_table_ARL1_k(summary_table_df_ARL1_k: DataFrame, dict_ARL0_k: OrderedDict, h) GT
+

Populate Multiindex table specific for ARLTheoretical.summary_table_df_ARL1_k

+
+
Parameters:
+
    +
  • summary_table_df_ARL1_k (pd.DataFrame) – Dataframe with ARL1 and k values.

  • +
  • dict_ARL0_k (OrderedDict) – Data Dictionary with the mapping between ARL0 and k.

  • +
  • h (float) – Normalized threshold.

  • +
+
+
Returns:
+

Table for ARL1 and k in HTML format.

+
+
Return type:
+

gt.GT

+
+
+
+ +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/search.html b/docs/build/html/search.html new file mode 100644 index 0000000000000000000000000000000000000000..89c4f8598bb1b09e095ea8415bb49ce72fa389b9 --- /dev/null +++ b/docs/build/html/search.html @@ -0,0 +1,131 @@ + + + + + + + Search — AIM-CU 1.0.0 documentation + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ + +
+ +

Search

+ + + + +

+ Searching for multiple words only shows matches that contain + all words. +

+ + +
+ + + +
+ + +
+ + +
+ +
+
+ +
+
+ + + + + + + \ No newline at end of file diff --git a/docs/build/html/searchindex.js b/docs/build/html/searchindex.js new file mode 100644 index 0000000000000000000000000000000000000000..977aa110c88e1c5c72d2e52674c623ee8dcd17fa --- /dev/null +++ b/docs/build/html/searchindex.js @@ -0,0 +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": {"change_detection() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.change_detection", false]], "compute_cusum() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.compute_cusum", false]], "cusum (class in package.cusum)": [[1, "package.cusum.CUSUM", false]], "initialize() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.initialize", false]], "module": [[1, "module-package.cusum", false]], "package.cusum": [[1, "module-package.cusum", false]], "plot_cusum_plotly() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.plot_cusum_plotly", false]], "plot_input_metric_plotly() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.plot_input_metric_plotly", false]], "plot_input_metric_plotly_raw() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.plot_input_metric_plotly_raw", false]], "set_df_metric_csv() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.set_df_metric_csv", false]], "set_df_metric_default() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.set_df_metric_default", false]], "set_init_stats() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.set_init_stats", false]], "set_timeline() (package.cusum.cusum method)": [[1, "package.cusum.CUSUM.set_timeline", false]]}, "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, "3": 0, "30": 1, "4": [1, 2], "5": [1, 2], "7860": 0, "A": [0, 1, 2], "If": 0, "In": 1, "The": [0, 2], "To": 2, "_": 2, "accept": 0, "accumul": 2, "across": 1, "ai": [0, 1], "alarm": 0, "along": 3, "also": 0, "an": [0, 1], "app": 0, "apt": 0, "ar": [1, 2], "arl0": [3, 4], "arl1": [3, 4], "arl_0": [2, 3], "arl_1": [2, 3], "arltheoret": [0, 4], "assign": 1, "author": [1, 3], "avail": 0, "awai": 2, "ax": 1, "base": 0, "befor": 2, "being": 2, "between": 4, "button": 0, "calcul": [1, 2, 3], "can": 0, "cd": 0, "chang": [0, 1, 2], "change_detect": 1, "chart": 0, "choic": [0, 2], "class": 1, "click": 0, "clone": 0, "co": 0, "com": 0, "comma": 1, "command": 0, "comput": [0, 1, 2], "compute_cusum": 1, "configur": 1, "consid": 1, "control": [1, 2], "csv": 1, "cumul": [0, 1, 2], "cusum": 0, "d": 2, "dai": 1, "data": [1, 3, 4], "data_csv": 1, "datafram": [1, 3, 4], "default": [1, 2], "delai": [0, 3], "denot": 2, "depend": 0, "descript": 2, "detect": [0, 1, 2, 3], "determin": 2, "deviat": [1, 2], "df": 4, "dict_arl0_k": [3, 4], "dictionari": [3, 4], "didsr": 0, "differ": [2, 4], "dimension": 1, "displac": 0, "drift": 2, "e": 2, "estim": 0, "exampl": 1, "fals": [0, 2], "figur": 1, "file": 1, "float": [1, 3, 4], "follow": 0, "format": 4, "from": [0, 2, 4], "function": 1, "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], "git": 0, "github": 0, "given": [0, 3], "go": 1, "graph": 1, "great_tabl": 4, "gt": 4, "h": [2, 3, 4], "handl": 4, "hat": 2, "hi": 2, "html": 4, "http": 0, "huggingfac": 0, "i": [0, 1, 2, 3], "individu": 2, "init_dai": 1, "initi": 1, "input": 1, "instal": 0, "int": 1, "intend": 3, "interest": [1, 2], "its": [1, 4], "k": [1, 2, 3, 4], "label": 1, "let": 2, "limit": 2, "list": [1, 3], "list_arl_0": 3, "lo": 2, "local": 0, "magnitud": [1, 2], "map": 4, "max": 2, "mean": [1, 2, 3], "method": 0, "metric": [0, 1, 2], "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, "np": 1, "number": [1, 2], "object": 1, "observ": [1, 2], "one": [1, 2], "open": 0, "oper": 4, "option": 1, "ordereddict": [3, 4], "output": 1, "packag": [1, 3, 4], "panda": 4, "paramet": [0, 1, 3, 4], "paus": 0, "pd": [3, 4], "perform": [0, 1, 2], "phase": 1, "pip": 0, "plot": 1, "plot_cusum_plotli": 1, "plot_input_metric_plotli": 1, "plot_input_metric_plotly_raw": 1, "plotli": 1, "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], "provid": [1, 3], "py": 0, "python": 0, "python3": 0, "quantiti": 2, "r": 0, "rate": 0, "read": 1, "refer": [1, 2, 3], "relat": [1, 2], "rendera": 4, "repositori": 0, "requir": 0, "respect": 4, "restart": 0, "return": [1, 3, 4], "run": 0, "s_": 2, "s_hi": 2, "s_lo": 2, "scatter": 1, "scheme": 2, "separ": 1, "set": 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], "space": 0, "specif": 4, "stabl": 1, "standard": [1, 2], "statist": 0, "structur": 1, "sum": [0, 1, 2], "summary_table_df_arl0_k": 4, "summary_table_df_arl1_k": 4, "tabl": [3, 4], "target": [0, 2], "textfileread": 1, "thi": 2, "those": 0, "threshold": [1, 2, 3, 4], "through": 0, "time": 2, "timelin": 1, "tool": 0, "true": 2, "tupl": [1, 3], "two": [1, 2], "txt": 0, "type": [1, 3, 4], "unit": [1, 2], "url": 0, "us": [0, 1], "util": 0, "valu": [1, 2, 3, 4], "when": [1, 2], "where": [2, 3], "which": 2, "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, "document": 0, "execut": 0, "method": 2, "paramet": 2, "util": 4}}) \ No newline at end of file diff --git a/docs/build/latex/LICRcyr2utf8.xdy b/docs/build/latex/LICRcyr2utf8.xdy new file mode 100644 index 0000000000000000000000000000000000000000..a9ca1c82cd661cfa1583e86fa881644d029d061f --- /dev/null +++ b/docs/build/latex/LICRcyr2utf8.xdy @@ -0,0 +1,101 @@ +;; -*- coding: utf-8; mode: Lisp; -*- +;; style file for xindy +;; filename: LICRcyr2utf8.xdy +;; description: style file for xindy which maps back LaTeX Internal +;; Character Representation of Cyrillic to utf-8 +;; usage: for use with pdflatex produced .idx files. +;; Contributed by the Sphinx team, July 2018. +(merge-rule "\IeC {\'\CYRG }" "Ѓ" :string) +(merge-rule "\IeC {\'\CYRK }" "Ќ" :string) +(merge-rule "\IeC {\'\cyrg }" "ѓ" :string) +(merge-rule "\IeC {\'\cyrk }" "ќ" :string) +(merge-rule "\IeC {\CYRA }" "А" :string) +(merge-rule "\IeC {\CYRB }" "Б" :string) +(merge-rule "\IeC {\CYRC }" "Ц" :string) +(merge-rule "\IeC {\CYRCH }" "Ч" :string) +(merge-rule "\IeC {\CYRD }" "Д" :string) +(merge-rule "\IeC {\CYRDJE }" "Ђ" :string) +(merge-rule "\IeC {\CYRDZE }" "Ѕ" :string) +(merge-rule "\IeC {\CYRDZHE }" "Џ" :string) +(merge-rule "\IeC {\CYRE }" "Е" :string) +(merge-rule "\IeC {\CYREREV }" "Э" :string) +(merge-rule "\IeC {\CYRERY }" "Ы" :string) +(merge-rule "\IeC {\CYRF }" "Ф" :string) +(merge-rule "\IeC {\CYRG }" "Г" :string) +(merge-rule "\IeC {\CYRGUP }" "Ґ" :string) +(merge-rule "\IeC {\CYRH }" "Х" :string) +(merge-rule "\IeC {\CYRHRDSN }" "Ъ" :string) +(merge-rule "\IeC {\CYRI }" "И" :string) +(merge-rule "\IeC {\CYRIE }" "Є" :string) +(merge-rule "\IeC {\CYRII }" "І" :string) +(merge-rule "\IeC {\CYRISHRT }" "Й" :string) +(merge-rule "\IeC {\CYRJE }" "Ј" :string) +(merge-rule "\IeC {\CYRK }" "К" :string) +(merge-rule "\IeC {\CYRL }" "Л" :string) +(merge-rule "\IeC {\CYRLJE }" "Љ" :string) +(merge-rule "\IeC {\CYRM }" "М" :string) +(merge-rule "\IeC {\CYRN }" "Н" :string) +(merge-rule "\IeC {\CYRNJE }" "Њ" :string) +(merge-rule "\IeC {\CYRO }" "О" :string) +(merge-rule "\IeC {\CYRP }" "П" :string) +(merge-rule "\IeC {\CYRR }" "Р" :string) +(merge-rule "\IeC {\CYRS }" "С" :string) +(merge-rule "\IeC {\CYRSFTSN }" "Ь" :string) +(merge-rule "\IeC {\CYRSH }" "Ш" :string) +(merge-rule "\IeC {\CYRSHCH }" "Щ" :string) +(merge-rule "\IeC {\CYRT }" "Т" :string) +(merge-rule "\IeC {\CYRTSHE }" "Ћ" :string) +(merge-rule "\IeC {\CYRU }" "У" :string) +(merge-rule "\IeC {\CYRUSHRT }" "Ў" :string) +(merge-rule "\IeC {\CYRV }" "В" :string) +(merge-rule "\IeC {\CYRYA }" "Я" :string) +(merge-rule "\IeC {\CYRYI }" "Ї" :string) +(merge-rule "\IeC {\CYRYO }" "Ё" :string) +(merge-rule "\IeC {\CYRYU }" "Ю" :string) +(merge-rule "\IeC {\CYRZ }" "З" :string) +(merge-rule "\IeC {\CYRZH }" "Ж" :string) +(merge-rule "\IeC {\cyra }" "а" :string) +(merge-rule "\IeC {\cyrb }" "б" :string) +(merge-rule "\IeC {\cyrc }" "ц" :string) +(merge-rule "\IeC {\cyrch }" "ч" :string) +(merge-rule "\IeC {\cyrd }" "д" :string) +(merge-rule "\IeC {\cyrdje }" "ђ" :string) +(merge-rule "\IeC {\cyrdze }" "ѕ" :string) +(merge-rule "\IeC {\cyrdzhe }" "џ" :string) +(merge-rule "\IeC {\cyre }" "е" :string) +(merge-rule "\IeC {\cyrerev }" "э" :string) +(merge-rule "\IeC {\cyrery }" "ы" :string) +(merge-rule "\IeC {\cyrf }" "ф" :string) +(merge-rule "\IeC {\cyrg }" "г" :string) +(merge-rule "\IeC {\cyrgup }" "ґ" :string) +(merge-rule "\IeC {\cyrh }" "х" :string) +(merge-rule "\IeC {\cyrhrdsn }" "ъ" :string) +(merge-rule "\IeC {\cyri }" "и" :string) +(merge-rule "\IeC {\cyrie }" "є" :string) +(merge-rule "\IeC {\cyrii }" "і" :string) +(merge-rule "\IeC {\cyrishrt }" "й" :string) +(merge-rule "\IeC {\cyrje }" "ј" :string) +(merge-rule "\IeC {\cyrk }" "к" :string) +(merge-rule "\IeC {\cyrl }" "л" :string) +(merge-rule "\IeC {\cyrlje }" "љ" :string) +(merge-rule "\IeC {\cyrm }" "м" :string) +(merge-rule "\IeC {\cyrn }" "н" :string) +(merge-rule "\IeC {\cyrnje }" "њ" :string) +(merge-rule "\IeC {\cyro }" "о" :string) +(merge-rule "\IeC {\cyrp }" "п" :string) +(merge-rule "\IeC {\cyrr }" "р" :string) +(merge-rule "\IeC {\cyrs }" "с" :string) +(merge-rule "\IeC {\cyrsftsn }" "ь" :string) +(merge-rule "\IeC {\cyrsh }" "ш" :string) +(merge-rule "\IeC {\cyrshch }" "щ" :string) +(merge-rule "\IeC {\cyrt }" "т" :string) +(merge-rule "\IeC {\cyrtshe }" "ћ" :string) +(merge-rule "\IeC {\cyru }" "у" :string) +(merge-rule "\IeC {\cyrushrt }" "ў" :string) +(merge-rule "\IeC {\cyrv }" "в" :string) +(merge-rule "\IeC {\cyrya }" "я" :string) +(merge-rule "\IeC {\cyryi }" "ї" :string) +(merge-rule "\IeC {\cyryo }" "ё" :string) +(merge-rule "\IeC {\cyryu }" "ю" :string) +(merge-rule "\IeC {\cyrz }" "з" :string) +(merge-rule "\IeC {\cyrzh }" "ж" :string) diff --git a/docs/build/latex/LICRlatin2utf8.xdy b/docs/build/latex/LICRlatin2utf8.xdy new file mode 100644 index 0000000000000000000000000000000000000000..1d768259cdbc1200244462dcd508e120087972fb --- /dev/null +++ b/docs/build/latex/LICRlatin2utf8.xdy @@ -0,0 +1,239 @@ +;; style file for xindy +;; filename: LICRlatin2utf8.xdy +;; description: style file for xindy which maps back LaTeX Internal +;; Character Representation of letters (as arising in .idx index +;; file) to UTF-8 encoding for correct sorting by xindy. +;; usage: for use with the pdflatex engine, +;; *not* for use with xelatex or lualatex. +;; +;; This is based upon xindy's distributed file tex/inputenc/utf8.xdy. +;; The modifications include: +;; +;; - Updates for compatibility with current LaTeX macro encoding. +;; +;; - Systematic usage of the \IeC {...} mark-up, because mark-up in +;; tex/inputenc/utf8.xdy was using it on seemingly random basis, and +;; Sphinx coercing of xindy usability for both Latin and Cyrillic scripts +;; with pdflatex requires its systematic presence here. +;; +;; - Support for some extra letters: Ÿ, Ŋ, ŋ, Œ, œ, IJ, ij, ȷ and ẞ. +;; +;; Indeed Sphinx needs to support for pdflatex engine all Unicode letters +;; available in TeX T1 font encoding. The above letters are found in +;; that encoding but not in the Latin1, 2, 3 charsets which are those +;; covered by original tex/inputenc/utf8.xdy. +;; +;; - There is a problem that ȷ is not supported out-of-the box by LaTeX +;; with inputenc, one must add explicitly +;; \DeclareUnicodeCharacter{0237}{\j} +;; to preamble of LaTeX document. However this character is not supported +;; by the TeX "times" font used by default by Sphinx for pdflatex engine. +;; +;; **Update**: since LaTeX 2018/12/01, the \j as well as \SS, \k{} and +;; \.{} need no extra user declaration anymore. +;; +;; - ẞ needs \DeclareUnicodeCharacter{1E9E}{\SS} (but ß needs no extra set-up). +;; +;; - U+02DB (˛) and U+02D9 (˙) are also not supported by inputenc +;; out of the box and require +;; \DeclareUnicodeCharacter{02DB}{\k{}} +;; \DeclareUnicodeCharacter{02D9}{\.{}} +;; to be added to preamble. +;; +;; - U+0127 ħ and U+0126 Ħ are absent from TeX T1+TS1 font encodings. +;; +;; - Characters Ŋ and ŋ are not supported by TeX font "times" used by +;; default by Sphinx for pdflatex engine but they are supported by +;; some TeX fonts, in particular by the default LaTeX font for T1 +;; encoding. +;; +;; - " and ~ must be escaped as ~" and resp. ~~ in xindy merge rules. +;; +;; Contributed by the Sphinx team, July 2018. +;; +;; See sphinx.xdy for superior figures, as they are escaped by LaTeX writer. +(merge-rule "\IeC {\textonesuperior }" "¹" :string) +(merge-rule "\IeC {\texttwosuperior }" "²" :string) +(merge-rule "\IeC {\textthreesuperior }" "³" :string) +(merge-rule "\IeC {\'a}" "á" :string) +(merge-rule "\IeC {\'A}" "Á" :string) +(merge-rule "\IeC {\`a}" "à" :string) +(merge-rule "\IeC {\`A}" "À" :string) +(merge-rule "\IeC {\^a}" "â" :string) +(merge-rule "\IeC {\^A}" "Â" :string) +(merge-rule "\IeC {\~"a}" "ä" :string) +(merge-rule "\IeC {\~"A}" "Ä" :string) +(merge-rule "\IeC {\~~a}" "ã" :string) +(merge-rule "\IeC {\~~A}" "Ã" :string) +(merge-rule "\IeC {\c c}" "ç" :string) +(merge-rule "\IeC {\c C}" "Ç" :string) +(merge-rule "\IeC {\'c}" "ć" :string) +(merge-rule "\IeC {\'C}" "Ć" :string) +(merge-rule "\IeC {\^c}" "ĉ" :string) +(merge-rule "\IeC {\^C}" "Ĉ" :string) +(merge-rule "\IeC {\.c}" "ċ" :string) +(merge-rule "\IeC {\.C}" "Ċ" :string) +(merge-rule "\IeC {\c s}" "ş" :string) +(merge-rule "\IeC {\c S}" "Ş" :string) +(merge-rule "\IeC {\c t}" "ţ" :string) +(merge-rule "\IeC {\c T}" "Ţ" :string) +(merge-rule "\IeC {\-}" "­" :string); soft hyphen +(merge-rule "\IeC {\textdiv }" "÷" :string) +(merge-rule "\IeC {\'e}" "é" :string) +(merge-rule "\IeC {\'E}" "É" :string) +(merge-rule "\IeC {\`e}" "è" :string) +(merge-rule "\IeC {\`E}" "È" :string) +(merge-rule "\IeC {\^e}" "ê" :string) +(merge-rule "\IeC {\^E}" "Ê" :string) +(merge-rule "\IeC {\~"e}" "ë" :string) +(merge-rule "\IeC {\~"E}" "Ë" :string) +(merge-rule "\IeC {\^g}" "ĝ" :string) +(merge-rule "\IeC {\^G}" "Ĝ" :string) +(merge-rule "\IeC {\.g}" "ġ" :string) +(merge-rule "\IeC {\.G}" "Ġ" :string) +(merge-rule "\IeC {\^h}" "ĥ" :string) +(merge-rule "\IeC {\^H}" "Ĥ" :string) +(merge-rule "\IeC {\H o}" "ő" :string) +(merge-rule "\IeC {\H O}" "Ő" :string) +(merge-rule "\IeC {\textacutedbl }" "˝" :string) +(merge-rule "\IeC {\H u}" "ű" :string) +(merge-rule "\IeC {\H U}" "Ű" :string) +(merge-rule "\IeC {\ae }" "æ" :string) +(merge-rule "\IeC {\AE }" "Æ" :string) +(merge-rule "\IeC {\textcopyright }" "©" :string) +(merge-rule "\IeC {\c \ }" "¸" :string) +(merge-rule "\IeC {\dh }" "ð" :string) +(merge-rule "\IeC {\DH }" "Ð" :string) +(merge-rule "\IeC {\dj }" "đ" :string) +(merge-rule "\IeC {\DJ }" "Đ" :string) +(merge-rule "\IeC {\guillemotleft }" "«" :string) +(merge-rule "\IeC {\guillemotright }" "»" :string) +(merge-rule "\IeC {\'\i }" "í" :string) +(merge-rule "\IeC {\`\i }" "ì" :string) +(merge-rule "\IeC {\^\i }" "î" :string) +(merge-rule "\IeC {\~"\i }" "ï" :string) +(merge-rule "\IeC {\i }" "ı" :string) +(merge-rule "\IeC {\^\j }" "ĵ" :string) +(merge-rule "\IeC {\k {}}" "˛" :string) +(merge-rule "\IeC {\l }" "ł" :string) +(merge-rule "\IeC {\L }" "Ł" :string) +(merge-rule "\IeC {\nobreakspace }" " " :string) +(merge-rule "\IeC {\o }" "ø" :string) +(merge-rule "\IeC {\O }" "Ø" :string) +(merge-rule "\IeC {\textsterling }" "£" :string) +(merge-rule "\IeC {\textparagraph }" "¶" :string) +(merge-rule "\IeC {\ss }" "ß" :string) +(merge-rule "\IeC {\textsection }" "§" :string) +(merge-rule "\IeC {\textbrokenbar }" "¦" :string) +(merge-rule "\IeC {\textcent }" "¢" :string) +(merge-rule "\IeC {\textcurrency }" "¤" :string) +(merge-rule "\IeC {\textdegree }" "°" :string) +(merge-rule "\IeC {\textexclamdown }" "¡" :string) +(merge-rule "\IeC {\texthbar }" "ħ" :string) +(merge-rule "\IeC {\textHbar }" "Ħ" :string) +(merge-rule "\IeC {\textonehalf }" "½" :string) +(merge-rule "\IeC {\textonequarter }" "¼" :string) +(merge-rule "\IeC {\textordfeminine }" "ª" :string) +(merge-rule "\IeC {\textordmasculine }" "º" :string) +(merge-rule "\IeC {\textperiodcentered }" "·" :string) +(merge-rule "\IeC {\textquestiondown }" "¿" :string) +(merge-rule "\IeC {\textregistered }" "®" :string) +(merge-rule "\IeC {\textthreequarters }" "¾" :string) +(merge-rule "\IeC {\textyen }" "¥" :string) +(merge-rule "\IeC {\th }" "þ" :string) +(merge-rule "\IeC {\TH }" "Þ" :string) +(merge-rule "\IeC {\'I}" "Í" :string) +(merge-rule "\IeC {\`I}" "Ì" :string) +(merge-rule "\IeC {\^I}" "Î" :string) +(merge-rule "\IeC {\~"I}" "Ï" :string) +(merge-rule "\IeC {\.I}" "İ" :string) +(merge-rule "\IeC {\^J}" "Ĵ" :string) +(merge-rule "\IeC {\k a}" "ą" :string) +(merge-rule "\IeC {\k A}" "Ą" :string) +(merge-rule "\IeC {\k e}" "ę" :string) +(merge-rule "\IeC {\k E}" "Ę" :string) +(merge-rule "\IeC {\'l}" "ĺ" :string) +(merge-rule "\IeC {\'L}" "Ĺ" :string) +(merge-rule "\IeC {\textlnot }" "¬" :string) +(merge-rule "\IeC {\textmu }" "µ" :string) +(merge-rule "\IeC {\'n}" "ń" :string) +(merge-rule "\IeC {\'N}" "Ń" :string) +(merge-rule "\IeC {\~~n}" "ñ" :string) +(merge-rule "\IeC {\~~N}" "Ñ" :string) +(merge-rule "\IeC {\'o}" "ó" :string) +(merge-rule "\IeC {\'O}" "Ó" :string) +(merge-rule "\IeC {\`o}" "ò" :string) +(merge-rule "\IeC {\`O}" "Ò" :string) +(merge-rule "\IeC {\^o}" "ô" :string) +(merge-rule "\IeC {\^O}" "Ô" :string) +(merge-rule "\IeC {\~"o}" "ö" :string) +(merge-rule "\IeC {\~"O}" "Ö" :string) +(merge-rule "\IeC {\~~o}" "õ" :string) +(merge-rule "\IeC {\~~O}" "Õ" :string) +(merge-rule "\IeC {\textpm }" "±" :string) +(merge-rule "\IeC {\r a}" "å" :string) +(merge-rule "\IeC {\r A}" "Å" :string) +(merge-rule "\IeC {\'r}" "ŕ" :string) +(merge-rule "\IeC {\'R}" "Ŕ" :string) +(merge-rule "\IeC {\r u}" "ů" :string) +(merge-rule "\IeC {\r U}" "Ů" :string) +(merge-rule "\IeC {\'s}" "ś" :string) +(merge-rule "\IeC {\'S}" "Ś" :string) +(merge-rule "\IeC {\^s}" "ŝ" :string) +(merge-rule "\IeC {\^S}" "Ŝ" :string) +(merge-rule "\IeC {\textasciidieresis }" "¨" :string) +(merge-rule "\IeC {\textasciimacron }" "¯" :string) +(merge-rule "\IeC {\.{}}" "˙" :string) +(merge-rule "\IeC {\textasciiacute }" "´" :string) +(merge-rule "\IeC {\texttimes }" "×" :string) +(merge-rule "\IeC {\u a}" "ă" :string) +(merge-rule "\IeC {\u A}" "Ă" :string) +(merge-rule "\IeC {\u g}" "ğ" :string) +(merge-rule "\IeC {\u G}" "Ğ" :string) +(merge-rule "\IeC {\textasciibreve }" "˘" :string) +(merge-rule "\IeC {\'u}" "ú" :string) +(merge-rule "\IeC {\'U}" "Ú" :string) +(merge-rule "\IeC {\`u}" "ù" :string) +(merge-rule "\IeC {\`U}" "Ù" :string) +(merge-rule "\IeC {\^u}" "û" :string) +(merge-rule "\IeC {\^U}" "Û" :string) +(merge-rule "\IeC {\~"u}" "ü" :string) +(merge-rule "\IeC {\~"U}" "Ü" :string) +(merge-rule "\IeC {\u u}" "ŭ" :string) +(merge-rule "\IeC {\u U}" "Ŭ" :string) +(merge-rule "\IeC {\v c}" "č" :string) +(merge-rule "\IeC {\v C}" "Č" :string) +(merge-rule "\IeC {\v d}" "ď" :string) +(merge-rule "\IeC {\v D}" "Ď" :string) +(merge-rule "\IeC {\v e}" "ě" :string) +(merge-rule "\IeC {\v E}" "Ě" :string) +(merge-rule "\IeC {\v l}" "ľ" :string) +(merge-rule "\IeC {\v L}" "Ľ" :string) +(merge-rule "\IeC {\v n}" "ň" :string) +(merge-rule "\IeC {\v N}" "Ň" :string) +(merge-rule "\IeC {\v r}" "ř" :string) +(merge-rule "\IeC {\v R}" "Ř" :string) +(merge-rule "\IeC {\v s}" "š" :string) +(merge-rule "\IeC {\v S}" "Š" :string) +(merge-rule "\IeC {\textasciicaron }" "ˇ" :string) +(merge-rule "\IeC {\v t}" "ť" :string) +(merge-rule "\IeC {\v T}" "Ť" :string) +(merge-rule "\IeC {\v z}" "ž" :string) +(merge-rule "\IeC {\v Z}" "Ž" :string) +(merge-rule "\IeC {\'y}" "ý" :string) +(merge-rule "\IeC {\'Y}" "Ý" :string) +(merge-rule "\IeC {\~"y}" "ÿ" :string) +(merge-rule "\IeC {\'z}" "ź" :string) +(merge-rule "\IeC {\'Z}" "Ź" :string) +(merge-rule "\IeC {\.z}" "ż" :string) +(merge-rule "\IeC {\.Z}" "Ż" :string) +;; letters not in Latin1, 2, 3 but available in TeX T1 font encoding +(merge-rule "\IeC {\~"Y}" "Ÿ" :string) +(merge-rule "\IeC {\NG }" "Ŋ" :string) +(merge-rule "\IeC {\ng }" "ŋ" :string) +(merge-rule "\IeC {\OE }" "Œ" :string) +(merge-rule "\IeC {\oe }" "œ" :string) +(merge-rule "\IeC {\IJ }" "IJ" :string) +(merge-rule "\IeC {\ij }" "ij" :string) +(merge-rule "\IeC {\j }" "ȷ" :string) +(merge-rule "\IeC {\SS }" "ẞ" :string) diff --git a/docs/build/latex/LatinRules.xdy b/docs/build/latex/LatinRules.xdy new file mode 100644 index 0000000000000000000000000000000000000000..b20fbbb83a55f6286917183d07d549846b0b8ed9 --- /dev/null +++ b/docs/build/latex/LatinRules.xdy @@ -0,0 +1,611 @@ +;; Common Lisp style file for xindy +;; filename: LatinRules.xdy +;; +;; Please note that this data file deliberately uses strings +;; with single non-ascii bytes. This is intentional and +;; follows the usage observed in similar xindy support files. +;; +;; It is based upon xindy's files lang/general/utf8.xdy and +;; lang/general/utf8-lang.xdy which implement +;; "a general sorting order for Western European languages". +;; +;; The aim for Sphinx is to be able to index in a Cyrillic document +;; also terms using the Latin alphabets, inclusive of letters +;; with diacritics. To this effect the xindy rules from lang/general +;; got manually re-coded to avoid collisions with the encoding +;; done by xindy for sorting words in Cyrillic languages, which was +;; observed not to use bytes with octal encoding 0o266 or higher. +;; +;; So here we use only 0o266 or higher bytes. +;; (Ŋ, ŋ, IJ, and ij are absent from +;; lang/general/utf8.xdy and not included here.) +;; Contributed by the Sphinx team, 2018. + +(define-letter-group "A" :prefixes ("")) +(define-letter-group "B" :after "A" :prefixes ("")) +(define-letter-group "C" :after "B" :prefixes ("")) +(define-letter-group "D" :after "C" :prefixes ("")) +(define-letter-group "E" :after "D" :prefixes ("")) +(define-letter-group "F" :after "E" :prefixes ("")) +(define-letter-group "G" :after "F" :prefixes ("")) +(define-letter-group "H" :after "G" :prefixes ("")) +(define-letter-group "I" :after "H" :prefixes ("")) +(define-letter-group "J" :after "I" :prefixes ("")) +(define-letter-group "K" :after "J" :prefixes ("")) +(define-letter-group "L" :after "K" :prefixes ("")) +(define-letter-group "M" :after "L" :prefixes ("")) +(define-letter-group "N" :after "M" :prefixes ("")) +(define-letter-group "O" :after "N" :prefixes ("")) +(define-letter-group "P" :after "O" :prefixes ("")) +(define-letter-group "Q" :after "P" :prefixes ("")) +(define-letter-group "R" :after "Q" :prefixes ("")) +(define-letter-group "S" :after "R" :prefixes ("")) +(define-letter-group "T" :after "S" :prefixes ("")) +(define-letter-group "U" :after "T" :prefixes ("")) +(define-letter-group "V" :after "U" :prefixes ("")) +(define-letter-group "W" :after "V" :prefixes ("")) +(define-letter-group "X" :after "W" :prefixes ("")) +(define-letter-group "Y" :after "X" :prefixes ("")) +(define-letter-group "Z" :after "Y" :prefixes ("")) + +(define-rule-set "sphinx-xy-alphabetize" + + :rules (("À" "" :string) + ("Ă" "" :string) + ("â" "" :string) + ("Ä" "" :string) + ("à" "" :string) + ("Å" "" :string) + ("Ã" "" :string) + ("Á" "" :string) + ("á" "" :string) + ("ã" "" :string) + ("Â" "" :string) + ("ă" "" :string) + ("å" "" :string) + ("ą" "" :string) + ("ä" "" :string) + ("Ą" "" :string) + ("æ" "" :string) + ("Æ" "" :string) + ("ć" "" :string) + ("ĉ" "" :string) + ("ç" "" :string) + ("Č" "" :string) + ("č" "" :string) + ("Ĉ" "" :string) + ("Ç" "" :string) + ("Ć" "" :string) + ("ď" "" :string) + ("Đ" "" :string) + ("Ď" "" :string) + ("đ" "" :string) + ("ê" "" :string) + ("Ę" "" :string) + ("Ě" "" :string) + ("ë" "" :string) + ("ě" "" :string) + ("é" "" :string) + ("È" "" :string) + ("Ë" "" :string) + ("É" "" :string) + ("è" "" :string) + ("Ê" "" :string) + ("ę" "" :string) + ("ĝ" "" :string) + ("ğ" "" :string) + ("Ğ" "" :string) + ("Ĝ" "" :string) + ("ĥ" "" :string) + ("Ĥ" "" :string) + ("Ï" "" :string) + ("Í" "" :string) + ("ï" "" :string) + ("Î" "" :string) + ("î" "" :string) + ("ı" "" :string) + ("İ" "" :string) + ("í" "" :string) + ("Ì" "" :string) + ("ì" "" :string) + ("Ĵ" "" :string) + ("ĵ" "" :string) + ("ł" "" :string) + ("Ł" "" :string) + ("ľ" "" :string) + ("Ľ" "" :string) + ("ń" "" :string) + ("Ń" "" :string) + ("ñ" "" :string) + ("ň" "" :string) + ("Ñ" "" :string) + ("Ň" "" :string) + ("Õ" "" :string) + ("Ő" "" :string) + ("ó" "" :string) + ("ö" "" :string) + ("ô" "" :string) + ("ő" "" :string) + ("Ø" "" :string) + ("Ö" "" :string) + ("õ" "" :string) + ("Ô" "" :string) + ("ø" "" :string) + ("Ó" "" :string) + ("Ò" "" :string) + ("ò" "" :string) + ("œ" "ĺ" :string) + ("Œ" "ĺ" :string) + ("Ř" "" :string) + ("ř" "" :string) + ("Ŕ" "" :string) + ("ŕ" "" :string) + ("ŝ" "" :string) + ("Ś" "" :string) + ("ș" "" :string) + ("ş" "" :string) + ("Ŝ" "" :string) + ("ś" "" :string) + ("Ș" "" :string) + ("š" "" :string) + ("Ş" "" :string) + ("Š" "" :string) + ("ß" "" :string) + ("Ț" "" :string) + ("Ť" "" :string) + ("ț" "" :string) + ("ť" "" :string) + ("û" "" :string) + ("ŭ" "" :string) + ("ů" "" :string) + ("ű" "" :string) + ("ù" "" :string) + ("Ŭ" "" :string) + ("Ù" "" :string) + ("Ű" "" :string) + ("Ü" "" :string) + ("Ů" "" :string) + ("ú" "" :string) + ("Ú" "" :string) + ("Û" "" :string) + ("ü" "" :string) + ("ÿ" "" :string) + ("Ý" "" :string) + ("Ÿ" "" :string) + ("ý" "" :string) + ("Ż" "" :string) + ("Ž" "" :string) + ("Ź" "" :string) + ("ž" "" :string) + ("ż" "" :string) + ("ź" "" :string) + ("a" "" :string) + ("A" "" :string) + ("b" "" :string) + ("B" "" :string) + ("c" "" :string) + ("C" "" :string) + ("d" "" :string) + ("D" "" :string) + ("e" "" :string) + ("E" "" :string) + ("F" "" :string) + ("f" "" :string) + ("G" "" :string) + ("g" "" :string) + ("H" "" :string) + ("h" "" :string) + ("i" "" :string) + ("I" "" :string) + ("J" "" :string) + ("j" "" :string) + ("K" "" :string) + ("k" "" :string) + ("L" "" :string) + ("l" "" :string) + ("M" "" :string) + ("m" "" :string) + ("n" "" :string) + ("N" "" :string) + ("O" "" :string) + ("o" "" :string) + ("p" "" :string) + ("P" "" :string) + ("Q" "" :string) + ("q" "" :string) + ("r" "" :string) + ("R" "" :string) + ("S" "" :string) + ("s" "" :string) + ("t" "" :string) + ("T" "" :string) + ("u" "" :string) + ("U" "" :string) + ("v" "" :string) + ("V" "" :string) + ("W" "" :string) + ("w" "" :string) + ("x" "" :string) + ("X" "" :string) + ("Y" "" :string) + ("y" "" :string) + ("z" "" :string) + ("Z" "" :string) + )) + +(define-rule-set "sphinx-xy-resolve-diacritics" + + :rules (("Ĥ" "" :string) + ("ó" "" :string) + ("ľ" "" :string) + ("Ř" "" :string) + ("ĝ" "" :string) + ("ď" "" :string) + ("Ě" "" :string) + ("ĥ" "" :string) + ("Č" "" :string) + ("Ĵ" "" :string) + ("ě" "" :string) + ("ž" "" :string) + ("Ď" "" :string) + ("ř" "" :string) + ("Ž" "" :string) + ("ı" "" :string) + ("Ť" "" :string) + ("á" "" :string) + ("č" "" :string) + ("Á" "" :string) + ("ň" "" :string) + ("Š" "" :string) + ("Ň" "" :string) + ("ĵ" "" :string) + ("ť" "" :string) + ("Ó" "" :string) + ("ý" "" :string) + ("Ĝ" "" :string) + ("Ú" "" :string) + ("Ľ" "" :string) + ("š" "" :string) + ("Ý" "" :string) + ("ú" "" :string) + ("Ś" "" :string) + ("ć" "" :string) + ("Ł" "" :string) + ("ł" "" :string) + ("ń" "" :string) + ("À" "" :string) + ("Ź" "" :string) + ("à" "" :string) + ("Ń" "" :string) + ("Đ" "" :string) + ("ÿ" "" :string) + ("ś" "" :string) + ("Ğ" "" :string) + ("ğ" "" :string) + ("Ù" "" :string) + ("İ" "" :string) + ("đ" "" :string) + ("ù" "" :string) + ("Ț" "" :string) + ("é" "" :string) + ("ŕ" "" :string) + ("Ć" "" :string) + ("ț" "" :string) + ("ò" "" :string) + ("ź" "" :string) + ("Ò" "" :string) + ("Ÿ" "" :string) + ("Ŕ" "" :string) + ("É" "" :string) + ("ĉ" "" :string) + ("ô" "" :string) + ("Í" "" :string) + ("ŝ" "" :string) + ("Ż" "" :string) + ("Ă" "" :string) + ("Ŝ" "" :string) + ("ñ" "" :string) + ("ŭ" "" :string) + ("í" "" :string) + ("È" "" :string) + ("Ô" "" :string) + ("Ŭ" "" :string) + ("ż" "" :string) + ("Ñ" "" :string) + ("è" "" :string) + ("Ĉ" "" :string) + ("ă" "" :string) + ("â" "" :string) + ("û" "" :string) + ("ê" "" :string) + ("Õ" "" :string) + ("õ" "" :string) + ("ș" "" :string) + ("ç" "" :string) + ("Â" "" :string) + ("Ê" "" :string) + ("Û" "" :string) + ("Ç" "" :string) + ("ì" "" :string) + ("Ì" "" :string) + ("Ș" "" :string) + ("ö" "" :string) + ("Ö" "" :string) + ("ş" "" :string) + ("ů" "" :string) + ("ë" "" :string) + ("ã" "" :string) + ("î" "" :string) + ("Î" "" :string) + ("Ã" "" :string) + ("Ş" "" :string) + ("Ů" "" :string) + ("Ë" "" :string) + ("ï" "" :string) + ("Ő" "" :string) + ("Ï" "" :string) + ("Ę" "" :string) + ("ő" "" :string) + ("Ü" "" :string) + ("Å" "" :string) + ("ü" "" :string) + ("ę" "" :string) + ("å" "" :string) + ("Ä" "" :string) + ("ű" "" :string) + ("Ø" "" :string) + ("ø" "" :string) + ("Ű" "" :string) + ("ä" "" :string) + ("Ą" "" :string) + ("ą" "" :string) + ("œ" "" :string) + ("ß" "" :string) + ("Æ" "" :string) + ("Œ" "" :string) + ("æ" "" :string) + ("e" "" :string) + ("t" "" :string) + ("L" "" :string) + ("Y" "" :string) + ("J" "" :string) + ("a" "" :string) + ("p" "" :string) + ("u" "" :string) + ("j" "" :string) + ("b" "" :string) + ("G" "" :string) + ("U" "" :string) + ("F" "" :string) + ("H" "" :string) + ("i" "" :string) + ("z" "" :string) + ("c" "" :string) + ("l" "" :string) + ("A" "" :string) + ("Q" "" :string) + ("w" "" :string) + ("D" "" :string) + ("R" "" :string) + ("d" "" :string) + ("s" "" :string) + ("r" "" :string) + ("k" "" :string) + ("v" "" :string) + ("m" "" :string) + ("P" "" :string) + ("y" "" :string) + ("K" "" :string) + ("q" "" :string) + ("S" "" :string) + ("I" "" :string) + ("C" "" :string) + ("M" "" :string) + ("Z" "" :string) + ("T" "" :string) + ("W" "" :string) + ("B" "" :string) + ("h" "" :string) + ("x" "" :string) + ("X" "" :string) + ("f" "" :string) + ("E" "" :string) + ("V" "" :string) + ("N" "" :string) + ("O" "" :string) + ("o" "" :string) + ("g" "" :string) + ("n" "" :string) + )) + +(define-rule-set "sphinx-xy-resolve-case" + + :rules (("Ú" "8" :string) + ("Ÿ" "8" :string) + ("Ç" "8" :string) + ("Ĉ" "8" :string) + ("Ŕ" "8" :string) + ("Ľ" "8" :string) + ("Ů" "8" :string) + ("Ý" "8" :string) + ("É" "8" :string) + ("Ë" "8" :string) + ("Ș" "8" :string) + ("Ì" "8" :string) + ("Ê" "8" :string) + ("Ň" "8" :string) + ("Ą" "8" :string) + ("Š" "8" :string) + ("Û" "8" :string) + ("Ş" "8" :string) + ("Ć" "8" :string) + ("Ò" "8" :string) + ("Ĝ" "8" :string) + ("Ñ" "8" :string) + ("Ó" "8" :string) + ("Î" "8" :string) + ("Á" "8" :string) + ("Ã" "8" :string) + ("Ț" "8" :string) + ("Å" "8" :string) + ("Ğ" "8" :string) + ("Ü" "8" :string) + ("È" "8" :string) + ("Ô" "8" :string) + ("İ" "8" :string) + ("Ű" "8" :string) + ("Ù" "8" :string) + ("Ŭ" "8" :string) + ("Â" "8" :string) + ("Ť" "8" :string) + ("Ń" "8" :string) + ("Ď" "8" :string) + ("Ź" "8" :string) + ("Ž" "8" :string) + ("Đ" "8" :string) + ("Ŝ" "8" :string) + ("Č" "8" :string) + ("Ĵ" "8" :string) + ("Ö" "8" :string) + ("Ø" "8" :string) + ("Ż" "8" :string) + ("Ł" "8" :string) + ("Ă" "8" :string) + ("Ě" "8" :string) + ("Ő" "8" :string) + ("Õ" "8" :string) + ("Ę" "8" :string) + ("Ï" "8" :string) + ("À" "8" :string) + ("Ĥ" "8" :string) + ("Ä" "8" :string) + ("Ś" "8" :string) + ("Ř" "8" :string) + ("Í" "8" :string) + ("Œ" "89" :string) + ("Æ" "89" :string) + ("ì" "9" :string) + ("è" "9" :string) + ("ą" "9" :string) + ("š" "9" :string) + ("ú" "9" :string) + ("å" "9" :string) + ("ă" "9" :string) + ("ę" "9" :string) + ("ü" "9" :string) + ("ź" "9" :string) + ("ò" "9" :string) + ("ť" "9" :string) + ("ț" "9" :string) + ("ĵ" "9" :string) + ("ŕ" "9" :string) + ("ż" "9" :string) + ("ä" "9" :string) + ("ý" "9" :string) + ("ù" "9" :string) + ("á" "9" :string) + ("é" "9" :string) + ("č" "9" :string) + ("ň" "9" :string) + ("ś" "9" :string) + ("ø" "9" :string) + ("í" "9" :string) + ("đ" "9" :string) + ("ı" "9" :string) + ("ğ" "9" :string) + ("î" "9" :string) + ("ã" "9" :string) + ("à" "9" :string) + ("ř" "9" :string) + ("ő" "9" :string) + ("ů" "9" :string) + ("ș" "9" :string) + ("ÿ" "9" :string) + ("ë" "9" :string) + ("ŭ" "9" :string) + ("ç" "9" :string) + ("ű" "9" :string) + ("ñ" "9" :string) + ("õ" "9" :string) + ("ě" "9" :string) + ("ş" "9" :string) + ("ž" "9" :string) + ("ĝ" "9" :string) + ("ŝ" "9" :string) + ("ń" "9" :string) + ("û" "9" :string) + ("ł" "9" :string) + ("ď" "9" :string) + ("ĥ" "9" :string) + ("ê" "9" :string) + ("ô" "9" :string) + ("ĉ" "9" :string) + ("â" "9" :string) + ("ć" "9" :string) + ("ï" "9" :string) + ("ö" "9" :string) + ("ľ" "9" :string) + ("ó" "9" :string) + ("æ" "99" :string) + ("ß" "99" :string) + ("œ" "99" :string) + ("N" "8" :string) + ("V" "8" :string) + ("O" "8" :string) + ("X" "8" :string) + ("E" "8" :string) + ("P" "8" :string) + ("K" "8" :string) + ("T" "8" :string) + ("Z" "8" :string) + ("M" "8" :string) + ("C" "8" :string) + ("I" "8" :string) + ("S" "8" :string) + ("B" "8" :string) + ("W" "8" :string) + ("D" "8" :string) + ("R" "8" :string) + ("H" "8" :string) + ("F" "8" :string) + ("Q" "8" :string) + ("A" "8" :string) + ("G" "8" :string) + ("U" "8" :string) + ("J" "8" :string) + ("Y" "8" :string) + ("L" "8" :string) + ("o" "9" :string) + ("n" "9" :string) + ("g" "9" :string) + ("x" "9" :string) + ("f" "9" :string) + ("y" "9" :string) + ("q" "9" :string) + ("h" "9" :string) + ("w" "9" :string) + ("s" "9" :string) + ("d" "9" :string) + ("v" "9" :string) + ("k" "9" :string) + ("r" "9" :string) + ("m" "9" :string) + ("z" "9" :string) + ("c" "9" :string) + ("i" "9" :string) + ("l" "9" :string) + ("b" "9" :string) + ("j" "9" :string) + ("a" "9" :string) + ("p" "9" :string) + ("u" "9" :string) + ("t" "9" :string) + ("e" "9" :string) + )) + +(use-rule-set :run 0 + :rule-set ("sphinx-xy-alphabetize")) +(use-rule-set :run 1 + :rule-set ("sphinx-xy-resolve-diacritics")) +(use-rule-set :run 2 + :rule-set ("sphinx-xy-resolve-case")) diff --git a/docs/build/latex/Makefile b/docs/build/latex/Makefile new file mode 100644 index 0000000000000000000000000000000000000000..3d4f1c958ee7da6e19b2d5f86f5c2de1afa3f7d2 --- /dev/null +++ b/docs/build/latex/Makefile @@ -0,0 +1,65 @@ +# Makefile for Sphinx LaTeX output + +ALLDOCS = $(basename $(wildcard *.tex)) +ALLPDF = $(addsuffix .pdf,$(ALLDOCS)) +ALLDVI = $(addsuffix .dvi,$(ALLDOCS)) +ALLXDV = +ALLPS = $(addsuffix .ps,$(ALLDOCS)) + +# Prefix for archive names +ARCHIVEPREFIX = +# Additional LaTeX options (passed via variables in latexmkrc/latexmkjarc file) +export LATEXOPTS ?= +# Additional latexmk options +LATEXMKOPTS ?= +# format: pdf or dvi (used only by archive targets) +FMT = pdf + +LATEX = latexmk -dvi +PDFLATEX = latexmk -pdf -dvi- -ps- + + +%.dvi: %.tex FORCE_MAKE + $(LATEX) $(LATEXMKOPTS) '$<' + +%.ps: %.dvi + dvips '$<' + +%.pdf: %.tex FORCE_MAKE + $(PDFLATEX) $(LATEXMKOPTS) '$<' + +all: $(ALLPDF) + +all-dvi: $(ALLDVI) + +all-ps: $(ALLPS) + +all-pdf: $(ALLPDF) + +zip: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + zip -q -r -9 $(ARCHIVEPREFIX)docs-$(FMT).zip $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +tar: all-$(FMT) + mkdir $(ARCHIVEPREFIX)docs-$(FMT) + cp $(ALLPDF) $(ARCHIVEPREFIX)docs-$(FMT) + tar cf $(ARCHIVEPREFIX)docs-$(FMT).tar $(ARCHIVEPREFIX)docs-$(FMT) + rm -r $(ARCHIVEPREFIX)docs-$(FMT) + +gz: tar + # -n to omit mtime from gzip headers + gzip -n -9 < $(ARCHIVEPREFIX)docs-$(FMT).tar > $(ARCHIVEPREFIX)docs-$(FMT).tar.gz + +bz2: tar + bzip2 -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +xz: tar + xz -9 -k $(ARCHIVEPREFIX)docs-$(FMT).tar + +clean: + rm -f *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz $(ALLPDF) $(ALLDVI) $(ALLXDV) *.fls *.fdb_latexmk + +.PHONY: all all-pdf all-dvi all-ps clean zip tar gz bz2 xz +.PHONY: FORCE_MAKE \ No newline at end of file diff --git a/docs/build/latex/aim-cu.aux b/docs/build/latex/aim-cu.aux new file mode 100644 index 0000000000000000000000000000000000000000..22f61e1454834e12e46bd35757331fc98ff45790 --- /dev/null +++ b/docs/build/latex/aim-cu.aux @@ -0,0 +1,72 @@ +\relax +\providecommand\hyper@newdestlabel[2]{} +\providecommand\babel@aux[2]{} +\@nameuse{bbl@beforestart} +\providecommand\HyperFirstAtBeginDocument{\AtBeginDocument} +\HyperFirstAtBeginDocument{\ifx\hyper@anchor\@undefined +\global\let\oldcontentsline\contentsline +\gdef\contentsline#1#2#3#4{\oldcontentsline{#1}{#2}{#3}} +\global\let\oldnewlabel\newlabel +\gdef\newlabel#1#2{\newlabelxx{#1}#2} +\gdef\newlabelxx#1#2#3#4#5#6{\oldnewlabel{#1}{{#2}{#3}}} +\AtEndDocument{\ifx\hyper@anchor\@undefined +\let\contentsline\oldcontentsline +\let\newlabel\oldnewlabel +\fi} +\fi} +\global\let\hyper@last\relax +\gdef\HyperFirstAtBeginDocument#1{#1} +\providecommand\HyField@AuxAddToFields[1]{} +\providecommand\HyField@AuxAddToCoFields[2]{} +\babel@aux{english}{} +\newlabel{index::doc}{{}{1}{}{section*.2}{}} +\@writefile{toc}{\contentsline {chapter}{\numberline {1}Code execution}{3}{chapter.1}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\newlabel{index:code-execution}{{1}{3}{Code execution}{chapter.1}{}} +\@writefile{toc}{\contentsline {chapter}{\numberline {2}Demo}{5}{chapter.2}\protected@file@percent } +\@writefile{lof}{\addvspace {10\p@ }} +\@writefile{lot}{\addvspace {10\p@ }} +\newlabel{index:demo}{{2}{5}{Demo}{chapter.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.1}Methods}{5}{section.2.1}\protected@file@percent } +\newlabel{ref_method:methods}{{2.1}{5}{Methods}{section.2.1}{}} +\newlabel{ref_method::doc}{{2.1}{5}{Methods}{section.2.1}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.1.1}CUSUM parameters}{5}{subsection.2.1.1}\protected@file@percent } +\newlabel{ref_method:cusum-parameters}{{2.1.1}{5}{CUSUM parameters}{subsection.2.1.1}{}} +\@writefile{lot}{\contentsline {table}{\numberline {1}{\ignorespaces CUSUM parameters}}{5}{table.2.1}\protected@file@percent } +\newlabel{ref_method:id1}{{1}{5}{CUSUM parameters}{table.2.1}{}} +\@writefile{toc}{\contentsline {subsection}{\numberline {2.1.2}CUSUM chart}{5}{subsection.2.1.2}\protected@file@percent } +\newlabel{ref_method:cusum-chart}{{2.1.2}{5}{CUSUM chart}{subsection.2.1.2}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.2}CUSUM}{6}{section.2.2}\protected@file@percent } +\newlabel{ref_cusum:module-package.cusum}{{2.2}{6}{CUSUM}{section.2.2}{}} +\newlabel{ref_cusum:cusum}{{2.2}{6}{CUSUM}{section.2.2}{}} +\newlabel{ref_cusum::doc}{{2.2}{6}{CUSUM}{section.2.2}{}} +\newlabel{ref_cusum:package.cusum.CUSUM}{{2.2}{6}{CUSUM}{section*.3}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.change_detection}{{2.2}{6}{CUSUM}{section*.4}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.compute_cusum}{{2.2}{6}{CUSUM}{section*.5}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.initialize}{{2.2}{6}{CUSUM}{section*.6}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.plot_cusum_plotly}{{2.2}{6}{CUSUM}{section*.7}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.plot_input_metric_plotly}{{2.2}{6}{CUSUM}{section*.8}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.plot_input_metric_plotly_raw}{{2.2}{6}{CUSUM}{section*.9}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.set_df_metric_csv}{{2.2}{7}{CUSUM}{section*.10}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.set_df_metric_default}{{2.2}{7}{CUSUM}{section*.11}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.set_init_stats}{{2.2}{7}{CUSUM}{section*.12}{}} +\newlabel{ref_cusum:package.cusum.CUSUM.set_timeline}{{2.2}{7}{CUSUM}{section*.13}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.3}ARLTheoretical}{7}{section.2.3}\protected@file@percent } +\newlabel{ref_theoretical:module-package.ARLTheoretical}{{2.3}{7}{ARLTheoretical}{section.2.3}{}} +\newlabel{ref_theoretical:arltheoretical}{{2.3}{7}{ARLTheoretical}{section.2.3}{}} +\newlabel{ref_theoretical::doc}{{2.3}{7}{ARLTheoretical}{section.2.3}{}} +\newlabel{ref_theoretical:package.ARLTheoretical.get_ARL_1}{{2.3}{7}{ARLTheoretical}{section*.14}{}} +\newlabel{ref_theoretical:package.ARLTheoretical.get_ARL_1_h_mu1_k}{{2.3}{7}{ARLTheoretical}{section*.15}{}} +\newlabel{ref_theoretical:package.ARLTheoretical.get_ref_value}{{2.3}{8}{ARLTheoretical}{section*.16}{}} +\newlabel{ref_theoretical:package.ARLTheoretical.get_ref_value_k}{{2.3}{8}{ARLTheoretical}{section*.17}{}} +\@writefile{toc}{\contentsline {section}{\numberline {2.4}Utils}{8}{section.2.4}\protected@file@percent } +\newlabel{ref_utils:module-package.utils}{{2.4}{8}{Utils}{section.2.4}{}} +\newlabel{ref_utils:utils}{{2.4}{8}{Utils}{section.2.4}{}} +\newlabel{ref_utils::doc}{{2.4}{8}{Utils}{section.2.4}{}} +\newlabel{ref_utils:package.utils.get_greattable_as_html}{{2.4}{8}{Utils}{section*.18}{}} +\newlabel{ref_utils:package.utils.populate_summary_table_ARL0_k}{{2.4}{8}{Utils}{section*.19}{}} +\newlabel{ref_utils:package.utils.populate_summary_table_ARL1_k}{{2.4}{9}{Utils}{section*.20}{}} +\@writefile{toc}{\contentsline {chapter}{Python Module Index}{11}{section*.21}\protected@file@percent } +\@writefile{toc}{\contentsline {chapter}{Index}{13}{section*.22}\protected@file@percent } +\gdef \@abspage@last{17} diff --git a/docs/build/latex/aim-cu.fdb_latexmk b/docs/build/latex/aim-cu.fdb_latexmk new file mode 100644 index 0000000000000000000000000000000000000000..737f741e64715342bcde8d679d6fd6334c493f16 --- /dev/null +++ b/docs/build/latex/aim-cu.fdb_latexmk @@ -0,0 +1,189 @@ +# Fdb version 3 +["makeindex aim-cu.idx"] 1738357406 "aim-cu.idx" "aim-cu.ind" "aim-cu" 1738357408 + "aim-cu.idx" 1738358436 3264 3c74a69915c90a0e849d9c12c67a7017 "pdflatex" + (generated) + "aim-cu.ilg" + "aim-cu.ind" +["pdflatex"] 1738357407 "aim-cu.tex" "aim-cu.pdf" "aim-cu" 1738357408 + "/etc/texmf/web2c/texmf.cnf" 1738181709 475 c0e671620eb5563b2130f56340a5fde8 "" + "/usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map" 1577235249 3524 cb3e574dea2d1052e39280babc910dc8 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/jknappen/ec/ecrm1000.tfm" 1136768653 3584 adb004a0c8e7c46ee66cad73671f37b4 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm" 1246382020 1004 54797486969f23fa377b128694d548df "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm" 1246382020 916 f87d7c45f9c908e672703b83b72241a3 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm" 1246382020 924 9904cf1d39e9767e7a3622f2a125a565 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm" 1246382020 928 2dc8d444221b7a635bb58038579b861a "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm" 1246382020 908 2921f8a10601f252058503cc6570e581 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm" 1246382020 940 75ac932a52f80982a9f8ea75d03a34cf "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm" 1246382020 940 228d6584342e91276bf566bcf9716b83 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm" 1136768653 992 662f679a0b3d2d53c1b94050fdaa3f50 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm" 1136768653 1524 4414a8315f39513458b80dfc63bff03a "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm" 1136768653 1288 655e228510b4c2a1abe905c368440826 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr17.tfm" 1136768653 1292 296a67155bdbfc32aa9c636f21e91433 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm" 1136768653 1124 6c73e740cf17375f03eec0ee63599741 "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm" 1136768653 1436 f00b2a275be56a8355f5c3b07a5a7a4c "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm" 1136768653 1384 8943063000d26272532f74ca134dfecd "" + "/usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xttsl.tfm" 1136768653 1624 fb8f48c6308ace0a799f9278aba03e18 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb" 1248133631 36299 5f9df58c2139e7edcf37c8fca4bd384d "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb" 1248133631 36281 c355509802a035cadc5f15869451dcee "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb" 1248133631 35752 024fb6c41858982481f6968b5fc26508 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb" 1248133631 32569 5e5ddc8df908dea60932f3c484a54c0d "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb" 1136849748 26580 8886cc7827569e05fd10df25f221aef6 "" + "/usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb" 1136849748 26301 f08b3c26ea42c3177a262c2ac37d6a91 "" + "/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii" 1461363279 71627 94eb9990bed73c364d7f53f960cc8c5b "" + "/usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty" 1575674566 24708 5584a51a7101caf7e6bbf1fc27d8f7b1 "" + "/usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf" 1496785618 7008 9ff5fdcc865b01beca2b0fe4a46231d4 "" + "/usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty" 1643231327 147419 2058c0f5e6893b19c8f3ce95d177646c "" + "/usr/share/texlive/texmf-dist/tex/generic/babel/txtbabel.def" 1643231327 5233 d5e383ed66bf272b71b1a90b596e21c6 "" + "/usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty" 1576625341 40635 c40361e206be584d448876bba8a64a3b "" + "/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty" 1576016050 33961 6b5c75130e435b2bfdb9f480a09a39f9 "" + "/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty" 1576625273 7734 b98cbb34c81f667027c1e3ebdbfce34b "" + "/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty" 1576625223 8371 9d55b8bd010bc717624922fb3477d92e "" + "/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty" 1583617216 6501 4011d89d9621e0b0901138815ba5ff29 "" + "/usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty" 1572645307 1057 525c2192b5febbd8c1f662c9468335bb "" + "/usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty" 1575499628 8356 7bbb2c2373aa810be568c29e333da8ed "" + "/usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty" 1576625065 31769 002a487f55041f8e805cfbf6385ffd97 "" + "/usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty" 1576878844 5412 d5a2436094cd7be85769db90f29250a6 "" + "/usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty" 1576624944 13807 952b0226d4efca026f0e19dd266dcc22 "" + "/usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty" 1600895880 17859 4409f8f50cd365c68e684407e5350b1b "" + "/usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty" 1576015897 19007 15924f7228aca6c6d184b115f4baa231 "" + "/usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty" 1593379760 20089 80423eac55aa175305d35b49e04fe23b "" + "/usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty" 1576624663 7008 f92eaa0a3872ed622bbf538217cd2ab7 "" + "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty" 1359763108 5949 3f3fd50a8cc94c3d4cbf4fc66cd3df1c "" + "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty" 1359763108 13829 94730e64147574077f8ecfea9bb69af4 "" + "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd" 1359763108 961 6518c6525a34feb5e8250ffa91731cff "" + "/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd" 1359763108 961 d02606146ba5601b5645f987c92e6193 "" + "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty" 1622667781 2222 da905dc1db75412efd2d8f67739f0596 "" + "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty" 1622667781 4173 bc0410bcccdff806d6132d3c1ef35481 "" + "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty" 1636758526 87648 07fbb6e9169e00cb2a2f40b31b2dbf3c "" + "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty" 1636758526 4128 8eea906621b6639f7ba476a472036bbe "" + "/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty" 1636758526 2444 926f379cc60fcf0c6e3fee2223b4370d "" + "/usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty" 1576191570 19336 ce7ae9438967282886b3b036cfad1e4d "" + "/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty" 1576625391 3935 57aa3c3e203a5c2effb4d2bd2efbc323 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty" 1622581934 3137 2366459cfce784001c7405ed16a872fb "" + "/usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty" 1636758526 3034 3bfb87122e6fa8758225c0dd3cbaceba "" + "/usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty" 1636758526 2462 754d6b31b2ab5a09bb72c348ace2ec75 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty" 1622581934 4946 461cc78f6f26901410d9f1d725079cc6 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty" 1622581934 5049 969aec05d5f39c43f8005910498fcf90 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty" 1636758526 1939 e44505a18ba4edebb8b70993e32c6350 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/report.cls" 1636758526 23203 8fbc410e29d3fd675970d5f9698c9c11 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo" 1636758526 8448 96f18c76bf608a36ee6fbf021ac1dd32 "" + "/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty" 1622581934 2894 55431114fc0e491ecee275edafd6c881 "" + "/usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty" 1579038678 6078 f1cb470c9199e7110a27851508ed7a5c "" + "/usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty" 1264379041 1311 063f8536a047a2d9cb1803321f793f37 "" + "/usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty" 1612650595 3574 ddc11a0ae1c579d351ed20d2319ad422 "" + "/usr/share/texlive/texmf-dist/tex/latex/cmap/ot1.cmap" 1177721415 1207 4e0d96772f0d338847cbfb4eca683c81 "" + "/usr/share/texlive/texmf-dist/tex/latex/cmap/t1.cmap" 1215522782 1938 beaa4a8467aa0074076e0e19f2992e29 "" + "/usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty" 1579991017 10793 d0af3aa11e27ae35ba4685b17597b122 "" + "/usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty" 1449445679 9937 7eb94c47265a0108f7a319db3c3b58b0 "" + "/usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty" 1579991033 13886 d1306dcf79a944f6988e688c1785f9ce "" + "/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty" 1601931149 46845 3b58f70c6e861a13d927bff09d35ecbc "" + "/usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty" 1612734021 17086 7ed8cbc4d361ec87392817e0dd4f65ec "" + "/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty" 1640123156 44023 c6f2f55a2bb9630fba10bfd488a5addd "" + "/usr/share/texlive/texmf-dist/tex/latex/float/float.sty" 1137110151 6749 16d2656a1984957e674b149555f1ea1d "" + "/usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty" 1292029257 19488 fdd52eb173b3197d748e1ec25acb042f "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty" 1622837620 1796 b613081fb73f572330a4c23f125aae34 "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def" 1622837620 107888 1633cdc16ba7668f2631413ef15f922e "" + "/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty" 1622837620 7431 6f96168cb69798b45fb68c05af9b56b0 "" + "/usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty" 1338588508 22449 7ec15c16d0d66790f28e90343c5434a3 "" + "/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty" 1578002852 41601 9cf6c5257b1bc7af01a58859749dd37a "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg" 1459978653 1213 620bba36b25224fa9b7e1ccb4ecb76fd "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg" 1465944070 1224 978390e9c2234eab29404bc21b268d1e "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def" 1601931164 19103 48d29b6e2a64cb717117ef65f107b404 "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty" 1639603921 7197 eb6c1ebf41667a05cb50c23c19d5e8bc "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty" 1622581934 18399 7e40f80366dffb22c0e7b70517db5cb4 "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty" 1636758526 7996 a8fb260d598dcaf305a7ae7b9c3e3229 "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty" 1622581934 2671 4de6781a30211fe0ea4c672e4a2a8166 "" + "/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty" 1636758526 4009 187ea2dc3194cd5a76cd99a8d7a6c4d0 "" + "/usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty" 1580250785 17914 4c28a13fc3d975e6e81c9bea1d697276 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def" 1623096352 49890 0bb76a5b745d92e86aed6f3f93e334f0 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def" 1623096352 1777 940b1aa83773bc035eb882e8d6842769 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty" 1623096352 230915 97a8817f13de4e61bbc3592cb2caa995 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty" 1612734870 13242 133e617c5eebffdd05e421624022b267 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def" 1623096352 14132 c9404e8e78123ef0d1007c34d1d6da51 "" + "/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def" 1623096352 117004 86586f287ddfad919a0a4bd68934277a "" + "/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty" 1602274869 22521 d2fceb764a442a2001d257ef11db7618 "" + "/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def" 1642022539 29921 f0f4f870357ebfb8fe58ed9ed4ee9b92 "" + "/usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty" 1642805374 6107 429b3b241150e53f86ce666eb492861e "" + "/usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty" 1642022539 4674 ac560df2ef76ab2c406a4948a48f79f8 "" + "/usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty" 1642022539 6758 7d9d899cbbfc962fbc4bb93f4c69eec2 "" + "/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg" 1279039959 678 4792914a8f45be57bb98413425e4c7af "" + "/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty" 1575499565 5766 13a9e8766c47f30327caf893ece86ac8 "" + "/usr/share/texlive/texmf-dist/tex/latex/mmap/oml.cmap" 1215649417 1866 c1c12138091b4a8edd4a24a940e6f792 "" + "/usr/share/texlive/texmf-dist/tex/latex/mmap/oms.cmap" 1215649417 2370 3b1f71b14b974f07cef532db09ae9ee0 "" + "/usr/share/texlive/texmf-dist/tex/latex/mmap/omx.cmap" 1215649417 3001 252c8ca42b06a22cb1a11c0e47790c6e "" + "/usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty" 1364856750 852 0e34dbb72efc69fa07602405ad95585e "" + "/usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty" 1575152444 3822 b53c749cd81352b4679a35b0dafefb95 "" + "/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty" 1615762720 4288 94714aa7f535440f33181fec52a31963 "" + "/usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def" 1454715303 1168 efb94e82cc1584d4f62679f3487b5339 "" + "/usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg" 1454715303 1920 2185073db458618f4a8a794158cf3681 "" + "/usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty" 1601586370 30933 ccdcd551eb516817cc8f41862254e6e7 "" + "/usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty" 1576624809 9878 9e94e8fa600d95f9c7731bb21dfb67a4 "" + "/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty" 1575674187 9715 b051d5b493d9fe5f4bc251462d039e5f "" + "/usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty" 1403566480 13791 8c83287d79183c3bf58fd70871e8a70b "" + "/usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty" 1625518490 48833 3b7b4cfab1a3d15596bfd3772a77ab65 "" + "/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty" 1636758526 12694 6c23725d50ab9d1e2d3ce482c58ffcf3 "" + "/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty" 1636758526 12892 3ffe092fc7f5d1cb9866f1bcb071d0d6 "" + "/usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty" 1636758526 32262 2bb622a0aa56c4a7a5cbdfe9d122c15a "" + "/usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd" 1137111002 1324 7b6c95370a64cd8c7620cbefefb53dba "" + "/usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty" 1334873510 1048 517e01cde97c1c0baf72e69d43aa5a2e "" + "/usr/share/texlive/texmf-dist/tex/latex/url/url.sty" 1388531844 12796 8edb7d69a20b857904dd0ea757c14ec9 "" + "/usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty" 1238697683 10894 d359a13923460b2a73d4312d613554c8 "" + "/usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty" 1137111090 26220 3701aebf80ccdef248c0c20dd062fea9 "" + "/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty" 1635798903 56029 3f7889dab51d620aa43177c391b7b190 "" + "/usr/share/texlive/texmf-dist/web2c/texmf.cnf" 1644012257 39432 7155514e09a3d69036fac785183a21c2 "" + "/usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ec.enc" 1529098226 2457 aaabbccba4df2a7f7371410ee4e075a3 "" + "/usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ts1.enc" 1529098226 3124 3813fd4c981d99822890a2861b0d274c "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm" 1480098718 11796 b7bc3db132e822d2872ea50ba8fa7cc0 "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvbi.tfm" 1480098718 12396 e65c2800bb94ee6ae6e4fdf18f68fa2e "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvr.tfm" 1480098718 12084 374c5b7e91efcc10472ab8e61f66d36b "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmb.tfm" 1480098718 11484 431d8013ae6931f9326b9a0f492d2a5e "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmr.tfm" 1480098718 11504 0b76b46eb90907e684139293e03c466a "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmri.tfm" 1480098718 11356 da1519f442d8a49b81c86cbaf25ef79f "" + "/usr/share/texmf/fonts/tfm/public/tex-gyre/ts1-qtmr.tfm" 1480098718 1600 20cdf11dab97d5d39e847571f9314407 "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qhvb.pfb" 1480098745 112164 176018dd42fcc60204173fa10e357da5 "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qhvbi.pfb" 1480098745 104926 77ce2f0433ac7fd33dbe9968d127e4fb "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qhvr.pfb" 1480098745 110045 c159829aa6d7d99f1777bb40c90b8157 "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qtmb.pfb" 1480098745 131776 4be3e220f990dc716f91bb7965c09237 "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qtmr.pfb" 1480098745 133302 8dca243a80ecf4cfe00077d4bd995bd7 "" + "/usr/share/texmf/fonts/type1/public/tex-gyre/qtmri.pfb" 1480098745 129669 aaf12ebd0b807d452087fc34bde5bd7d "" + "/usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd" 1480098840 2378 01e898189bf06467f2f6fe33decbff09 "" + "/usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd" 1480098840 1638 7cc855d1dc7c12c1858f209a4ef88c4a "" + "/usr/share/texmf/tex/latex/tex-gyre/tgheros.sty" 1480098840 2130 2b41e80713f78d339e74c19d96fe70a1 "" + "/usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty" 1480098840 2211 af9b7d12507105a58a3e8e926996b827 "" + "/usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd" 1480098840 1160 de7b1cf70edab73c9f1704df2a9fdbbd "" + "/usr/share/texmf/web2c/texmf.cnf" 1644012257 39432 7155514e09a3d69036fac785183a21c2 "" + "/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map" 1738182452 4379155 98693266ff65f58d9f98aff394de12d2 "" + "/var/lib/texmf/web2c/pdftex/pdflatex.fmt" 1738182460 2802951 8e81926bd8c7925ef7f2c2ab47027050 "" + "aim-cu.aux" 1738358436 4977 b0b6b27bafd72138494739b6d289d3f0 "pdflatex" + "aim-cu.ind" 1738358434 2518 d1db4b42b3661be20e444f491e183348 "makeindex aim-cu.idx" + "aim-cu.out" 1738358436 1030 dc97e87c01af9ac4fcbaa2ffec7da0d3 "pdflatex" + "aim-cu.tex" 1738358432 29091 bfa568e17d0962b6cf433c7640f5f12a "" + "aim-cu.toc" 1738358436 710 855f53881d687323850cac77f4e31bf0 "pdflatex" + "sphinx.sty" 1732720504 54119 967a674353157928503df7cae9b6165e "" + "sphinxhighlight.sty" 1738358432 7553 83fb52292c17957d9f4aadcb28c57a87 "" + "sphinxlatexadmonitions.sty" 1732720504 19110 2855832b1a32f04033523b9919260ac9 "" + "sphinxlatexcontainers.sty" 1732720504 900 d61f923db071a7b54d3cee8a1e6935d3 "" + "sphinxlatexgraphics.sty" 1732720504 4918 c9266041d02bc615d54b890e96e3acd3 "" + "sphinxlatexindbibtoc.sty" 1732720504 2065 1f1f215c304208004fc0522855b3b127 "" + "sphinxlatexlists.sty" 1732720504 5138 98bcb41aa6ecb6cc5c1a6a7c936cb8a8 "" + "sphinxlatexliterals.sty" 1732720504 45860 fa61a279a7f157481590da017e0c6962 "" + "sphinxlatexnumfig.sty" 1732720504 5419 aeaffe9a9d596e3663201bb873b06758 "" + "sphinxlatexobjects.sty" 1732720504 14353 ece39b9f5052a425b12c0b91f2bcd818 "" + "sphinxlatexshadowbox.sty" 1732720504 8437 cec78b6bb66e95d214da9fd42b1af598 "" + "sphinxlatexstyleheadings.sty" 1732720504 3742 2a2cc6aa695b2f8c98eb9ee104e5fc6f "" + "sphinxlatexstylepage.sty" 1732720504 2671 e63daf3b9f0f8a387a8b4ba09c515982 "" + "sphinxlatexstyletext.sty" 1732720504 6759 9e932c65374cfb62686485d331bc975c "" + "sphinxlatextables.sty" 1732720504 57643 7f1013c2fa11942370d867527bdda568 "" + "sphinxmanual.cls" 1732720504 4241 7b0d7a37df7b5715fb0dbd585c52ecdb "" + "sphinxmessages.sty" 1738358432 745 3f5fcd6cdd7964ed608767954a8ced6f "" + "sphinxoptionsgeometry.sty" 1732720504 2060 6c27b3eba37bde592ae8908ab2c1ac0f "" + "sphinxoptionshyperref.sty" 1732720504 1093 e468489bae7631a7f387b4b0f7bc15d4 "" + "sphinxpackageboxes.sty" 1732720504 36106 1be2053eb1cb9b083b3a75e3657bcb24 "" + "sphinxpackagefootnote.sty" 1732720504 15330 2fb656b6ce8cd1f6aba2d1c508fb51e5 "" + (generated) + "aim-cu.aux" + "aim-cu.idx" + "aim-cu.log" + "aim-cu.out" + "aim-cu.pdf" + "aim-cu.toc" diff --git a/docs/build/latex/aim-cu.fls b/docs/build/latex/aim-cu.fls new file mode 100644 index 0000000000000000000000000000000000000000..0a45e4008fa56c70f61945d6af16d1c07860cba2 --- /dev/null +++ b/docs/build/latex/aim-cu.fls @@ -0,0 +1,1367 @@ +PWD /home/dhaval.kadia/code/rst/cusum/publish/AIM-CU/docs/build/latex +INPUT /etc/texmf/web2c/texmf.cnf +INPUT /usr/share/texmf/web2c/texmf.cnf +INPUT /usr/share/texlive/texmf-dist/web2c/texmf.cnf +INPUT /var/lib/texmf/web2c/pdftex/pdflatex.fmt +INPUT aim-cu.tex +OUTPUT aim-cu.log +INPUT ./sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT sphinxmanual.cls +INPUT ./sphinxmanual.cls +INPUT sphinxmanual.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/report.cls +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +INPUT /usr/share/texlive/texmf-dist/fonts/map/fontname/texfonts.map +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/jknappen/ec/ecrm1000.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/t1.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/t1.cmap +OUTPUT aim-cu.pdf +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/t1.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel/txtbabel.def +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT ./sphinx.sty +INPUT sphinx.sty +INPUT ./sphinx.sty +INPUT sphinx.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT ./sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT sphinxoptionshyperref.sty +INPUT ./sphinxoptionshyperref.sty +INPUT sphinxoptionshyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT sphinxoptionsgeometry.sty +INPUT ./sphinxoptionsgeometry.sty +INPUT sphinxoptionsgeometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/float/float.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT sphinxlatexgraphics.sty +INPUT ./sphinxlatexgraphics.sty +INPUT sphinxlatexgraphics.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT sphinxpackageboxes.sty +INPUT ./sphinxpackageboxes.sty +INPUT sphinxpackageboxes.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT sphinxlatexadmonitions.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT sphinxlatexadmonitions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT sphinxpackagefootnote.sty +INPUT ./sphinxpackagefootnote.sty +INPUT sphinxpackagefootnote.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT sphinxlatexliterals.sty +INPUT ./sphinxlatexliterals.sty +INPUT sphinxlatexliterals.sty +INPUT ./sphinxpackageboxes.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT sphinxlatexshadowbox.sty +INPUT ./sphinxlatexshadowbox.sty +INPUT sphinxlatexshadowbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +INPUT ./sphinxlatexgraphics.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxlatexadmonitions.sty +INPUT ./sphinxpackageboxes.sty +INPUT ./sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT sphinxlatexcontainers.sty +INPUT ./sphinxlatexcontainers.sty +INPUT sphinxlatexcontainers.sty +INPUT ./sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT sphinxhighlight.sty +INPUT ./sphinxhighlight.sty +INPUT sphinxhighlight.sty +INPUT ./sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT sphinxlatextables.sty +INPUT ./sphinxlatextables.sty +INPUT sphinxlatextables.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +INPUT ./sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT sphinxlatexnumfig.sty +INPUT ./sphinxlatexnumfig.sty +INPUT sphinxlatexnumfig.sty +INPUT ./sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT sphinxlatexlists.sty +INPUT ./sphinxlatexlists.sty +INPUT sphinxlatexlists.sty +INPUT ./sphinxpackagefootnote.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT sphinxlatexindbibtoc.sty +INPUT ./sphinxlatexindbibtoc.sty +INPUT sphinxlatexindbibtoc.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +INPUT ./sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT sphinxlatexstylepage.sty +INPUT ./sphinxlatexstylepage.sty +INPUT sphinxlatexstylepage.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT sphinxlatexstyleheadings.sty +INPUT ./sphinxlatexstyleheadings.sty +INPUT sphinxlatexstyleheadings.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +INPUT ./sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT sphinxlatexstyletext.sty +INPUT ./sphinxlatexstyletext.sty +INPUT sphinxlatexstyletext.sty +INPUT ./sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT sphinxlatexobjects.sty +INPUT ./sphinxlatexobjects.sty +INPUT sphinxlatexobjects.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/url/url.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/atbegshi/atbegshi.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/atveryend/atveryend.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +INPUT ./sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT sphinxmessages.sty +INPUT ./sphinxmessages.sty +INPUT sphinxmessages.sty +OUTPUT aim-cu.idx +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmr.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +INPUT ./aim-cu.aux +INPUT aim-cu.aux +INPUT aim-cu.aux +OUTPUT aim-cu.aux +INPUT /usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-helper.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def +INPUT /usr/share/texlive/texmf-dist/tex/latex/graphics/color.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +INPUT /usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +INPUT /usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +INPUT ./aim-cu.out +INPUT aim-cu.out +INPUT ./aim-cu.out +INPUT aim-cu.out +INPUT ./aim-cu.out +INPUT aim-cu.out +INPUT ./aim-cu.out +INPUT aim-cu.out +INPUT ./aim-cu.out +INPUT ./aim-cu.out +OUTPUT aim-cu.out +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvr.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvbi.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvbi.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr17.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/ot1.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/ot1.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/cmap/ot1.cmap +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmr12.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oml.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oml.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oml.cmap +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmmi12.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oms.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oms.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/oms.cmap +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmsy10.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/omx.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/omx.cmap +INPUT /usr/share/texlive/texmf-dist/tex/latex/mmap/omx.cmap +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/cm/cmex10.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam10.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm10.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm +INPUT /var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmr.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvr.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvb.tfm +INPUT ./aim-cu.toc +INPUT aim-cu.toc +INPUT aim-cu.toc +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmb.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/cmextra/cmex7.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam7.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msam5.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm7.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/amsfonts/symbols/msbm5.tfm +OUTPUT aim-cu.toc +INPUT /usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd +INPUT /usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ts1-qtmr.tfm +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +INPUT /usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xtt.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmr.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qhvr.tfm +INPUT /usr/share/texmf/fonts/tfm/public/tex-gyre/ec-qtmri.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xbtt.tfm +INPUT /usr/share/texlive/texmf-dist/fonts/tfm/public/txfonts/t1xttsl.tfm +INPUT ./aim-cu.ind +INPUT aim-cu.ind +INPUT ./aim-cu.ind +INPUT aim-cu.ind +INPUT aim-cu.aux +INPUT ./aim-cu.out +INPUT ./aim-cu.out +INPUT /usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ec.enc +INPUT /usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ts1.enc +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi10.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmmi7.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmr10.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/amsfonts/cm/cmsy10.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qhvb.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qhvbi.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qhvr.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qtmb.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qtmr.pfb +INPUT /usr/share/texmf/fonts/type1/public/tex-gyre/qtmri.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xbtt.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb +INPUT /usr/share/texlive/texmf-dist/fonts/type1/public/txfonts/t1xtt.pfb diff --git a/docs/build/latex/aim-cu.idx b/docs/build/latex/aim-cu.idx new file mode 100644 index 0000000000000000000000000000000000000000..faf8cbc9fb26f3aa3d7168822cafabdd92990e42 --- /dev/null +++ b/docs/build/latex/aim-cu.idx @@ -0,0 +1,24 @@ +\indexentry{module@\spxentry{module}!package.cusum@\spxentry{package.cusum}|hyperpage}{6} +\indexentry{package.cusum@\spxentry{package.cusum}!module@\spxentry{module}|hyperpage}{6} +\indexentry{CUSUM (class in package.cusum)@\spxentry{CUSUM}\spxextra{class in package.cusum}|hyperpage}{6} +\indexentry{change\_detection() (package.cusum.CUSUM method)@\spxentry{change\_detection()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{compute\_cusum() (package.cusum.CUSUM method)@\spxentry{compute\_cusum()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{initialize() (package.cusum.CUSUM method)@\spxentry{initialize()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{plot\_cusum\_plotly() (package.cusum.CUSUM method)@\spxentry{plot\_cusum\_plotly()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{plot\_input\_metric\_plotly() (package.cusum.CUSUM method)@\spxentry{plot\_input\_metric\_plotly()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{plot\_input\_metric\_plotly\_raw() (package.cusum.CUSUM method)@\spxentry{plot\_input\_metric\_plotly\_raw()}\spxextra{package.cusum.CUSUM method}|hyperpage}{6} +\indexentry{set\_df\_metric\_csv() (package.cusum.CUSUM method)@\spxentry{set\_df\_metric\_csv()}\spxextra{package.cusum.CUSUM method}|hyperpage}{7} +\indexentry{set\_df\_metric\_default() (package.cusum.CUSUM method)@\spxentry{set\_df\_metric\_default()}\spxextra{package.cusum.CUSUM method}|hyperpage}{7} +\indexentry{set\_init\_stats() (package.cusum.CUSUM method)@\spxentry{set\_init\_stats()}\spxextra{package.cusum.CUSUM method}|hyperpage}{7} +\indexentry{set\_timeline() (package.cusum.CUSUM method)@\spxentry{set\_timeline()}\spxextra{package.cusum.CUSUM method}|hyperpage}{7} +\indexentry{module@\spxentry{module}!package.ARLTheoretical@\spxentry{package.ARLTheoretical}|hyperpage}{7} +\indexentry{package.ARLTheoretical@\spxentry{package.ARLTheoretical}!module@\spxentry{module}|hyperpage}{7} +\indexentry{get\_ARL\_1() (in module package.ARLTheoretical)@\spxentry{get\_ARL\_1()}\spxextra{in module package.ARLTheoretical}|hyperpage}{7} +\indexentry{get\_ARL\_1\_h\_mu1\_k() (in module package.ARLTheoretical)@\spxentry{get\_ARL\_1\_h\_mu1\_k()}\spxextra{in module package.ARLTheoretical}|hyperpage}{7} +\indexentry{get\_ref\_value() (in module package.ARLTheoretical)@\spxentry{get\_ref\_value()}\spxextra{in module package.ARLTheoretical}|hyperpage}{8} +\indexentry{get\_ref\_value\_k() (in module package.ARLTheoretical)@\spxentry{get\_ref\_value\_k()}\spxextra{in module package.ARLTheoretical}|hyperpage}{8} +\indexentry{module@\spxentry{module}!package.utils@\spxentry{package.utils}|hyperpage}{8} +\indexentry{package.utils@\spxentry{package.utils}!module@\spxentry{module}|hyperpage}{8} +\indexentry{get\_greattable\_as\_html() (in module package.utils)@\spxentry{get\_greattable\_as\_html()}\spxextra{in module package.utils}|hyperpage}{8} +\indexentry{populate\_summary\_table\_ARL0\_k() (in module package.utils)@\spxentry{populate\_summary\_table\_ARL0\_k()}\spxextra{in module package.utils}|hyperpage}{8} +\indexentry{populate\_summary\_table\_ARL1\_k() (in module package.utils)@\spxentry{populate\_summary\_table\_ARL1\_k()}\spxextra{in module package.utils}|hyperpage}{9} diff --git a/docs/build/latex/aim-cu.ilg b/docs/build/latex/aim-cu.ilg new file mode 100644 index 0000000000000000000000000000000000000000..52039e98cb05835a6305b886ec8154bc78fa2a0d --- /dev/null +++ b/docs/build/latex/aim-cu.ilg @@ -0,0 +1,7 @@ +This is makeindex, version 2.15 [TeX Live 2022/dev] (kpathsea + Thai support). +Scanning style file ./python.ist.......done (7 attributes redefined, 0 ignored). +Scanning input file aim-cu.idx....done (24 entries accepted, 0 rejected). +Sorting entries....done (116 comparisons). +Generating output file aim-cu.ind....done (57 lines written, 0 warnings). +Output written in aim-cu.ind. +Transcript written in aim-cu.ilg. diff --git a/docs/build/latex/aim-cu.ind b/docs/build/latex/aim-cu.ind new file mode 100644 index 0000000000000000000000000000000000000000..7ff51179ece16537c74e187890babaff6245fdbf --- /dev/null +++ b/docs/build/latex/aim-cu.ind @@ -0,0 +1,57 @@ +\begin{sphinxtheindex} +\let\bigletter\sphinxstyleindexlettergroup +\let\spxpagem \sphinxstyleindexpagemain +\let\spxentry \sphinxstyleindexentry +\let\spxextra \sphinxstyleindexextra + + \bigletter C + \item \spxentry{change\_detection()}\spxextra{package.cusum.CUSUM method}, \hyperpage{6} + \item \spxentry{compute\_cusum()}\spxextra{package.cusum.CUSUM method}, \hyperpage{6} + \item \spxentry{CUSUM}\spxextra{class in package.cusum}, \hyperpage{6} + + \indexspace + \bigletter G + \item \spxentry{get\_ARL\_1()}\spxextra{in module package.ARLTheoretical}, \hyperpage{7} + \item \spxentry{get\_ARL\_1\_h\_mu1\_k()}\spxextra{in module package.ARLTheoretical}, + \hyperpage{7} + \item \spxentry{get\_greattable\_as\_html()}\spxextra{in module package.utils}, \hyperpage{8} + \item \spxentry{get\_ref\_value()}\spxextra{in module package.ARLTheoretical}, \hyperpage{8} + \item \spxentry{get\_ref\_value\_k()}\spxextra{in module package.ARLTheoretical}, \hyperpage{8} + + \indexspace + \bigletter I + \item \spxentry{initialize()}\spxextra{package.cusum.CUSUM method}, \hyperpage{6} + + \indexspace + \bigletter M + \item \spxentry{module} + \subitem \spxentry{package.ARLTheoretical}, \hyperpage{7} + \subitem \spxentry{package.cusum}, \hyperpage{6} + \subitem \spxentry{package.utils}, \hyperpage{8} + + \indexspace + \bigletter P + \item \spxentry{package.ARLTheoretical} + \subitem \spxentry{module}, \hyperpage{7} + \item \spxentry{package.cusum} + \subitem \spxentry{module}, \hyperpage{6} + \item \spxentry{package.utils} + \subitem \spxentry{module}, \hyperpage{8} + \item \spxentry{plot\_cusum\_plotly()}\spxextra{package.cusum.CUSUM method}, \hyperpage{6} + \item \spxentry{plot\_input\_metric\_plotly()}\spxextra{package.cusum.CUSUM method}, + \hyperpage{6} + \item \spxentry{plot\_input\_metric\_plotly\_raw()}\spxextra{package.cusum.CUSUM method}, + \hyperpage{6} + \item \spxentry{populate\_summary\_table\_ARL0\_k()}\spxextra{in module package.utils}, + \hyperpage{8} + \item \spxentry{populate\_summary\_table\_ARL1\_k()}\spxextra{in module package.utils}, + \hyperpage{9} + + \indexspace + \bigletter S + \item \spxentry{set\_df\_metric\_csv()}\spxextra{package.cusum.CUSUM method}, \hyperpage{7} + \item \spxentry{set\_df\_metric\_default()}\spxextra{package.cusum.CUSUM method}, \hyperpage{7} + \item \spxentry{set\_init\_stats()}\spxextra{package.cusum.CUSUM method}, \hyperpage{7} + \item \spxentry{set\_timeline()}\spxextra{package.cusum.CUSUM method}, \hyperpage{7} + +\end{sphinxtheindex} diff --git a/docs/build/latex/aim-cu.log b/docs/build/latex/aim-cu.log new file mode 100644 index 0000000000000000000000000000000000000000..3517685ae02d654d5d7ff5041ad833b0f4888190 --- /dev/null +++ b/docs/build/latex/aim-cu.log @@ -0,0 +1,1026 @@ +This is pdfTeX, Version 3.141592653-2.6-1.40.22 (TeX Live 2022/dev/Debian) (preloaded format=pdflatex 2025.1.29) 31 JAN 2025 16:03 +entering extended mode + restricted \write18 enabled. + %&-line parsing enabled. +**aim-cu.tex +(./aim-cu.tex +LaTeX2e <2021-11-15> patch level 1 +L3 programming layer <2022-01-21> (./sphinxmanual.cls +Document Class: sphinxmanual 2019/12/01 v2.3.0 Document class (Sphinx manual) +(/usr/share/texlive/texmf-dist/tex/latex/base/report.cls +Document Class: report 2021/10/04 v1.4n Standard LaTeX document class +(/usr/share/texlive/texmf-dist/tex/latex/base/size10.clo +File: size10.clo 2021/10/04 v1.4n Standard LaTeX file (size option) +) +\c@part=\count185 +\c@chapter=\count186 +\c@section=\count187 +\c@subsection=\count188 +\c@subsubsection=\count189 +\c@paragraph=\count190 +\c@subparagraph=\count191 +\c@figure=\count192 +\c@table=\count193 +\abovecaptionskip=\skip47 +\belowcaptionskip=\skip48 +\bibindent=\dimen138 +) +LaTeX Info: Redefining \and on input line 35. +) +(/usr/share/texlive/texmf-dist/tex/latex/base/inputenc.sty +Package: inputenc 2021/02/14 v1.3d Input encoding file +\inpenc@prehook=\toks16 +\inpenc@posthook=\toks17 +) + defining Unicode char U+00A0 (decimal 160) + defining Unicode char U+2500 (decimal 9472) + defining Unicode char U+2502 (decimal 9474) + defining Unicode char U+2514 (decimal 9492) + defining Unicode char U+251C (decimal 9500) + defining Unicode char U+2572 (decimal 9586) + +(/usr/share/texlive/texmf-dist/tex/latex/cmap/cmap.sty +Package: cmap 2021/02/06 v1.0j CMap support: searchable PDF +) +(/usr/share/texlive/texmf-dist/tex/latex/base/fontenc.sty +Package: fontenc 2021/04/29 v2.0v Standard LaTeX package +<>) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsmath.sty +Package: amsmath 2021/10/15 v2.17l AMS math features +\@mathmargin=\skip49 + +For additional information on amsmath, use the `?' option. +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amstext.sty +Package: amstext 2021/08/26 v2.01 AMS text + +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsgen.sty +File: amsgen.sty 1999/11/30 v2.0 generic functions +\@emptytoks=\toks18 +\ex@=\dimen139 +)) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsbsy.sty +Package: amsbsy 1999/11/29 v1.2d Bold Symbols +\pmbraise@=\dimen140 +) +(/usr/share/texlive/texmf-dist/tex/latex/amsmath/amsopn.sty +Package: amsopn 2021/08/26 v2.02 operator names +) +\inf@bad=\count194 +LaTeX Info: Redefining \frac on input line 234. +\uproot@=\count195 +\leftroot@=\count196 +LaTeX Info: Redefining \overline on input line 399. +\classnum@=\count197 +\DOTSCASE@=\count198 +LaTeX Info: Redefining \ldots on input line 496. +LaTeX Info: Redefining \dots on input line 499. +LaTeX Info: Redefining \cdots on input line 620. +\Mathstrutbox@=\box50 +\strutbox@=\box51 +\big@size=\dimen141 +LaTeX Font Info: Redeclaring font encoding OML on input line 743. +LaTeX Font Info: Redeclaring font encoding OMS on input line 744. +\macc@depth=\count199 +\c@MaxMatrixCols=\count266 +\dotsspace@=\muskip16 +\c@parentequation=\count267 +\dspbrk@lvl=\count268 +\tag@help=\toks19 +\row@=\count269 +\column@=\count270 +\maxfields@=\count271 +\andhelp@=\toks20 +\eqnshift@=\dimen142 +\alignsep@=\dimen143 +\tagshift@=\dimen144 +\tagwidth@=\dimen145 +\totwidth@=\dimen146 +\lineht@=\dimen147 +\@envbody=\toks21 +\multlinegap=\skip50 +\multlinetaggap=\skip51 +\mathdisplay@stack=\toks22 +LaTeX Info: Redefining \[ on input line 2938. +LaTeX Info: Redefining \] on input line 2939. +) +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amssymb.sty +Package: amssymb 2013/01/14 v3.01 AMS font symbols + +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/amsfonts.sty +Package: amsfonts 2013/01/14 v3.01 Basic AMSFonts support +\symAMSa=\mathgroup4 +\symAMSb=\mathgroup5 +LaTeX Font Info: Redeclaring math symbol \hbar on input line 98. +LaTeX Font Info: Overwriting math alphabet `\mathfrak' in version `bold' +(Font) U/euf/m/n --> U/euf/b/n on input line 106. +)) +(/usr/share/texlive/texmf-dist/tex/generic/babel/babel.sty +Package: babel 2022/01/26 3.70 The Babel package +\babel@savecnt=\count272 +\U@D=\dimen148 +\l@unhyphenated=\language87 + +(/usr/share/texlive/texmf-dist/tex/generic/babel/txtbabel.def) +\bbl@readstream=\read2 +\bbl@dirlevel=\count273 + +(/usr/share/texlive/texmf-dist/tex/generic/babel-english/english.ldf +Language: english 2017/06/06 v3.3r English support from the babel system +Package babel Info: Hyphen rules for 'canadian' set to \l@english +(babel) (\language0). Reported on input line 102. +Package babel Info: Hyphen rules for 'australian' set to \l@ukenglish +(babel) (\language67). Reported on input line 105. +Package babel Info: Hyphen rules for 'newzealand' set to \l@ukenglish +(babel) (\language67). Reported on input line 108. +)) +(/usr/share/texmf/tex/latex/tex-gyre/tgtermes.sty +Package: tgtermes 2009/09/27 v1.2 TeX Gyre Termes as default roman family + +(/usr/share/texlive/texmf-dist/tex/latex/kvoptions/kvoptions.sty +Package: kvoptions 2020-10-07 v3.14 Key value format for package options (HO) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics/keyval.sty +Package: keyval 2014/10/28 v1.15 key=value parser (DPC) +\KV@toks@=\toks23 +) +(/usr/share/texlive/texmf-dist/tex/generic/ltxcmds/ltxcmds.sty +Package: ltxcmds 2020-05-10 v1.25 LaTeX kernel commands for general use (HO) +) +(/usr/share/texlive/texmf-dist/tex/generic/kvsetkeys/kvsetkeys.sty +Package: kvsetkeys 2019/12/15 v1.18 Key value parser (HO) +))) +(/usr/share/texmf/tex/latex/tex-gyre/tgheros.sty +Package: tgheros 2009/09/27 v1.2 TeX Gyre Heros as default sans serif family +) +(/usr/share/texlive/texmf-dist/tex/latex/fncychap/fncychap.sty +Package: fncychap 2007/07/30 v1.34 LaTeX package (Revised chapters) +\RW=\skip52 +\mylen=\skip53 +\myhi=\skip54 +\px=\skip55 +\py=\skip56 +\pyy=\skip57 +\pxx=\skip58 +\c@AlphaCnt=\count274 +\c@AlphaDecCnt=\count275 +) (./sphinx.sty +Package: sphinx 2024/10/11 v8.1.1 Sphinx LaTeX package (sphinx-doc) + +(/usr/share/texlive/texmf-dist/tex/latex/xcolor/xcolor.sty +Package: xcolor 2021/10/31 v2.13 LaTeX color extensions (UK) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/color.cfg +File: color.cfg 2016/01/02 v1.6 sample color configuration +) +Package xcolor Info: Driver file: pdftex.def on input line 227. + +(/usr/share/texlive/texmf-dist/tex/latex/graphics-def/pdftex.def +File: pdftex.def 2020/10/05 v1.2a Graphics/color driver for pdftex +) +Package xcolor Info: Model `cmy' substituted by `cmy0' on input line 1352. +Package xcolor Info: Model `hsb' substituted by `rgb' on input line 1356. +Package xcolor Info: Model `RGB' extended on input line 1368. +Package xcolor Info: Model `HTML' substituted by `rgb' on input line 1370. +Package xcolor Info: Model `Hsb' substituted by `hsb' on input line 1371. +Package xcolor Info: Model `tHsb' substituted by `hsb' on input line 1372. +Package xcolor Info: Model `HSB' substituted by `hsb' on input line 1373. +Package xcolor Info: Model `Gray' substituted by `gray' on input line 1374. +Package xcolor Info: Model `wave' substituted by `hsb' on input line 1375. +) +(./sphinxoptionshyperref.sty +Package: sphinxoptionshyperref 2021/01/27 hyperref +) (./sphinxoptionsgeometry.sty +Package: sphinxoptionsgeometry 2021/01/27 geometry +) +(/usr/share/texlive/texmf-dist/tex/latex/base/textcomp.sty +Package: textcomp 2020/02/02 v2.0n Standard LaTeX package +) +(/usr/share/texlive/texmf-dist/tex/latex/float/float.sty +Package: float 2001/11/08 v1.3d Float enhancements (AL) +\c@float@type=\count276 +\float@exts=\toks24 +\float@box=\box52 +\@float@everytoks=\toks25 +\@floatcapt=\box53 +) +(/usr/share/texlive/texmf-dist/tex/latex/wrapfig/wrapfig.sty +\wrapoverhang=\dimen149 +\WF@size=\dimen150 +\c@WF@wrappedlines=\count277 +\WF@box=\box54 +\WF@everypar=\toks26 +Package: wrapfig 2003/01/31 v 3.6 +) +(/usr/share/texlive/texmf-dist/tex/latex/capt-of/capt-of.sty +Package: capt-of 2009/12/29 v0.2 standard captions outside of floats +) +(/usr/share/texlive/texmf-dist/tex/latex/tools/multicol.sty +Package: multicol 2021/10/28 v1.9b multicolumn formatting (FMi) +\c@tracingmulticols=\count278 +\mult@box=\box55 +\multicol@leftmargin=\dimen151 +\c@unbalance=\count279 +\c@collectmore=\count280 +\doublecol@number=\count281 +\multicoltolerance=\count282 +\multicolpretolerance=\count283 +\full@width=\dimen152 +\page@free=\dimen153 +\premulticols=\dimen154 +\postmulticols=\dimen155 +\multicolsep=\skip59 +\multicolbaselineskip=\skip60 +\partial@page=\box56 +\last@line=\box57 +\maxbalancingoverflow=\dimen156 +\mult@rightbox=\box58 +\mult@grightbox=\box59 +\mult@firstbox=\box60 +\mult@gfirstbox=\box61 +\@tempa=\box62 +\@tempa=\box63 +\@tempa=\box64 +\@tempa=\box65 +\@tempa=\box66 +\@tempa=\box67 +\@tempa=\box68 +\@tempa=\box69 +\@tempa=\box70 +\@tempa=\box71 +\@tempa=\box72 +\@tempa=\box73 +\@tempa=\box74 +\@tempa=\box75 +\@tempa=\box76 +\@tempa=\box77 +\@tempa=\box78 +\@tempa=\box79 +\@tempa=\box80 +\@tempa=\box81 +\@tempa=\box82 +\@tempa=\box83 +\@tempa=\box84 +\@tempa=\box85 +\@tempa=\box86 +\@tempa=\box87 +\@tempa=\box88 +\@tempa=\box89 +\@tempa=\box90 +\@tempa=\box91 +\@tempa=\box92 +\@tempa=\box93 +\@tempa=\box94 +\@tempa=\box95 +\@tempa=\box96 +\@tempa=\box97 +\c@minrows=\count284 +\c@columnbadness=\count285 +\c@finalcolumnbadness=\count286 +\last@try=\dimen157 +\multicolovershoot=\dimen158 +\multicolundershoot=\dimen159 +\mult@nat@firstbox=\box98 +\colbreak@box=\box99 +\mc@col@check@num=\count287 +) +(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphicx.sty +Package: graphicx 2021/09/16 v1.2d Enhanced LaTeX Graphics (DPC,SPQR) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics/graphics.sty +Package: graphics 2021/03/04 v1.4d Standard LaTeX Graphics (DPC,SPQR) + +(/usr/share/texlive/texmf-dist/tex/latex/graphics/trig.sty +Package: trig 2021/08/11 v1.11 sin cos tan (DPC) +) +(/usr/share/texlive/texmf-dist/tex/latex/graphics-cfg/graphics.cfg +File: graphics.cfg 2016/06/04 v1.11 sample graphics configuration +) +Package graphics Info: Driver file: pdftex.def on input line 107. +) +\Gin@req@height=\dimen160 +\Gin@req@width=\dimen161 +) +(./sphinxlatexgraphics.sty +Package: sphinxlatexgraphics 2024/08/13 v8.1.0 graphics +\spx@image@maxheight=\dimen162 +\spx@image@box=\box100 +) (./sphinxpackageboxes.sty +Package: sphinxpackageboxes 2024/07/01 v7.4.0 advanced colored boxes + +(/usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.sty +Package: pict2e 2020/09/30 v0.4b Improved picture commands (HjG,RN,JT) + +(/usr/share/texlive/texmf-dist/tex/latex/pict2e/pict2e.cfg +File: pict2e.cfg 2016/02/05 v0.1u pict2e configuration for teTeX/TeXLive +) +Package pict2e Info: Driver file: pdftex.def on input line 112. +Package pict2e Info: Driver file for pict2e: p2e-pdftex.def on input line 114. + +(/usr/share/texlive/texmf-dist/tex/latex/pict2e/p2e-pdftex.def +File: p2e-pdftex.def 2016/02/05 v0.1u Driver-dependant file (RN,HjG,JT) +) +\pIIe@GRAPH=\toks27 +\@arclen=\dimen163 +\@arcrad=\dimen164 +\pIIe@tempdima=\dimen165 +\pIIe@tempdimb=\dimen166 +\pIIe@tempdimc=\dimen167 +\pIIe@tempdimd=\dimen168 +\pIIe@tempdime=\dimen169 +\pIIe@tempdimf=\dimen170 +) +(/usr/share/texlive/texmf-dist/tex/latex/ellipse/ellipse.sty +Package: ellipse 2004/11/05 v1.0 .dtx ellipse file +) +\@tempdimd=\dimen171 +\spx@tempboxa=\box101 +\spx@tempboxb=\box102 +\spx@boxes@border@top=\dimen172 +\spx@boxes@border@right=\dimen173 +\spx@boxes@border@bottom=\dimen174 +\spx@boxes@border@left=\dimen175 +\spx@boxes@padding@top=\dimen176 +\spx@boxes@padding@right=\dimen177 +\spx@boxes@padding@bottom=\dimen178 +\spx@boxes@padding@left=\dimen179 +\spx@boxes@shadow@xoffset=\dimen180 +\spx@boxes@shadow@yoffset=\dimen181 +\spx@boxes@radius@topleft@x=\dimen182 +\spx@boxes@radius@topright@x=\dimen183 +\spx@boxes@radius@bottomright@x=\dimen184 +\spx@boxes@radius@bottomleft@x=\dimen185 +\spx@boxes@radius@topleft@y=\dimen186 +\spx@boxes@radius@topright@y=\dimen187 +\spx@boxes@radius@bottomright@y=\dimen188 +\spx@boxes@radius@bottomleft@y=\dimen189 +) +(./sphinxlatexadmonitions.sty +Package: sphinxlatexadmonitions 2024/10/11 v8.1.1 admonitions + +(/usr/share/texlive/texmf-dist/tex/latex/framed/framed.sty +Package: framed 2011/10/22 v 0.96: framed or shaded text with page breaks +\OuterFrameSep=\skip61 +\fb@frw=\dimen190 +\fb@frh=\dimen191 +\FrameRule=\dimen192 +\FrameSep=\dimen193 +) +(./sphinxpackagefootnote.sty +Package: sphinxpackagefootnote 2024/05/17 v7.3.x Sphinx custom footnotehyper pa +ckage (Sphinx team) +\FNH@notes=\box103 +\FNH@toks=\toks28 +\FNH@width=\dimen194 +\c@sphinxfootnotemark=\count288 +) +\spx@notice@border=\dimen195 +\c@sphinxtodo=\count289 +) (./sphinxlatexliterals.sty +Package: sphinxlatexliterals 2024/07/01 v7.4.0 code-blocks and parsed literals + +(/usr/share/texlive/texmf-dist/tex/latex/fancyvrb/fancyvrb.sty +Package: fancyvrb 2021/12/21 4.1b verbatim text (tvz,hv) +\FV@CodeLineNo=\count290 +\FV@InFile=\read3 +\FV@TabBox=\box104 +\c@FancyVerbLine=\count291 +\FV@StepNumber=\count292 +\FV@OutFile=\write3 +) +(/usr/share/texlive/texmf-dist/tex/latex/base/alltt.sty +Package: alltt 2021/01/29 v2.0g defines alltt environment +) +(/usr/share/texlive/texmf-dist/tex/latex/upquote/upquote.sty +Package: upquote 2012/04/19 v1.3 upright-quote and grave-accent glyphs in verba +tim +) +(/usr/share/texlive/texmf-dist/tex/latex/needspace/needspace.sty +Package: needspace 2010/09/12 v1.3d reserve vertical space +) +\sphinxcontinuationbox=\box105 +\sphinxvisiblespacebox=\box106 +\sphinxVerbatim@TitleBox=\box107 +\sphinxVerbatim@ContentsBox=\box108 +) +(./sphinxlatexshadowbox.sty +Package: sphinxlatexshadowbox 2024/07/28 v8.1.0 sphinxShadowBox +) (./sphinxlatexcontainers.sty +Package: sphinxlatexcontainers 2021/05/03 containers +) +(./sphinxhighlight.sty +Package: sphinxhighlight 2022/06/30 stylesheet for highlighting with pygments +) (./sphinxlatextables.sty +Package: sphinxlatextables 2024/07/01 v7.4.0 tables + +(/usr/share/texlive/texmf-dist/tex/latex/tabulary/tabulary.sty +Package: tabulary 2014/06/11 v0.10 tabulary package (DPC) + +(/usr/share/texlive/texmf-dist/tex/latex/tools/array.sty +Package: array 2021/10/04 v2.5f Tabular extension package (FMi) +\col@sep=\dimen196 +\ar@mcellbox=\box109 +\extrarowheight=\dimen197 +\NC@list=\toks29 +\extratabsurround=\skip62 +\backup@length=\skip63 +\ar@cellbox=\box110 +) +\TY@count=\count293 +\TY@linewidth=\dimen198 +\tymin=\dimen199 +\tymax=\dimen256 +\TY@tablewidth=\dimen257 +) +(/usr/share/texlive/texmf-dist/tex/latex/tools/longtable.sty +Package: longtable 2021-09-01 v4.17 Multi-page Table package (DPC) +\LTleft=\skip64 +\LTright=\skip65 +\LTpre=\skip66 +\LTpost=\skip67 +\LTchunksize=\count294 +\LTcapwidth=\dimen258 +\LT@head=\box111 +\LT@firsthead=\box112 +\LT@foot=\box113 +\LT@lastfoot=\box114 +\LT@gbox=\box115 +\LT@cols=\count295 +\LT@rows=\count296 +\c@LT@tables=\count297 +\c@LT@chunks=\count298 +\LT@p@ftn=\toks30 +) +(/usr/share/texlive/texmf-dist/tex/latex/varwidth/varwidth.sty +Package: varwidth 2009/03/30 ver 0.92; Variable-width minipages +\@vwid@box=\box116 +\sift@deathcycles=\count299 +\@vwid@loff=\dimen259 +\@vwid@roff=\dimen260 +) +\sphinx@TY@tablewidth=\dimen261 + +(/usr/share/texlive/texmf-dist/tex/latex/colortbl/colortbl.sty +Package: colortbl 2020/01/04 v1.0e Color table columns (DPC) +\everycr=\toks31 +\minrowclearance=\skip68 +) +\rownum=\count300 + +(/usr/share/texlive/texmf-dist/tex/latex/booktabs/booktabs.sty +Package: booktabs 2020/01/12 v1.61803398 Publication quality tables +\heavyrulewidth=\dimen262 +\lightrulewidth=\dimen263 +\cmidrulewidth=\dimen264 +\belowrulesep=\dimen265 +\belowbottomsep=\dimen266 +\aboverulesep=\dimen267 +\abovetopsep=\dimen268 +\cmidrulesep=\dimen269 +\cmidrulekern=\dimen270 +\defaultaddspace=\dimen271 +\@cmidla=\count301 +\@cmidlb=\count302 +\@aboverulesep=\dimen272 +\@belowrulesep=\dimen273 +\@thisruleclass=\count303 +\@lastruleclass=\count304 +\@thisrulewidth=\dimen274 +)) +(./sphinxlatexnumfig.sty +Package: sphinxlatexnumfig 2024/07/31 v8.1.0 numbering +) (./sphinxlatexlists.sty +Package: sphinxlatexlists 2021/12/20 lists +\spx@lineitemlabel=\toks32 +) +\c@sphinxscope=\count305 + (./sphinxlatexindbibtoc.sty +Package: sphinxlatexindbibtoc 2021/01/27 index, bib., toc + +(/usr/share/texlive/texmf-dist/tex/latex/base/makeidx.sty +Package: makeidx 2021/10/04 v1.0m Standard LaTeX package +)) +(./sphinxlatexstylepage.sty +Package: sphinxlatexstylepage 2021/01/27 page styling + +(/usr/share/texlive/texmf-dist/tex/latex/parskip/parskip.sty +Package: parskip 2021-03-14 v2.0h non-zero parskip adjustments + +(/usr/share/texlive/texmf-dist/tex/latex/etoolbox/etoolbox.sty +Package: etoolbox 2020/10/05 v2.5k e-TeX tools for LaTeX (JAW) +\etb@tempcnta=\count306 +)) +(/usr/share/texlive/texmf-dist/tex/latex/fancyhdr/fancyhdr.sty +Package: fancyhdr 2021/01/28 v4.0.1 Extensive control of page headers and foote +rs +\f@nch@headwidth=\skip69 +\f@nch@O@elh=\skip70 +\f@nch@O@erh=\skip71 +\f@nch@O@olh=\skip72 +\f@nch@O@orh=\skip73 +\f@nch@O@elf=\skip74 +\f@nch@O@erf=\skip75 +\f@nch@O@olf=\skip76 +\f@nch@O@orf=\skip77 +)) +(./sphinxlatexstyleheadings.sty +Package: sphinxlatexstyleheadings 2023/02/11 headings + +(/usr/share/texlive/texmf-dist/tex/latex/titlesec/titlesec.sty +Package: titlesec 2021/07/05 v2.14 Sectioning titles +\ttl@box=\box117 +\beforetitleunit=\skip78 +\aftertitleunit=\skip79 +\ttl@plus=\dimen275 +\ttl@minus=\dimen276 +\ttl@toksa=\toks33 +\titlewidth=\dimen277 +\titlewidthlast=\dimen278 +\titlewidthfirst=\dimen279 +)) +(./sphinxlatexstyletext.sty +Package: sphinxlatexstyletext 2024/07/28 v8.1.0 text styling +) (./sphinxlatexobjects.sty +Package: sphinxlatexobjects 2023/07/23 documentation environments +\sphinxsignaturesep=\skip80 +\sphinxsignaturelistskip=\skip81 +\py@argswidth=\skip82 +\lineblockindentation=\skip83 +\DUlineblockindent=\skip84 +)) +(/usr/share/texlive/texmf-dist/tex/latex/geometry/geometry.sty +Package: geometry 2020/01/02 v5.9 Page Geometry + +(/usr/share/texlive/texmf-dist/tex/generic/iftex/ifvtex.sty +Package: ifvtex 2019/10/25 v1.7 ifvtex legacy package. Use iftex instead. + +(/usr/share/texlive/texmf-dist/tex/generic/iftex/iftex.sty +Package: iftex 2020/03/06 v1.0d TeX engine tests +)) +\Gm@cnth=\count307 +\Gm@cntv=\count308 +\c@Gm@tempcnt=\count309 +\Gm@bindingoffset=\dimen280 +\Gm@wd@mp=\dimen281 +\Gm@odd@mp=\dimen282 +\Gm@even@mp=\dimen283 +\Gm@layoutwidth=\dimen284 +\Gm@layoutheight=\dimen285 +\Gm@layouthoffset=\dimen286 +\Gm@layoutvoffset=\dimen287 +\Gm@dimlist=\toks34 +) +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref.sty +Package: hyperref 2021-06-07 v7.00m Hypertext links for LaTeX + +(/usr/share/texlive/texmf-dist/tex/generic/pdftexcmds/pdftexcmds.sty +Package: pdftexcmds 2020-06-27 v0.33 Utility functions of pdfTeX for LuaTeX (HO +) + +(/usr/share/texlive/texmf-dist/tex/generic/infwarerr/infwarerr.sty +Package: infwarerr 2019/12/03 v1.5 Providing info/warning/error messages (HO) +) +Package pdftexcmds Info: \pdf@primitive is available. +Package pdftexcmds Info: \pdf@ifprimitive is available. +Package pdftexcmds Info: \pdfdraftmode found. +) +(/usr/share/texlive/texmf-dist/tex/generic/kvdefinekeys/kvdefinekeys.sty +Package: kvdefinekeys 2019-12-19 v1.6 Define keys (HO) +) +(/usr/share/texlive/texmf-dist/tex/generic/pdfescape/pdfescape.sty +Package: pdfescape 2019/12/09 v1.15 Implements pdfTeX's escape features (HO) +) +(/usr/share/texlive/texmf-dist/tex/latex/hycolor/hycolor.sty +Package: hycolor 2020-01-27 v1.10 Color options for hyperref/bookmark (HO) +) +(/usr/share/texlive/texmf-dist/tex/latex/letltxmacro/letltxmacro.sty +Package: letltxmacro 2019/12/03 v1.6 Let assignment for LaTeX macros (HO) +) +(/usr/share/texlive/texmf-dist/tex/latex/auxhook/auxhook.sty +Package: auxhook 2019-12-17 v1.6 Hooks for auxiliary files (HO) +) +\@linkdim=\dimen288 +\Hy@linkcounter=\count310 +\Hy@pagecounter=\count311 + +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/pd1enc.def +File: pd1enc.def 2021-06-07 v7.00m Hyperref: PDFDocEncoding definition (HO) +Now handling font encoding PD1 ... +... no UTF-8 mapping file for font encoding PD1 +) +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hyperref-langpatches.def +File: hyperref-langpatches.def 2021-06-07 v7.00m Hyperref: patches for babel la +nguages +) +(/usr/share/texlive/texmf-dist/tex/generic/intcalc/intcalc.sty +Package: intcalc 2019/12/15 v1.3 Expandable calculations with integers (HO) +) +(/usr/share/texlive/texmf-dist/tex/generic/etexcmds/etexcmds.sty +Package: etexcmds 2019/12/15 v1.7 Avoid name clashes with e-TeX commands (HO) +) +\Hy@SavedSpaceFactor=\count312 + +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/puenc.def +File: puenc.def 2021-06-07 v7.00m Hyperref: PDF Unicode definition (HO) +Now handling font encoding PU ... +... no UTF-8 mapping file for font encoding PU +) +Package hyperref Info: Option `unicode' set `true' on input line 4073. +Package hyperref Info: Option `colorlinks' set `true' on input line 4073. +Package hyperref Info: Option `breaklinks' set `true' on input line 4073. +Package hyperref Info: Hyper figures OFF on input line 4192. +Package hyperref Info: Link nesting OFF on input line 4197. +Package hyperref Info: Hyper index ON on input line 4200. +Package hyperref Info: Plain pages OFF on input line 4207. +Package hyperref Info: Backreferencing OFF on input line 4212. +Package hyperref Info: Implicit mode ON; LaTeX internals redefined. +Package hyperref Info: Bookmarks ON on input line 4445. +\c@Hy@tempcnt=\count313 + +(/usr/share/texlive/texmf-dist/tex/latex/url/url.sty +\Urlmuskip=\muskip17 +Package: url 2013/09/16 ver 3.4 Verb mode for urls, etc. +) +LaTeX Info: Redefining \url on input line 4804. +\XeTeXLinkMargin=\dimen289 + +(/usr/share/texlive/texmf-dist/tex/generic/bitset/bitset.sty +Package: bitset 2019/12/09 v1.3 Handle bit-vector datatype (HO) + +(/usr/share/texlive/texmf-dist/tex/generic/bigintcalc/bigintcalc.sty +Package: bigintcalc 2019/12/15 v1.5 Expandable calculations on big integers (HO +) +)) +\Fld@menulength=\count314 +\Field@Width=\dimen290 +\Fld@charsize=\dimen291 +Package hyperref Info: Hyper figures OFF on input line 6076. +Package hyperref Info: Link nesting OFF on input line 6081. +Package hyperref Info: Hyper index ON on input line 6084. +Package hyperref Info: backreferencing OFF on input line 6091. +Package hyperref Info: Link coloring ON on input line 6094. +Package hyperref Info: Link coloring with OCG OFF on input line 6101. +Package hyperref Info: PDF/A mode OFF on input line 6106. +LaTeX Info: Redefining \ref on input line 6146. +LaTeX Info: Redefining \pageref on input line 6150. + +(/usr/share/texlive/texmf-dist/tex/latex/base/atbegshi-ltx.sty +Package: atbegshi-ltx 2021/01/10 v1.0c Emulation of the original atbegshi +package with kernel methods +) +\Hy@abspage=\count315 +\c@Item=\count316 +\c@Hfootnote=\count317 +) +Package hyperref Info: Driver (autodetected): hpdftex. + +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/hpdftex.def +File: hpdftex.def 2021-06-07 v7.00m Hyperref driver for pdfTeX + +(/usr/share/texlive/texmf-dist/tex/latex/base/atveryend-ltx.sty +Package: atveryend-ltx 2020/08/19 v1.0a Emulation of the original atveryend pac +kage +with kernel methods +) +\Fld@listcount=\count318 +\c@bookmark@seq@number=\count319 + +(/usr/share/texlive/texmf-dist/tex/latex/rerunfilecheck/rerunfilecheck.sty +Package: rerunfilecheck 2019/12/05 v1.9 Rerun checks for auxiliary files (HO) + +(/usr/share/texlive/texmf-dist/tex/generic/uniquecounter/uniquecounter.sty +Package: uniquecounter 2019/12/15 v1.4 Provide unlimited unique counter (HO) +) +Package uniquecounter Info: New unique counter `rerunfilecheck' on input line 2 +86. +) +\Hy@SectionHShift=\skip85 +) +(/usr/share/texlive/texmf-dist/tex/latex/oberdiek/hypcap.sty +Package: hypcap 2016/05/16 v1.12 Adjusting the anchors of captions (HO) +) +(./sphinxmessages.sty +Package: sphinxmessages 2019/01/04 v2.0 Localized LaTeX macros (Sphinx team) +) + defining Unicode char U+03BC (decimal 956) + defining Unicode char U+03C3 (decimal 963) +\@indexfile=\write4 +\openout4 = `aim-cu.idx'. + + +Writing index file aim-cu.idx +LaTeX Font Info: Trying to load font information for T1+qtm on input line 76 +. +(/usr/share/texmf/tex/latex/tex-gyre/t1qtm.fd +File: t1qtm.fd 2009/09/25 v1.2 font definition file for T1/qtm +) +(/usr/share/texlive/texmf-dist/tex/latex/l3backend/l3backend-pdftex.def +File: l3backend-pdftex.def 2022-01-12 L3 backend support: PDF output (pdfTeX) +\l__color_backend_stack_int=\count320 +\l__pdf_internal_box=\box118 +) +(./aim-cu.aux) +\openout1 = `aim-cu.aux'. + +LaTeX Font Info: Checking defaults for OML/cmm/m/it on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for OMS/cmsy/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for OT1/cmr/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for T1/cmr/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for TS1/cmr/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for OMX/cmex/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for U/cmr/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for PD1/pdf/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. +LaTeX Font Info: Checking defaults for PU/pdf/m/n on input line 76. +LaTeX Font Info: ... okay on input line 76. + +(/usr/share/texlive/texmf-dist/tex/context/base/mkii/supp-pdf.mkii +[Loading MPS to PDF converter (version 2006.09.02).] +\scratchcounter=\count321 +\scratchdimen=\dimen292 +\scratchbox=\box119 +\nofMPsegments=\count322 +\nofMParguments=\count323 +\everyMPshowfont=\toks35 +\MPscratchCnt=\count324 +\MPscratchDim=\dimen293 +\MPnumerator=\count325 +\makeMPintoPDFobject=\count326 +\everyMPtoPDFconversion=\toks36 +) (/usr/share/texlive/texmf-dist/tex/latex/epstopdf-pkg/epstopdf-base.sty +Package: epstopdf-base 2020-01-24 v2.11 Base part for package epstopdf +Package epstopdf-base Info: Redefining graphics rule for `.eps' on input line 4 +85. + +(/usr/share/texlive/texmf-dist/tex/latex/latexconfig/epstopdf-sys.cfg +File: epstopdf-sys.cfg 2010/07/13 v1.3 Configuration of (r)epstopdf for TeX Liv +e +)) +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5.sty +(/usr/share/texlive/texmf-dist/tex/latex/l3kernel/expl3.sty +Package: expl3 2022-01-21 L3 programming layer (loader) +) +Package: fontawesome5 2021/06/04 v5.15.3 Font Awesome 5 + +(/usr/share/texlive/texmf-dist/tex/latex/l3packages/l3keys2e/l3keys2e.sty +Package: l3keys2e 2022-01-12 LaTeX2e option processing using LaTeX3 keys +) +(/usr/share/texlive/texmf-dist/tex/latex/l3packages/xparse/xparse.sty +Package: xparse 2022-01-12 L3 Experimental document command parser +) +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-generic-help +er.sty +Package: fontawesome5-generic-helper 2021/06/04 v5.15.3 non-uTeX helper for fon +tawesome5 + +(/usr/share/texlive/texmf-dist/tex/latex/fontawesome5/fontawesome5-mapping.def) +)) +\c@literalblock=\count327 + +*geometry* driver: auto-detecting +*geometry* detected driver: pdftex +*geometry* verbose mode - [ preamble ] result: +* driver: pdftex +* paper: letterpaper +* layout: +* layoutoffset:(h,v)=(0.0pt,0.0pt) +* modes: twoside +* h-part:(L,W,R)=(72.26999pt, 469.75502pt, 72.26999pt) +* v-part:(T,H,B)=(72.26999pt, 650.43001pt, 72.26999pt) +* \paperwidth=614.295pt +* \paperheight=794.96999pt +* \textwidth=469.75502pt +* \textheight=650.43001pt +* \oddsidemargin=0.0pt +* \evensidemargin=0.0pt +* \topmargin=-37.0pt +* \headheight=12.0pt +* \headsep=25.0pt +* \topskip=10.0pt +* \footskip=30.0pt +* \marginparwidth=36.135pt +* \marginparsep=11.0pt +* \columnsep=10.0pt +* \skip\footins=9.0pt plus 4.0pt minus 2.0pt +* \hoffset=0.0pt +* \voffset=0.0pt +* \mag=1000 +* \@twocolumnfalse +* \@twosidetrue +* \@mparswitchtrue +* \@reversemarginfalse +* (1in=72.27pt=25.4mm, 1cm=28.453pt) + +Package hyperref Info: Link coloring ON on input line 76. +(/usr/share/texlive/texmf-dist/tex/latex/hyperref/nameref.sty +Package: nameref 2021-04-02 v2.47 Cross-referencing by name of section + +(/usr/share/texlive/texmf-dist/tex/latex/refcount/refcount.sty +Package: refcount 2019/12/15 v3.6 Data extraction from label references (HO) +) +(/usr/share/texlive/texmf-dist/tex/generic/gettitlestring/gettitlestring.sty +Package: gettitlestring 2019/12/15 v1.6 Cleanup title references (HO) +) +\c@section@level=\count328 +) +LaTeX Info: Redefining \ref on input line 76. +LaTeX Info: Redefining \pageref on input line 76. +LaTeX Info: Redefining \nameref on input line 76. + +(./aim-cu.out) (./aim-cu.out) +\@outlinefile=\write5 +\openout5 = `aim-cu.out'. + +Package hyperref Info: Option `pageanchor' set `false' on input line 84. + + +Package hyperref Warning: Token not allowed in a PDF string (Unicode): +(hyperref) removing `\spacefactor' on input line 84. + + +Package hyperref Warning: Token not allowed in a PDF string (Unicode): +(hyperref) removing `\@m' on input line 84. + +LaTeX Font Info: Trying to load font information for T1+qhv on input line 84 +. +(/usr/share/texmf/tex/latex/tex-gyre/t1qhv.fd +File: t1qhv.fd 2009/09/25 v1.2 font definition file for T1/qhv +)<><><><> +LaTeX Font Info: Trying to load font information for U+msa on input line 84. + + (/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsa.fd +File: umsa.fd 2013/01/14 v3.01 AMS symbols A +) +LaTeX Font Info: Trying to load font information for U+msb on input line 84. + + +(/usr/share/texlive/texmf-dist/tex/latex/amsfonts/umsb.fd +File: umsb.fd 2013/01/14 v3.01 AMS symbols B +) +Overfull \hbox (75.98514pt too wide) in paragraph at lines 84--84 + [][] + [] + +[1 + +{/var/lib/texmf/fonts/map/pdftex/updmap/pdftex.map}] [2 + + +] (./aim-cu.toc) +\tf@toc=\write6 +\openout6 = `aim-cu.toc'. + + +[1 + +] [2 + +] +LaTeX Font Info: Trying to load font information for TS1+qtm on input line 9 +7. + (/usr/share/texmf/tex/latex/tex-gyre/ts1qtm.fd +File: ts1qtm.fd 2009/09/25 v1.2 font definition file for TS1/qtm +) [1] [2 + +] +Chapter 1. +LaTeX Font Info: Trying to load font information for T1+txtt on input line 1 +13. +(/usr/share/texlive/texmf-dist/tex/latex/txfonts/t1txtt.fd +File: t1txtt.fd 2000/12/15 v3.1 +) [3] [4 + +] +Chapter 2. + +Underfull \hbox (badness 10000) in paragraph at lines 226--226 +[]\T1/qhv/m/n/10 Pa- + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 226--226 +\T1/qhv/m/n/10 ram-e- + [] + + +Overfull \hbox (3.87894pt too wide) in paragraph at lines 226--226 +[]\T1/qtm/m/n/10 ARL_0| + [] + + +Overfull \hbox (3.87894pt too wide) in paragraph at lines 226--226 +[]\T1/qtm/m/n/10 ARL_1| + [] + +[5] +LaTeX Font Info: Font shape `T1/txtt/b/n' in size <10> not available +(Font) Font shape `T1/txtt/bx/n' tried instead on input line 269. +LaTeX Font Info: Font shape `T1/txtt/m/it' in size <10> not available +(Font) Font shape `T1/txtt/m/sl' tried instead on input line 289. + [6] [7] [8] [9] [10 + +] [11 + + +] (./aim-cu.ind [12 + + +] +Underfull \hbox (badness 10000) in paragraph at lines 8--9 +[]\T1/txtt/m/n/10 change_detection() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 pack-age.c +usum.CUSUM + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 15--17 +[]\T1/txtt/m/n/10 get_ARL_1_h_mu1_k() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 in mod-ul +e pack- + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 19--20 +[]\T1/txtt/m/n/10 get_ref_value_k() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 in mod-ule +pack- + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 40--41 +[]\T1/txtt/m/n/10 plot_cusum_plotly() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 pack-age. +cusum.CUSUM + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 41--43 +[]\T1/txtt/m/n/10 plot_input_metric_plotly() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 pa +ck- + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 43--45 +[]\T1/txtt/m/n/10 plot_input_metric_plotly_raw() \T1/qtm/m/n/10 (\T1/qtm/m/it/1 +0 pack- + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 45--47 +[]\T1/txtt/m/n/10 populate_summary_table_ARL0_k() \T1/qtm/m/n/10 (\T1/qtm/m/it/ +10 in mod-ule + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 47--49 +[]\T1/txtt/m/n/10 populate_summary_table_ARL1_k() \T1/qtm/m/n/10 (\T1/qtm/m/it/ +10 in mod-ule + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 52--53 +[]\T1/txtt/m/n/10 set_df_metric_csv() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 pack-age. +cusum.CUSUM + [] + + +Underfull \hbox (badness 10000) in paragraph at lines 53--54 +[]\T1/txtt/m/n/10 set_df_metric_default() \T1/qtm/m/n/10 (\T1/qtm/m/it/10 pack- +age.cusum.CUSUM + [] + +[13 + +]) (./aim-cu.aux) +Package rerunfilecheck Info: File `aim-cu.out' has not changed. +(rerunfilecheck) Checksum: DC97E87C01AF9AC4FCBAA2FFEC7DA0D3;1030. + ) +Here is how much of TeX's memory you used: + 19961 strings out of 478287 + 359276 string characters out of 5849289 + 633421 words of memory out of 5000000 + 37705 multiletter control sequences out of 15000+600000 + 520533 words of font info for 69 fonts, out of 8000000 for 9000 + 1142 hyphenation exceptions out of 8191 + 70i,16n,83p,1195b,643s stack positions out of 5000i,500n,10000p,200000b,80000s +{/usr/share/texmf/fonts/enc/dvips/tex-gyre/q-ec.enc}{/usr/share/texmf/fonts/e +nc/dvips/tex-gyre/q-ts1.enc} +Output written on aim-cu.pdf (17 pages, 214164 bytes). +PDF statistics: + 252 PDF objects out of 1000 (max. 8388607) + 210 compressed objects within 3 object streams + 47 named destinations out of 1000 (max. 500000) + 101 words of extra memory for PDF output out of 10000 (max. 10000000) + diff --git a/docs/build/latex/aim-cu.out b/docs/build/latex/aim-cu.out new file mode 100644 index 0000000000000000000000000000000000000000..a2e985e2c3e7afb93178f7f40f78cc57cb4fb111 --- /dev/null +++ b/docs/build/latex/aim-cu.out @@ -0,0 +1,10 @@ +\BOOKMARK [0][-]{chapter.1}{\376\377\000C\000o\000d\000e\000\040\000e\000x\000e\000c\000u\000t\000i\000o\000n}{}% 1 +\BOOKMARK [0][-]{chapter.2}{\376\377\000D\000e\000m\000o}{}% 2 +\BOOKMARK [1][-]{section.2.1}{\376\377\000M\000e\000t\000h\000o\000d\000s}{chapter.2}% 3 +\BOOKMARK [2][-]{subsection.2.1.1}{\376\377\000C\000U\000S\000U\000M\000\040\000p\000a\000r\000a\000m\000e\000t\000e\000r\000s}{section.2.1}% 4 +\BOOKMARK [2][-]{subsection.2.1.2}{\376\377\000C\000U\000S\000U\000M\000\040\000c\000h\000a\000r\000t}{section.2.1}% 5 +\BOOKMARK [1][-]{section.2.2}{\376\377\000C\000U\000S\000U\000M}{chapter.2}% 6 +\BOOKMARK [1][-]{section.2.3}{\376\377\000A\000R\000L\000T\000h\000e\000o\000r\000e\000t\000i\000c\000a\000l}{chapter.2}% 7 +\BOOKMARK [1][-]{section.2.4}{\376\377\000U\000t\000i\000l\000s}{chapter.2}% 8 +\BOOKMARK [0][-]{section*.21}{\376\377\000P\000y\000t\000h\000o\000n\000\040\000M\000o\000d\000u\000l\000e\000\040\000I\000n\000d\000e\000x}{}% 9 +\BOOKMARK [0][-]{section*.22}{\376\377\000I\000n\000d\000e\000x}{}% 10 diff --git a/docs/build/latex/aim-cu.pdf b/docs/build/latex/aim-cu.pdf new file mode 100644 index 0000000000000000000000000000000000000000..b5aefab058d3f2ab87e910245d2a3e9b6eb4b4cd --- /dev/null +++ b/docs/build/latex/aim-cu.pdf @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:93dfcb8bab790019e595646e65c50e4d9dd98f6edac6c5460a9c8e1714f75ab9 +size 214164 diff --git a/docs/build/latex/aim-cu.tex b/docs/build/latex/aim-cu.tex new file mode 100644 index 0000000000000000000000000000000000000000..04eb7371722ce2fcb3781c52ee8bb694efd83396 --- /dev/null +++ b/docs/build/latex/aim-cu.tex @@ -0,0 +1,805 @@ +%% Generated by Sphinx. +\def\sphinxdocclass{report} +\documentclass[letterpaper,10pt,english]{sphinxmanual} +\ifdefined\pdfpxdimen + \let\sphinxpxdimen\pdfpxdimen\else\newdimen\sphinxpxdimen +\fi \sphinxpxdimen=.75bp\relax +\ifdefined\pdfimageresolution + \pdfimageresolution= \numexpr \dimexpr1in\relax/\sphinxpxdimen\relax +\fi +%% let collapsible pdf bookmarks panel have high depth per default +\PassOptionsToPackage{bookmarksdepth=5}{hyperref} + +\PassOptionsToPackage{booktabs}{sphinx} +\PassOptionsToPackage{colorrows}{sphinx} + +\PassOptionsToPackage{warn}{textcomp} +\usepackage[utf8]{inputenc} +\ifdefined\DeclareUnicodeCharacter +% support both utf8 and utf8x syntaxes + \ifdefined\DeclareUnicodeCharacterAsOptional + \def\sphinxDUC#1{\DeclareUnicodeCharacter{"#1}} + \else + \let\sphinxDUC\DeclareUnicodeCharacter + \fi + \sphinxDUC{00A0}{\nobreakspace} + \sphinxDUC{2500}{\sphinxunichar{2500}} + \sphinxDUC{2502}{\sphinxunichar{2502}} + \sphinxDUC{2514}{\sphinxunichar{2514}} + \sphinxDUC{251C}{\sphinxunichar{251C}} + \sphinxDUC{2572}{\textbackslash} +\fi +\usepackage{cmap} +\usepackage[T1]{fontenc} +\usepackage{amsmath,amssymb,amstext} +\usepackage{babel} + + + +\usepackage{tgtermes} +\usepackage{tgheros} +\renewcommand{\ttdefault}{txtt} + + + +\usepackage[Bjarne]{fncychap} +\usepackage{sphinx} + +\fvset{fontsize=auto} +\usepackage{geometry} + + +% Include hyperref last. +\usepackage{hyperref} +% Fix anchor placement for figures with captions. +\usepackage{hypcap}% it must be loaded after hyperref. +% Set up styles of URL: it should be placed after hyperref. +\urlstyle{same} + +\addto\captionsenglish{\renewcommand{\contentsname}{Contents:}} + +\usepackage{sphinxmessages} +\setcounter{tocdepth}{1} + + + \DeclareUnicodeCharacter{03BC}{\textmu} + \DeclareUnicodeCharacter{03C3}{\ensuremath{\sigma}} + + +\title{AIM\sphinxhyphen{}CU} +\date{Jan 31, 2025} +\release{1.0.0} +\author{Smriti Prathapan, Berkman Sahiner, Dhaval Kadia, Ravi K.\@{} Samala} +\newcommand{\sphinxlogo}{\vbox{}} +\renewcommand{\releasename}{Release} +\makeindex +\begin{document} + +\ifdefined\shorthandoff + \ifnum\catcode`\=\string=\active\shorthandoff{=}\fi + \ifnum\catcode`\"=\active\shorthandoff{"}\fi +\fi + +\pagestyle{empty} +\sphinxmaketitle +\pagestyle{plain} +\sphinxtableofcontents +\pagestyle{normal} +\phantomsection\label{\detokenize{index::doc}} + + +\sphinxAtStartPar +A CUSUM\sphinxhyphen{}based tool for AI Monitoring + +\sphinxAtStartPar +AIM\sphinxhyphen{}CU is a statistical tool for AI monitoring using cumulative sum (AIM\sphinxhyphen{}CU). AIM\sphinxhyphen{}CU computes: +\begin{itemize} +\item {} +\sphinxAtStartPar +The parameter choices for change\sphinxhyphen{}point detection based on an acceptable false alarm rate + +\item {} +\sphinxAtStartPar +Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices. + +\end{itemize} + + +\chapter{Code execution} +\label{\detokenize{index:code-execution}} +\sphinxAtStartPar +Clone AIM\sphinxhyphen{}CU repository. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +git\PYG{+w}{ }clone\PYG{+w}{ }https://github.com/DIDSR/AIM\PYGZhy{}CU.git +\end{sphinxVerbatim} + +\sphinxAtStartPar +Run the following commands to install required dependencies (Python = 3.10 is used). + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +apt\PYGZhy{}get\PYG{+w}{ }\PYGZhy{}y\PYG{+w}{ }install\PYG{+w}{ }python3 +apt\PYGZhy{}get\PYG{+w}{ }\PYGZhy{}y\PYG{+w}{ }install\PYG{+w}{ }pip +\PYG{n+nb}{cd}\PYG{+w}{ }AIM\PYGZhy{}CU +pip\PYG{+w}{ }install\PYG{+w}{ }\PYGZhy{}r\PYG{+w}{ }requirements.txt +\end{sphinxVerbatim} + +\sphinxAtStartPar +Run AIM\sphinxhyphen{}CU. + +\begin{sphinxVerbatim}[commandchars=\\\{\}] +python3\PYG{+w}{ }app.py +\end{sphinxVerbatim} + +\sphinxAtStartPar +Open the URL \sphinxurl{http://0.0.0.0:7860} that is running the AIM\sphinxhyphen{}CU locally. + + +\chapter{Demo} +\label{\detokenize{index:demo}} +\sphinxAtStartPar +AIM\sphinxhyphen{}CU can also be run through the demo available at \sphinxurl{https://huggingface.co/spaces/didsr/AIM-CU}. If Space is paused, click on Restart button. + +\sphinxstepscope + + +\section{Methods} +\label{\detokenize{ref_method:methods}}\label{\detokenize{ref_method::doc}} + +\subsection{CUSUM parameters} +\label{\detokenize{ref_method:cusum-parameters}} + +\begin{savenotes}\sphinxattablestart +\sphinxthistablewithglobalstyle +\centering +\sphinxcapstartof{table} +\sphinxthecaptionisattop +\sphinxcaption{CUSUM parameters}\label{\detokenize{ref_method:id1}} +\sphinxaftertopcaption +\begin{tabulary}{\linewidth}[t]{TT} +\sphinxtoprule +\sphinxstyletheadfamily +\sphinxAtStartPar +Parameter +&\sphinxstyletheadfamily +\sphinxAtStartPar +Description +\\ +\sphinxmidrule +\sphinxtableatstartofbodyhook +\sphinxAtStartPar +μ\_in +& +\sphinxAtStartPar +The mean of the performance metric when the process is in\sphinxhyphen{}control, i.e., when there is no performance drift +\\ +\sphinxhline +\sphinxAtStartPar +ARL\_0 +& +\sphinxAtStartPar +Number of observations before the control chart signals a false detection +\\ +\sphinxhline +\sphinxAtStartPar +σ\_in +& +\sphinxAtStartPar +The in\sphinxhyphen{}control standard deviation of the metric +\\ +\sphinxhline +\sphinxAtStartPar +ARL\_1 +& +\sphinxAtStartPar +Number of observations before the control chart signals a true detection +\\ +\sphinxhline +\sphinxAtStartPar +k +& +\sphinxAtStartPar +The normalized reference value, which is related to the magnitude of change that one is interested in detecting. k = 0.5 is the default choice for detecting a unit standard deviation change +\\ +\sphinxhline +\sphinxAtStartPar +S\_hi +& +\sphinxAtStartPar +Cumulative sum of positive changes in the metric +\\ +\sphinxhline +\sphinxAtStartPar +h +& +\sphinxAtStartPar +The normalized threshold or control limit (default =4). This threshold determines when the control chart signals a detection +\\ +\sphinxhline +\sphinxAtStartPar +S\_lo +& +\sphinxAtStartPar +Cumulative sum of negative changes in the metric +\\ +\sphinxbottomrule +\end{tabulary} +\sphinxtableafterendhook\par +\sphinxattableend\end{savenotes} + + +\subsection{CUSUM chart} +\label{\detokenize{ref_method:cusum-chart}} +\sphinxAtStartPar +A two\sphinxhyphen{}sided CUSUM control chart computes the cumulative differences or +deviations of individual observations from the target mean (or +in\sphinxhyphen{}control mean, \(\mu_{in}\)). The positive and negative cumulative +sums are calculated: +\begin{equation*} +\begin{split}\\ S_{hi}(d) = max(0, S_{hi}(d-1) + x_d - \hat{\mu}_{in} - K) +\\ S_{lo}(d) = max(0, S_{lo}(d-1) - x_d + \hat{\mu}_{in} - K)\end{split} +\end{equation*} +\sphinxAtStartPar +where \sphinxstyleemphasis{d} denotes a unit of time, \(x_d\) is the value of quantity +being monitored at time \(d\), \(\hat{\mu}_{in}\) is the +in\sphinxhyphen{}control mean of \(x_d\), and \(K\) is a “reference value” +related to the magnitude of change that one is interested in detecting. +\(S_{hi}\) and \(S_{lo}\) are the cumulative sum of positive and +negative changes. To detect a change in the observed values from the +in\sphinxhyphen{}control mean, the CUSUM scheme accumulates deviations that are +\(K\) units away from the in\sphinxhyphen{}control mean. Let \(\sigma_{in}\) +denote the in\sphinxhyphen{}control standard deviation of \(x_d\). + +\sphinxstepscope + + +\section{CUSUM} +\label{\detokenize{ref_cusum:module-package.cusum}}\label{\detokenize{ref_cusum:cusum}}\label{\detokenize{ref_cusum::doc}}\index{module@\spxentry{module}!package.cusum@\spxentry{package.cusum}}\index{package.cusum@\spxentry{package.cusum}!module@\spxentry{module}} +\sphinxAtStartPar +Cumulative Sum (CUSUM) + +\sphinxAtStartPar +@author: smriti.prathapan +\index{CUSUM (class in package.cusum)@\spxentry{CUSUM}\spxextra{class in package.cusum}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM}} +\pysigstartsignatures +\pysigline +{\sphinxbfcode{\sphinxupquote{class\DUrole{w}{ }}}\sphinxcode{\sphinxupquote{package.cusum.}}\sphinxbfcode{\sphinxupquote{CUSUM}}} +\pysigstopsignatures +\sphinxAtStartPar +CUSUM class and its functionalities. +\index{change\_detection() (package.cusum.CUSUM method)@\spxentry{change\_detection()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.change_detection}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{change\_detection}}} +{\sphinxparam{\DUrole{n}{normalized\_ref\_value}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}\DUrole{w}{ }\DUrole{o}{=}\DUrole{w}{ }\DUrole{default_value}{0.5}}\sphinxparamcomma \sphinxparam{\DUrole{n}{normalized\_threshold}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}\DUrole{w}{ }\DUrole{o}{=}\DUrole{w}{ }\DUrole{default_value}{4}}} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Detects a change in the process. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{pre\_change\_days}} (\sphinxstyleliteralemphasis{\sphinxupquote{int}}) \textendash{} Number of days for in\sphinxhyphen{}control phase. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{normalized\_ref\_value}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}\sphinxstyleliteralemphasis{\sphinxupquote{, }}\sphinxstyleliteralemphasis{\sphinxupquote{optional}}) \textendash{} Normalized reference value for detecting a unit standard deviation change in mean of the process. Defaults to 0.5. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{normalized\_threshold}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}\sphinxstyleliteralemphasis{\sphinxupquote{, }}\sphinxstyleliteralemphasis{\sphinxupquote{optional}}) \textendash{} Normalized threshold. Defaults to 4. + +\end{itemize} + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{compute\_cusum() (package.cusum.CUSUM method)@\spxentry{compute\_cusum()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.compute_cusum}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{compute\_cusum}}} +{\sphinxparam{\DUrole{n}{x}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{list\DUrole{p}{{[}}float\DUrole{p}{{]}}}}\sphinxparamcomma \sphinxparam{\DUrole{n}{mu\_0}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}} +{{ $\rightarrow$ tuple\DUrole{p}{{[}}list\DUrole{p}{{[}}float\DUrole{p}{{]}}\DUrole{p}{,}\DUrole{w}{ }list\DUrole{p}{{[}}float\DUrole{p}{{]}}\DUrole{p}{,}\DUrole{w}{ }list\DUrole{p}{{[}}float\DUrole{p}{{]}}\DUrole{p}{{]}}}} +\pysigstopsignatures +\sphinxAtStartPar +Compute CUSUM for the observations in x +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{x}} (\sphinxstyleliteralemphasis{\sphinxupquote{list}}\sphinxstyleliteralemphasis{\sphinxupquote{{[}}}\sphinxstyleliteralemphasis{\sphinxupquote{float}}\sphinxstyleliteralemphasis{\sphinxupquote{{]}}}) \textendash{} Performance metric to be monitored + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{mu\_0}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} In\sphinxhyphen{}control mean of the observations/performance metric + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{k}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Reference value related to the magnitude of change that one is interested in detecting + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Positive cumulative sum, negative cumulative sum, and CUSUM + +\sphinxlineitem{Return type} +\sphinxAtStartPar +tuple{[}list{[}float{]}, list{[}float{]}, list{[}float{]}{]} + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{initialize() (package.cusum.CUSUM method)@\spxentry{initialize()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.initialize}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{initialize}}} +{} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Initialize with the configuration file. + +\end{fulllineitems} + +\index{plot\_cusum\_plotly() (package.cusum.CUSUM method)@\spxentry{plot\_cusum\_plotly()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.plot_cusum_plotly}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{plot\_cusum\_plotly}}} +{} +{{ $\rightarrow$ Figure}} +\pysigstopsignatures +\sphinxAtStartPar +Plot CUSUM value using Plotly +\begin{quote}\begin{description} +\sphinxlineitem{Returns} +\sphinxAtStartPar +CUSUM plot using Plotly graph object. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +go.Figure + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{plot\_input\_metric\_plotly() (package.cusum.CUSUM method)@\spxentry{plot\_input\_metric\_plotly()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.plot_input_metric_plotly}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{plot\_input\_metric\_plotly}}} +{} +{{ $\rightarrow$ Figure}} +\pysigstopsignatures +\sphinxAtStartPar +Plot the input metric using Plotly. +\begin{quote}\begin{description} +\sphinxlineitem{Returns} +\sphinxAtStartPar +Scatter plot as Plotly graph object. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +go.Figure + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{plot\_input\_metric\_plotly\_raw() (package.cusum.CUSUM method)@\spxentry{plot\_input\_metric\_plotly\_raw()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.plot_input_metric_plotly_raw}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{plot\_input\_metric\_plotly\_raw}}} +{} +{{ $\rightarrow$ Figure}} +\pysigstopsignatures +\sphinxAtStartPar +Plot AI output using Plotly. +\begin{quote}\begin{description} +\sphinxlineitem{Returns} +\sphinxAtStartPar +Scatter plot as Plotly graph object. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +go.Figure + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{set\_df\_metric\_csv() (package.cusum.CUSUM method)@\spxentry{set\_df\_metric\_csv()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.set_df_metric_csv}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{set\_df\_metric\_csv}}} +{\sphinxparam{\DUrole{n}{data\_csv}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{DataFrame}}} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Assign the performance metric data to be used for CUSUM. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{data\_csv}} (\sphinxstyleliteralemphasis{\sphinxupquote{DataFrame}}\sphinxstyleliteralemphasis{\sphinxupquote{ or }}\sphinxstyleliteralemphasis{\sphinxupquote{TextFileReader}}) \textendash{} A comma\sphinxhyphen{}separated values (csv) file is returned as two\sphinxhyphen{}dimensional data structure with labeled axes. + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{set\_df\_metric\_default() (package.cusum.CUSUM method)@\spxentry{set\_df\_metric\_default()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.set_df_metric_default}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{set\_df\_metric\_default}}} +{} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Read the provided performance metric data to be used for CUSUM for an example. + +\end{fulllineitems} + +\index{set\_init\_stats() (package.cusum.CUSUM method)@\spxentry{set\_init\_stats()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.set_init_stats}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{set\_init\_stats}}} +{\sphinxparam{\DUrole{n}{init\_days}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{int}}} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Use initial days to calculate in\sphinxhyphen{}control mean and standard deviation. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{init\_days}} (\sphinxstyleliteralemphasis{\sphinxupquote{int}}\sphinxstyleliteralemphasis{\sphinxupquote{, }}\sphinxstyleliteralemphasis{\sphinxupquote{optional}}) \textendash{} Initial days when observations are considered stable. Defaults to 30. + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{set\_timeline() (package.cusum.CUSUM method)@\spxentry{set\_timeline()}\spxextra{package.cusum.CUSUM method}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_cusum:package.cusum.CUSUM.set_timeline}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxbfcode{\sphinxupquote{set\_timeline}}} +{\sphinxparam{\DUrole{n}{data}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{ndarray}}} +{{ $\rightarrow$ None}} +\pysigstopsignatures +\sphinxAtStartPar +Set the timeline of observations. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{data}} (\sphinxstyleliteralemphasis{\sphinxupquote{np.ndarray}}) \textendash{} Data of the metric values across the observations. + +\end{description}\end{quote} + +\end{fulllineitems} + + +\end{fulllineitems} + + +\sphinxstepscope + + +\section{ARLTheoretical} +\label{\detokenize{ref_theoretical:module-package.ARLTheoretical}}\label{\detokenize{ref_theoretical:arltheoretical}}\label{\detokenize{ref_theoretical::doc}}\index{module@\spxentry{module}!package.ARLTheoretical@\spxentry{package.ARLTheoretical}}\index{package.ARLTheoretical@\spxentry{package.ARLTheoretical}!module@\spxentry{module}} +\sphinxAtStartPar +ARLTheoretical + +\sphinxAtStartPar +@author: smriti.prathapan +\index{get\_ARL\_1() (in module package.ARLTheoretical)@\spxentry{get\_ARL\_1()}\spxextra{in module package.ARLTheoretical}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_theoretical:package.ARLTheoretical.get_ARL_1}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.ARLTheoretical.}}\sphinxbfcode{\sphinxupquote{get\_ARL\_1}}} +{\sphinxparam{\DUrole{n}{h}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{shift\_in\_mean}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{list\DUrole{p}{{[}}float\DUrole{p}{{]}}}}\sphinxparamcomma \sphinxparam{\DUrole{n}{dict\_ARL0\_k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{OrderedDict}}} +{{ $\rightarrow$ DataFrame}} +\pysigstopsignatures +\sphinxAtStartPar +Get the ARL1 along with k values. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{shift\_in\_mean}} (\sphinxstyleliteralemphasis{\sphinxupquote{list}}\sphinxstyleliteralemphasis{\sphinxupquote{{[}}}\sphinxstyleliteralemphasis{\sphinxupquote{float}}\sphinxstyleliteralemphasis{\sphinxupquote{{]}}}) \textendash{} List of the values of shift in mean. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{dict\_ARL0\_k}} (\sphinxstyleliteralemphasis{\sphinxupquote{OrderedDict}}) \textendash{} Data dictionary of ARL0 and k + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Table for ARL1 and k values. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +pd.DataFrame + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{get\_ARL\_1\_h\_mu1\_k() (in module package.ARLTheoretical)@\spxentry{get\_ARL\_1\_h\_mu1\_k()}\spxextra{in module package.ARLTheoretical}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_theoretical:package.ARLTheoretical.get_ARL_1_h_mu1_k}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.ARLTheoretical.}}\sphinxbfcode{\sphinxupquote{get\_ARL\_1\_h\_mu1\_k}}} +{\sphinxparam{\DUrole{n}{h}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{mu1}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}} +{{ $\rightarrow$ float}} +\pysigstopsignatures +\sphinxAtStartPar +Calculate ARL\_1 with given Shift in Mean (mu1) and k. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{k}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized reference value. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{mu1}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Intended shift in mean. + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Detection delay (ARL1). + +\sphinxlineitem{Return type} +\sphinxAtStartPar +float + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{get\_ref\_value() (in module package.ARLTheoretical)@\spxentry{get\_ref\_value()}\spxextra{in module package.ARLTheoretical}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_theoretical:package.ARLTheoretical.get_ref_value}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.ARLTheoretical.}}\sphinxbfcode{\sphinxupquote{get\_ref\_value}}} +{\sphinxparam{\DUrole{n}{h}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{list\_ARL\_0}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{list\DUrole{p}{{[}}float\DUrole{p}{{]}}}}} +{{ $\rightarrow$ tuple\DUrole{p}{{[}}DataFrame\DUrole{p}{,}\DUrole{w}{ }OrderedDict\DUrole{p}{{]}}}} +\pysigstopsignatures +\sphinxAtStartPar +provides normalized reference values k for provided list of ARL0, given the value of normalized threshold h. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{list\_ARL\_0}} (\sphinxstyleliteralemphasis{\sphinxupquote{list}}) \textendash{} List of ARL0 values. + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Dataframe of ARL0 and k, Data dictionary of ARL0 and k; where k is normalized reference value. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +tuple{[}pd.Dataframe, OrderedDict{]} + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{get\_ref\_value\_k() (in module package.ARLTheoretical)@\spxentry{get\_ref\_value\_k()}\spxextra{in module package.ARLTheoretical}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_theoretical:package.ARLTheoretical.get_ref_value_k}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.ARLTheoretical.}}\sphinxbfcode{\sphinxupquote{get\_ref\_value\_k}}} +{\sphinxparam{\DUrole{n}{h}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}\sphinxparamcomma \sphinxparam{\DUrole{n}{ARL\_0}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{float}}} +{{ $\rightarrow$ float}} +\pysigstopsignatures +\sphinxAtStartPar +Calculation for the reference value for given h and ARL\_0. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{ARL\_0}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} ARL0 value. + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Normalized reference value k. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +float + +\end{description}\end{quote} + +\end{fulllineitems} + + +\sphinxstepscope + + +\section{Utils} +\label{\detokenize{ref_utils:module-package.utils}}\label{\detokenize{ref_utils:utils}}\label{\detokenize{ref_utils::doc}}\index{module@\spxentry{module}!package.utils@\spxentry{package.utils}}\index{package.utils@\spxentry{package.utils}!module@\spxentry{module}} +\sphinxAtStartPar +Utilities to handle different operations +\index{get\_greattable\_as\_html() (in module package.utils)@\spxentry{get\_greattable\_as\_html()}\spxextra{in module package.utils}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_utils:package.utils.get_greattable_as_html}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.utils.}}\sphinxbfcode{\sphinxupquote{get\_greattable\_as\_html}}} +{\sphinxparam{\DUrole{n}{df}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{DataFrame}}} +{{ $\rightarrow$ GT}} +\pysigstopsignatures +\sphinxAtStartPar +Get the great\_table as HTML from Pandas dataframe. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{df}} (\sphinxstyleliteralemphasis{\sphinxupquote{pd.DataFrame}}) \textendash{} Dataframe to rendera as a table. + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Table in HTML format. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +gt.GT + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{populate\_summary\_table\_ARL0\_k() (in module package.utils)@\spxentry{populate\_summary\_table\_ARL0\_k()}\spxextra{in module package.utils}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_utils:package.utils.populate_summary_table_ARL0_k}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.utils.}}\sphinxbfcode{\sphinxupquote{populate\_summary\_table\_ARL0\_k}}} +{\sphinxparam{\DUrole{n}{summary\_table\_df\_ARL0\_k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{DataFrame}}\sphinxparamcomma \sphinxparam{\DUrole{n}{h}}} +{{ $\rightarrow$ GT}} +\pysigstopsignatures +\sphinxAtStartPar +Populate ARLTheoretical.summary\_table\_df\_ARL0\_k. +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{summary\_table\_df\_ARL0\_k}} (\sphinxstyleliteralemphasis{\sphinxupquote{pd.DataFrame}}) \textendash{} Dataframe of ARL0 and its respective values of k. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Table of ARL0 and k in HTML format. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +gt.GT + +\end{description}\end{quote} + +\end{fulllineitems} + +\index{populate\_summary\_table\_ARL1\_k() (in module package.utils)@\spxentry{populate\_summary\_table\_ARL1\_k()}\spxextra{in module package.utils}} + +\begin{fulllineitems} +\phantomsection\label{\detokenize{ref_utils:package.utils.populate_summary_table_ARL1_k}} +\pysigstartsignatures +\pysiglinewithargsret +{\sphinxcode{\sphinxupquote{package.utils.}}\sphinxbfcode{\sphinxupquote{populate\_summary\_table\_ARL1\_k}}} +{\sphinxparam{\DUrole{n}{summary\_table\_df\_ARL1\_k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{DataFrame}}\sphinxparamcomma \sphinxparam{\DUrole{n}{dict\_ARL0\_k}\DUrole{p}{:}\DUrole{w}{ }\DUrole{n}{OrderedDict}}\sphinxparamcomma \sphinxparam{\DUrole{n}{h}}} +{{ $\rightarrow$ GT}} +\pysigstopsignatures +\sphinxAtStartPar +Populate Multiindex table specific for ARLTheoretical.summary\_table\_df\_ARL1\_k +\begin{quote}\begin{description} +\sphinxlineitem{Parameters}\begin{itemize} +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{summary\_table\_df\_ARL1\_k}} (\sphinxstyleliteralemphasis{\sphinxupquote{pd.DataFrame}}) \textendash{} Dataframe with ARL1 and k values. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{dict\_ARL0\_k}} (\sphinxstyleliteralemphasis{\sphinxupquote{OrderedDict}}) \textendash{} Data Dictionary with the mapping between ARL0 and k. + +\item {} +\sphinxAtStartPar +\sphinxstyleliteralstrong{\sphinxupquote{h}} (\sphinxstyleliteralemphasis{\sphinxupquote{float}}) \textendash{} Normalized threshold. + +\end{itemize} + +\sphinxlineitem{Returns} +\sphinxAtStartPar +Table for ARL1 and k in HTML format. + +\sphinxlineitem{Return type} +\sphinxAtStartPar +gt.GT + +\end{description}\end{quote} + +\end{fulllineitems} + + + +\renewcommand{\indexname}{Python Module Index} +\begin{sphinxtheindex} +\let\bigletter\sphinxstyleindexlettergroup +\bigletter{p} +\item\relax\sphinxstyleindexentry{package.ARLTheoretical}\sphinxstyleindexpageref{ref_theoretical:\detokenize{module-package.ARLTheoretical}} +\item\relax\sphinxstyleindexentry{package.cusum}\sphinxstyleindexpageref{ref_cusum:\detokenize{module-package.cusum}} +\item\relax\sphinxstyleindexentry{package.utils}\sphinxstyleindexpageref{ref_utils:\detokenize{module-package.utils}} +\end{sphinxtheindex} + +\renewcommand{\indexname}{Index} +\printindex +\end{document} \ No newline at end of file diff --git a/docs/build/latex/aim-cu.toc b/docs/build/latex/aim-cu.toc new file mode 100644 index 0000000000000000000000000000000000000000..28e3adbc9cdcd834891a8cad133449572c68efc8 --- /dev/null +++ b/docs/build/latex/aim-cu.toc @@ -0,0 +1,11 @@ +\babel@toc {english}{}\relax +\contentsline {chapter}{\numberline {1}Code execution}{3}{chapter.1}% +\contentsline {chapter}{\numberline {2}Demo}{5}{chapter.2}% +\contentsline {section}{\numberline {2.1}Methods}{5}{section.2.1}% +\contentsline {subsection}{\numberline {2.1.1}CUSUM parameters}{5}{subsection.2.1.1}% +\contentsline {subsection}{\numberline {2.1.2}CUSUM chart}{5}{subsection.2.1.2}% +\contentsline {section}{\numberline {2.2}CUSUM}{6}{section.2.2}% +\contentsline {section}{\numberline {2.3}ARLTheoretical}{7}{section.2.3}% +\contentsline {section}{\numberline {2.4}Utils}{8}{section.2.4}% +\contentsline {chapter}{Python Module Index}{11}{section*.21}% +\contentsline {chapter}{Index}{13}{section*.22}% diff --git a/docs/build/latex/latexmkjarc b/docs/build/latex/latexmkjarc new file mode 100644 index 0000000000000000000000000000000000000000..6e36b195b2d3083c18c06bafa280ce86729aa546 --- /dev/null +++ b/docs/build/latex/latexmkjarc @@ -0,0 +1,22 @@ +$latex = 'pdflatex ' . $ENV{'LATEXOPTS'} . ' -kanji=utf8 %O %S'; +$dvipdf = 'dvipdfmx %O -o %D %S'; +$makeindex = 'internal mendex %S %B %D'; +sub mendex { + my ($source, $basename, $destination) = @_; + my $dictfile = $basename . ".dic"; + unlink($destination); + system("mendex", "-U", "-f", "-d", $dictfile, "-s", "python.ist", $source); + if ($? > 0) { + print("mendex exited with error code $? (ignored)\n"); + } + if (!-e $destination) { + # create an empty .ind file if nothing + open(FH, ">" . $destination); + close(FH); + } + return 0; +} +add_cus_dep( "glo", "gls", 0, "makeglo" ); +sub makeglo { + return system( "mendex -J -f -s gglo.ist -o '$_[0].gls' '$_[0].glo'" ); +} \ No newline at end of file diff --git a/docs/build/latex/latexmkrc b/docs/build/latex/latexmkrc new file mode 100644 index 0000000000000000000000000000000000000000..bba17fa6bc6aa2e1a0f08088b7bd685077463e8e --- /dev/null +++ b/docs/build/latex/latexmkrc @@ -0,0 +1,9 @@ +$latex = 'latex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$pdflatex = 'pdflatex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$lualatex = 'lualatex ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$xelatex = 'xelatex --no-pdf ' . $ENV{'LATEXOPTS'} . ' %O %S'; +$makeindex = 'makeindex -s python.ist %O -o %D %S'; +add_cus_dep( "glo", "gls", 0, "makeglo" ); +sub makeglo { + return system( "makeindex -s gglo.ist -o '$_[0].gls' '$_[0].glo'" ); +} \ No newline at end of file diff --git a/docs/build/latex/make.bat b/docs/build/latex/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..94bda2139156340fc42bb1cb678e49ac9ac8d3c6 --- /dev/null +++ b/docs/build/latex/make.bat @@ -0,0 +1,31 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +pushd %~dp0 + +set PDFLATEX=latexmk -pdf -dvi- -ps- + +set "LATEXOPTS= " + +if "%1" == "" goto all-pdf + +if "%1" == "all-pdf" ( + :all-pdf + for %%i in (*.tex) do ( + %PDFLATEX% %LATEXMKOPTS% %%i + ) + goto end +) + +if "%1" == "all-pdf-ja" ( + goto all-pdf +) + +if "%1" == "clean" ( + del /q /s *.dvi *.log *.ind *.aux *.toc *.syn *.idx *.out *.ilg *.pla *.ps *.tar *.tar.gz *.tar.bz2 *.tar.xz *.fls *.fdb_latexmk + goto end +) + +:end +popd \ No newline at end of file diff --git a/docs/build/latex/python.ist b/docs/build/latex/python.ist new file mode 100644 index 0000000000000000000000000000000000000000..70536a6683577925167e84e0b0f6a06228754d0a --- /dev/null +++ b/docs/build/latex/python.ist @@ -0,0 +1,16 @@ +line_max 100 +headings_flag 1 +heading_prefix " \\bigletter " + +preamble "\\begin{sphinxtheindex} +\\let\\bigletter\\sphinxstyleindexlettergroup +\\let\\spxpagem \\sphinxstyleindexpagemain +\\let\\spxentry \\sphinxstyleindexentry +\\let\\spxextra \\sphinxstyleindexextra + +" + +postamble "\n\n\\end{sphinxtheindex}\n" + +symhead_positive "{\\sphinxsymbolsname}" +numhead_positive "{\\sphinxnumbersname}" diff --git a/docs/build/latex/sphinx.sty b/docs/build/latex/sphinx.sty new file mode 100644 index 0000000000000000000000000000000000000000..0d52676c4fe7cdf3ca569b3642df5cbce19f8b3c --- /dev/null +++ b/docs/build/latex/sphinx.sty @@ -0,0 +1,1195 @@ +% +% sphinx.sty +% +% Adapted from the old python.sty, mostly written by Fred Drake, +% by Georg Brandl. +% This has now grown to become a full-fledged LaTeX support, split +% among multiple files, some of which provide features unavailable +% from usual LaTeX packages in interaction with the mark-up produced +% by the Sphinx LaTeX writer. + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{sphinx}[2024/10/11 v8.1.1 Sphinx LaTeX package (sphinx-doc)] + +% provides \ltx@ifundefined +% (many packages load ltxcmds: graphicx does for pdftex and lualatex but +% not xelatex, and anyhow kvoptions does, but it may be needed in future to +% use \sphinxdeprecationwarning earlier, and it needs \ltx@ifundefined) +\RequirePackage{ltxcmds} + +%% for deprecation warnings +\newcommand\sphinxdeprecationwarning[4]{% #1 the deprecated macro or name, +% #2 = when deprecated, #3 = when removed, #4 = additional info + {% limit scope of \spx@tempa, \AtEndDocument works even if nested. + \edef\spx@tempa{\detokenize{#1}}% + \ltx@ifundefined{sphinx_depr_\spx@tempa}{% + \global\expandafter\let\csname sphinx_depr_\spx@tempa\endcsname\spx@tempa + \expandafter\AtEndDocument\expandafter{\expandafter\let\expandafter + \sphinxdeprecatedmacro\csname sphinx_depr_\spx@tempa\endcsname + \PackageWarningNoLine{sphinx}{^^J**** SPHINX DEPRECATION WARNING:^^J + \sphinxdeprecatedmacro^^J + \@spaces- is deprecated at Sphinx #2^^J + \@spaces- and removed at Sphinx #3.^^J + #4^^J****}}% + }{% warning already emitted (at end of latex log), don't repeat + }% + }% end of scope limiting group for \spx@tempa +} +%% important build warnings use an undefined reference to induce latexmk +%% into complaining (once per warning) at very end of console output +\newcommand\sphinxbuildwarning[2][]{% + \ifcsname sphinx_emitted_#2\endcsname + \else + \global\expandafter\let\csname sphinx_emitted_#2\endcsname\@empty + \AtEndDocument{\hbox{% should the printing of text be made conditional on + % some boolean? (7.4.0 answers this by adding an + % optional argument and testing it here for emptiness + % but no usage is made of this novelty yet.) + \if\relax\detokenize{#1}\relax + % No [], print a red warning text at very end of document + \bfseries\color{red}% + \@nameuse{sphinx_buildwarning_#2}% + \fi + % place an undefined reference deliberately + \let\nfss@text\@gobble % no ?? + \ref{!!\@nameuse{sphinx_buildwarning_#2}}% + }% + }% + \fi +} +\@namedef{sphinx_buildwarning_badtitlesec}{% + Your system has titlesec version 2.10.1 which causes disappearance + of section numbers; check the latex log warning for details} +\@namedef{sphinx_buildwarning_booktabs}{% + Some tables with booktabs class (check latex log) but booktabs + package not loaded; add its loading to the latex preamble}% +\@namedef{sphinx_buildwarning_badfootnotes}{% + Footnote rendering may have had problems, due to extra package or + document class; check latex log for instructions}% +\@namedef{sphinx_buildwarning_badiconpackage}{% + You have set iconpackage=\spx@opt@iconpackage, but this LaTeX package + is not found}% + +%% OPTION HANDLING +% +% We generally first handle options then load packages, but we need +% \definecolor and \colorlet from xcolor to handle the options. + +% Support for colour options +% -------------------------- +% At 7.4.0, package xcolor is required (which has allowed to get rid of +% annoying fall-back branches). Internals here got refactored to some extent. +% +% MEMO: xcolor \fcolorbox coloured boxes render better in some PDF viewers +% than with color package \fcolorbox. Since 1.6.3, Sphinx uses only its own +% custom variant of \fcolorbox when handling code-blocks. But \fcolorbox +% appears also in Pygmentize output mark-up. +% Should Sphinx load xcolor with its dvipsnames and svgnames options? +\RequirePackage{xcolor} + +% the \colorlet of xcolor is overkill for our internal usage here +\newcommand{\sphinxcolorlet}[2] + {\expandafter\let\csname\@backslashchar color@#1\expandafter\endcsname + \csname\@backslashchar color@#2\endcsname } + +% (5.3.0) Allow colour options to use both the \definecolor and the \colorlet +% syntaxes, for example VerbatimColor={gray}{0.9} or VerbatimColor=red!10 +% In the latter case we need the real \colorlet from xcolor package. +% Prior to 7.4.0 xcolor was not required and thus \spx@colorlet was configured +% to raise a warning in case of absence of xcolor. +\def\spx@defineorletcolor#1{% + \def\spx@definedcolor{{#1}}% + \futurelet\spx@token\spx@defineorlet} +\def\spx@defineorlet{% + \ifx\spx@token\bgroup + \expandafter\spx@definecolor\else\expandafter\spx@colorlet\fi} +\def\spx@colorlet#1\relax{\expandafter\colorlet\spx@definedcolor{#1}} +\def\spx@definecolor{\expandafter\definecolor\spx@definedcolor} +% These internals refactored at 7.4.0: +\newcommand*{\spx@DeclareColorOption}[3][]{% +% #1 = almost always "sphinx" but left empty for a few for legacy reasons +% #2 = option name, but internal colour name is #1#2 (i.e. with prefix) +% #3 = initial default colour with either \definecolor or \colorlet syntax + % Set the initial default + \spx@defineorletcolor{#1#2}#3\relax + % Set the key handler to accept both \definecolor and \colorlet syntax + % The key name does not have the #1 prefix from the colour name + \define@key{sphinx}{#2}{\spx@defineorletcolor{#1#2}##1\relax}% +}% + +% Handle options via "kvoptions" (later loaded by hyperref anyhow) +\RequirePackage{kvoptions} +\SetupKeyvalOptions{prefix=spx@opt@} % use \spx@opt@ prefix + +% Optional usage of booktabs package for tables +\DeclareBoolOption[false]{booktabs} +\DeclareBoolOption[false]{borderless} +\DeclareBoolOption[true]{booktabscolorgaps} +\DeclareVoidOption{booktabsnogaps}{% + \ifx\@nodocument\relax + % in body + \expandafter\@firstofone + \else + % in preamble, wait for at begin document + \expandafter\AtBeginDocument + \fi + {\ifdefined\abovetopsep % silently do nothing if booktabs not loaded + \abovetopsep\z@\belowrulesep\z@\aboverulesep\z@\belowbottomsep\z@ + \fi + }% +} +% Coloured table rows +\DeclareBoolOption[false]{colorrows} +% Sphinx legacy text layout: 1in margins on all four sides +\ifx\@jsc@uplatextrue\@undefined +\DeclareStringOption[1in]{hmargin} +\DeclareStringOption[1in]{vmargin} +\DeclareStringOption[.5in]{marginpar} +\else +% Japanese standard document classes handle \mag in a special way +\DeclareStringOption[\inv@mag in]{hmargin} +\DeclareStringOption[\inv@mag in]{vmargin} +\DeclareStringOption[.5\dimexpr\inv@mag in\relax]{marginpar} +\fi + +\DeclareStringOption[0]{maxlistdepth}% \newcommand*\spx@opt@maxlistdepth{0} +\DeclareStringOption[-1]{numfigreset} +\DeclareBoolOption[false]{nonumfigreset} +\DeclareBoolOption[false]{mathnumfig} +\DeclareStringOption[.]{mathnumsep} +\define@key{sphinx}{bookmarksdepth}{\AtBeginDocument{\hypersetup{bookmarksdepth=#1}}} +\AtBeginDocument{\define@key{sphinx}{bookmarksdepth}{\hypersetup{bookmarksdepth=#1}}} +% \DeclareBoolOption[false]{usespart}% not used + +% Code-blocks +% ----------- +% +% INFO: the keys for padding and border widths were extended at 5.1.0, +% and legacy names for user interface were kept, but their definitions +% are delayed further down. The legacy internally used dimen registers +% \sphinxverbatimborder and \sphinxverbatimsep got removed at 6.2.0. +% More code-blocks related options are found in "CSS" part below. +\DeclareBoolOption[true]{verbatimwithframe} +\DeclareBoolOption[true]{verbatimwrapslines} +\DeclareBoolOption[false]{verbatimforcewraps} +\DeclareStringOption[3]{verbatimmaxoverfull} +\DeclareStringOption[100]{verbatimmaxunderfull} +\DeclareBoolOption[true]{verbatimhintsturnover} +\DeclareBoolOption[true]{inlineliteralwraps} +\DeclareStringOption[t]{literalblockcappos} +\DeclareStringOption[r]{verbatimcontinuedalign} +\DeclareStringOption[r]{verbatimcontinuesalign} +% parsed literal +\DeclareBoolOption[true]{parsedliteralwraps} +% \textvisiblespace for compatibility with fontspec+XeTeX/LuaTeX +\DeclareStringOption[\textcolor{red}{\textvisiblespace}]{verbatimvisiblespace} +\DeclareStringOption % must use braces to hide the brackets + [{\makebox[2\fontcharwd\font`\x][r]{\textcolor{red}{\tiny$\m@th\hookrightarrow$}}}]% + {verbatimcontinued} + +% Topic boxes +% ----------- +% +% 5.1.0 added new keys for configuration. The legacy keys shadowsep, +% shadowsize, shadowrule were kept for backward compatibility. +% 5.1.2 fixed some bugs. +% +% All configuration is now to be found in the "CSS" section below. +% +% 6.2.0 removed \sphinxshadowsep, \sphinxshadowsize, \sphinxshadowrule +% \dimen registers + +% Footnotes +% --------- +\DeclareStringOption[\mbox{ }]{AtStartFootnote} +% we need a public macro name for direct use in latex file +\newcommand*{\sphinxAtStartFootnote}{\spx@opt@AtStartFootnote} +% no such need for this one, as it is used inside other macros +\DeclareStringOption[\leavevmode\unskip]{BeforeFootnote} + +% Some font styling +% ----------------- +% TODO: the replacement of old syntax \py@HeaderFamily as used +% in sphinxlatexstyle{page,headings}.sty and sphinx{manual,howto}.cls +% has never been really put in place. Hence this isolated tidbit here. +\DeclareStringOption[\sffamily\bfseries]{HeaderFamily} + +% Some legacy colour options +% -------------------------- +% +\spx@DeclareColorOption{TitleColor}{{rgb}{0.126,0.263,0.361}} +\spx@DeclareColorOption{InnerLinkColor}{{rgb}{0.208,0.374,0.486}} +\spx@DeclareColorOption{OuterLinkColor}{{rgb}{0.216,0.439,0.388}} +% The Verbatim ones are "legacy" only since 5.1.0... call it "new-legacy" ;-) +\spx@DeclareColorOption{VerbatimColor}{{RGB}{242,242,242}}% same as {gray}{0.95} +\spx@DeclareColorOption{VerbatimBorderColor}{{RGB}{32,32,32}} +% All other colours will be internally assigned a "sphinx" prefix + +% Table row colors (since 6.0.0) +% ---------------- +\spx@DeclareColorOption[sphinx]{TableRowColorHeader}{{gray}{0.86}} +\spx@DeclareColorOption[sphinx]{TableRowColorOdd}{{gray}{0.92}} +\spx@DeclareColorOption[sphinx]{TableRowColorEven}{{gray}{0.98}} +% if not set, the "Merge" colour will keep in sync with the "Row" colour +\def\sphinxTableMergeColorHeader{sphinxTableRowColorHeader} +\define@key{sphinx}{TableMergeColorHeader}{% + \spx@defineorletcolor{sphinxTableMergeColorHeader}#1\relax + \def\sphinxTableMergeColorHeader{sphinxTableMergeColorHeader}% +}% +\def\sphinxTableMergeColorOdd{sphinxTableRowColorOdd} +\define@key{sphinx}{TableMergeColorOdd}{% + \spx@defineorletcolor{sphinxTableMergeColorOdd}#1\relax + \def\sphinxTableMergeColorOdd{sphinxTableMergeColorOdd}% +}% +\def\sphinxTableMergeColorEven{sphinxTableRowColorEven} +\define@key{sphinx}{TableMergeColorEven}{% + \spx@defineorletcolor{sphinxTableMergeColorEven}#1\relax + \def\sphinxTableMergeColorEven{sphinxTableMergeColorEven}% +}% +% Default color chosen to be as in minted.sty LaTeX package! +\spx@DeclareColorOption[sphinx]{VerbatimHighlightColor}{{rgb}{0.878,1,1}} + +% Notices/admonitions +% ------------------- +% +% 5.1.0 added much customizability to warning, caution, attention, danger and +% error types of notices via an enhanced sphinxheavybox environment. +% +% 6.2.0 added the possibility to use the same kind of rendering also for +% note, hint, important, and tip. +% +% Legacy user interface for options was kept working. All of it is handled in +% the "CSS" section below. +% +% 6.2.0 added booleans to serve internally as a record of whether the +% note, hint, important and tip admonitions used the legacy "lightbox" or +% the then enhanced "heavybox" environment. +% +% 7.4.0 uses "heavybox" environment from sphinxlatexadmonitions in all cases, +% hence the booleans mentioned above have been removed as well as the rather +% complex TeX code which was done so that these booleans were made true if +% and only if the CSS-named keys had been made usage of via 'sphinxsetup'. +% +% The "light style" implemented in sphinxlatexadmonitions.sty as +% "sphinxlightbox" is not used. Also, admonitions by default have a "title +% row", and the corresponding options are only named in the CSS style which is +% implemented further below. Here we define options having a legacy name. +% +% seealso directive is also using "heavybox" at 7.4.0 acquiring the same +% customizability as admonitions. +% todo directive also. +\definecolor{sphinx-admonition-bgcolor} {RGB}{247, 247, 247}% #F7F7F7 +\definecolor{sphinx-admonition-bordercolor} {RGB}{134, 152, 155}% #86989B +\definecolor{sphinx-warning-bordercolor} {RGB}{148, 0, 0}% #940000 +\definecolor{sphinx-error-bordercolor} {RGB}{180, 0, 0}% #B40000 +\spx@DeclareColorOption[sphinx]{noteBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{hintBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{importantBorderColor}{sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{tipBorderColor} {sphinx-admonition-bordercolor} +\spx@DeclareColorOption[sphinx]{seealsoBorderColor} {sphinx-admonition-bordercolor}% 7.4.0 +\spx@DeclareColorOption[sphinx]{todoBorderColor} {sphinx-admonition-bordercolor}% 7.4.0 +% +\spx@DeclareColorOption[sphinx]{noteBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{hintBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{importantBgColor}{sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{tipBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{seealsoBgColor} {sphinx-admonition-bgcolor}% 7.4.0 +\spx@DeclareColorOption[sphinx]{todoBgColor} {sphinx-admonition-bgcolor}% 7.4.0 +% +\spx@DeclareColorOption[sphinx]{warningBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{cautionBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{attentionBorderColor}{sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{dangerBorderColor} {sphinx-warning-bordercolor} +\spx@DeclareColorOption[sphinx]{errorBorderColor} {sphinx-error-bordercolor} +% +\spx@DeclareColorOption[sphinx]{warningBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{cautionBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{attentionBgColor}{sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{dangerBgColor} {sphinx-admonition-bgcolor} +\spx@DeclareColorOption[sphinx]{errorBgColor} {sphinx-admonition-bgcolor} +% +%%%%%%%% +% +% Additions of CSS-like keys at 5.1.0 (and possibility of rounded boxes) +% ----------------------------------- +% +% These CSS-named alikes allow to configure 4 border widths, 4 padding seps, 4 +% corner radii, optional shadow, border color, background color, shadow color. +% +% In future, an alternative user interface will perhaps be provided to parse +% genuine CSS, but this will be easier to do in Python than in LaTeX. +% +% Refactoring (and extension) at 6.2.0 +% ------------------------------------ +% +% 6.2.0 batch defines in one go all auxiliaries for code-blocks, topics, and +% admonitions. The needed steps to maintain the legacy option names working +% and to set some specific defaults are handled in a second step. +% +% This allowed to: +% +% - associate these CSS-named options also to note, hint, important, and tip +% which thus can access the full customizability of sphinxheavybox if they use +% it. +% +% - provide a \sphinxbox command for boxing inline text elements with the same +% full customizability. +% +% The \dimen's \sphinxverbatimborder, \sphinxverbatimsep, \sphinxshadowsep, +% \sphinxshadowsize, and \sphinxshadowrule, which had been deprecated have +% finally been removed entirely. No more \dimen register is used here only +% storage in macros. +% +% Restyling at 7.4.0 with new defaults for all admonition types +% ------------------------------------------------------------- +% +% So far the 5.1.0 added possibilities for fancier boxes had been used by +% default only for code-blocks, and admonitions kept their old-fashioned +% legacy styles. At 7.4.0, as a follow-up to the revamped styles of +% admonitions in the HTML sphinx13 theme (PR #12439), it is decided to +% apply similar styling for PDF output. Also the seealso directive +% is handled as an admonition with the same customizability. And the +% todo directive. +% +% 8.1.0: style separately topic, contents, and sidebar directives +% --------------------------------------------------------------- +% +% And use some title row also for them (but without icon, per default). +% +\def\spxstring@none{none} +\def\spxstring@clone{clone} +% +% Border keys +% At 7.4.0 refactoring to avoid defining legacy \spx@@border +% macros which are (now) used nowhere, only @top, @right, @bottom, @left. +\def\spx@tempa#1{% #1 = macro prefix + \expandafter\spx@tempb + \csname #1border@top\expandafter\endcsname + \csname #1border@right\expandafter\endcsname + \csname #1border@bottom\expandafter\endcsname + \csname #1border@left\expandafter\endcsname + \csname if#1border@open\expandafter\endcsname + \csname #1border@opentrue\expandafter\endcsname + \csname #1border@openfalse\endcsname +}% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #8 = option prefix + \define@key{sphinx}{#8border-top-width}{\def#1{##1}}% + \define@key{sphinx}{#8border-right-width}{\def#2{##1}}% + \define@key{sphinx}{#8border-bottom-width}{\def#3{##1}}% + \define@key{sphinx}{#8border-left-width}{\def#4{##1}}% + \define@key{sphinx}{#8border-width}{% + % MEMO: not immediately expanded, should this be changed? + \def#1{##1}\let#2#1\let#3#1\let#4#1% + }% + \newif#5% + % 6.2.0 has added support for box-decoration-break also to admonition + % directives, formerly the option setting was ignored for them. + \define@key{sphinx}{#8box-decoration-break}% + {\begingroup\edef\spx@tempa{##1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@clone#7\else#6\fi}% + % 7.4.0 sets the default behaviour to "slice" not only for code-blocks but + % also for admonitions, as the latter now have a background colour each. + #6% + % #8 = option prefix (with underscore), #9 = legacy option name + % keep legacy option names as aliases to new-named options + \expandafter\let\csname KV@sphinx@#9\expandafter\endcsname + \csname KV@sphinx@#8border-width\endcsname + % init border-width (fetches next argument) + \csname KV@sphinx@#8border-width\endcsname +} +% MEMO: from 6.2.0 to 7.4.0 (excluive) \fboxrule was used in the first +% two, and was resolved only at location of use. At 7.4.0, we again +% use 0.4pt rather and not \fboxrule dimen register. +% macro prefix option prefix legacy option init value +\spx@tempa{spx@pre@} {pre_} {verbatimborder} {0.4pt} +\spx@tempa{spx@topic@} {div.topic_} {shadowrule} {0.5pt}% mod. at 7.4.0 +\spx@tempa{spx@contents@} {div.contents_} {shadowrule} {0.5pt}% 8.1.0 +\spx@tempa{spx@sidebar@} {div.sidebar_} {shadowrule} {1pt}% 8.1.0 +% let legacy shadowrule key set all topic/contents/sidebar border +% keys to the common value given by user to shadowrule +\def\KV@sphinx@shadowrule #1{% + \@nameuse{KV@sphinx@div.topic_border-width}{#1}% + \@nameuse{KV@sphinx@div.contents_border-width}{#1}% + \@nameuse{KV@sphinx@div.sidebar_border-width}{#1}% +}% +\spx@tempa{spx@note@} {div.note_} {noteborder} {0.5pt} +\spx@tempa{spx@hint@} {div.hint_} {hintborder} {0.5pt} +\spx@tempa{spx@important@}{div.important_}{importantborder}{0.5pt} +\spx@tempa{spx@tip@} {div.tip_} {tipborder} {0.5pt} +\spx@tempa{spx@seealso@} {div.seealso_} {seealsoborder} {0.5pt}% new at 7.4.0 +\spx@tempa{spx@todo@} {div.todo_} {todoborder} {0.5pt}% new at 7.4.0 +\spx@tempa{spx@warning@} {div.warning_} {warningborder} {1pt} +\spx@tempa{spx@caution@} {div.caution_} {cautionborder} {1pt} +\spx@tempa{spx@attention@}{div.attention_}{attentionborder}{1pt} +\spx@tempa{spx@danger@} {div.danger_} {dangerborder} {1pt} +\spx@tempa{spx@error@} {div.error_} {errorborder} {1.25pt}% mod. at 7.4.0 +% this one new at 6.2.0: (we do not create a "legacy name" for it) +\spx@tempa{spx@box@} {box_} {box_border-width}{0.4pt} +% Reset default box-decoration-break style to "clone" for \sphinxbox, +% but anyhow this is ignored as \sphinxbox produces unbreakable boxes. +\spx@box@border@openfalse + +% Padding keys +% At 7.4.0, \spx@@padding internal macros removed, only @top, @right, +% @bottom, @left are actually needed by sphinxpackageboxes.sty. +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname #1padding@top\expandafter\endcsname + \csname #1padding@right\expandafter\endcsname + \csname #1padding@bottom\expandafter\endcsname + \csname #1padding@left\endcsname +}% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #5 = option prefix + \define@key{sphinx}{#5padding-top}{\def#1{##1}}% + \define@key{sphinx}{#5padding-right}{\def#2{##1}}% + \define@key{sphinx}{#5padding-bottom}{\def#3{##1}}% + \define@key{sphinx}{#5padding-left}{\def#4{##1}}% + \define@key{sphinx}{#5padding}{% + \def#1{##1}\let#2#1\let#3#1\let#4#1% + }% + % initial defaults + \def#1{#6}\def#2{#7}\def#3{#8}\def#4{#9}% +} +% MEMO: prior to 6.2.0 the \fboxsep value (3pt, a priori) was frozen here via +% a \dimen assignment done immediately. From 6.2.0 to 7.4.0 an unfrozen +% \fboxsep was used, and at 7.4.0 it is again explicit 3pt. +% The defaults for admonitions were all modified at 7.4.0. +% For topic/contents and all admonitions the horizontal padding plus borders +% are put inside the text area (i.e. do not go into the margins). +% In order for perfect exact same vertical alignment of contents from all such +% directives, the value of horizontal border-width+padding is kept constant +% (equal to 7.5pt since 7.4.0). +% 8.1.0 styles separately topic, contents, and sidebar. +% #1 macro prefix #6 option prefix top right bottom left +\spx@tempa{spx@pre@} {pre_} {3pt}{3pt}{3pt}{3pt} +\spx@tempa{spx@topic@} {div.topic_} {6pt}{7pt}{6pt}{7pt}% mod. at 8.1.0 +% contents styling inherits at 8.1.0 the former 7.4.0 topic defaults +\spx@tempa{spx@contents@} {div.contents_} {10pt}{7pt}{12pt}{7pt}% 8.1.0 +\spx@tempa{spx@sidebar@} {div.sidebar_} {6pt}{6.5pt}{6pt}{6.5pt}% 8.1.0 +% 7.4.0 drops legacy settings which linked strangely padding with border width +\spx@tempa{spx@note@} {div.note_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@hint@} {div.hint_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@important@}{div.important_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@tip@} {div.tip_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@seealso@} {div.seealso_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@todo@} {div.todo_} {6pt}{7pt}{6pt}{7pt} +\spx@tempa{spx@warning@} {div.warning_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@caution@} {div.caution_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@attention@}{div.attention_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@danger@} {div.danger_} {6pt}{6.5pt}{6pt}{6.5pt} +\spx@tempa{spx@error@} {div.error_} {6pt}{6.25pt}{6pt}{6.25pt} +\spx@tempa{spx@box@} {box_} {3pt}{3pt}{3pt}{3pt} +% define legacy verbatimsep key as alias of pre_padding key +\expandafter\let\expandafter\KV@sphinx@verbatimsep\csname KV@sphinx@pre_padding\endcsname +% let legacy shadowsep key set all topic/contents/sidebar padding +% keys to the common value given by user to shadosep +\def\KV@sphinx@shadowsep #1{% + \@nameuse{KV@sphinx@div.topic_padding}{#1}% + \@nameuse{KV@sphinx@div.contents_padding}{#1}% + \@nameuse{KV@sphinx@div.sidebar_padding}{#1}% +}% + +% Corner radii keys +% +% Prior to 6.2.0, the "rounded box" branch obeyed the 4 radii but ignored +% the separate border widths and used only the border-width setting. +% Now, all 4 + 4 parameters are obeyed. +\def\spx@tempa#1{% #1 = macro prefix + \expandafter\spx@tempb + \csname #1radius@topleft\expandafter\endcsname + \csname #1radius@topright\expandafter\endcsname + \csname #1radius@bottomright\expandafter\endcsname + \csname #1radius@bottomleft\endcsname +}% +\def\spx@tempb #1#2#3#4#5#6#7#8#9{% #5 = option prefix + \define@key{sphinx}{#5border-top-left-radius}{\def#1{##1}}% + \define@key{sphinx}{#5border-top-right-radius}{\def#2{##1}}% + \define@key{sphinx}{#5border-bottom-right-radius}{\def#3{##1}}% + \define@key{sphinx}{#5border-bottom-left-radius}{\def#4{##1}}% + \define@key{sphinx}{#5border-radius}{\def#1{##1}\let#2#1\let#3#1\let#4#1}% + \def#1{#6}\def#2{#7}\def#3{#8}\def#4{#9}% +} +% The init value for corner radius in code-blocks was \z@ (i.e. 0pt) prior +% to 6.0.0., then 3pt, then \fboxsep at 6.2.0 as padding was also \fboxsep. +% At 7.4.0: +% - the 3pt is used (which is normal value of \fboxsep). +% - some admonitions use rounded corners as well. +% - topic boxed have only their bottom right corner rounded. +% At 8.1.0 topic, contents and sidebar separately styled. +% macro prefix option prefix tl tr br bl +\spx@tempa{spx@pre@} {pre_} {3pt}{3pt}{3pt}{3pt} +% use four rounded corners (and no shadow) for topic at 8.1.0 +\spx@tempa{spx@topic@} {div.topic_} {8pt}{8pt}{8pt}{8pt} +% contents inherits at 8.1.0 the 7.4.0 former styling of topic +\spx@tempa{spx@contents@} {div.contents_} \z@ \z@ {12pt} \z@ +% make sidebard distinctive as we can't really safely implement +% it with text flowing around it, but rather as a full width block +\spx@tempa{spx@sidebar@} {div.sidebar_} {12pt}\z@ {12pt} \z@ +\spx@tempa{spx@note@} {div.note_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@hint@} {div.hint_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@important@}{div.important_} \z@\z@\z@\z@ +\spx@tempa{spx@tip@} {div.tip_} {5pt}{5pt}{5pt}{5pt} +\spx@tempa{spx@seealso@} {div.seealso_} \z@\z@\z@\z@ +\spx@tempa{spx@todo@} {div.todo_} \z@\z@\z@\z@ +\spx@tempa{spx@warning@} {div.warning_} \z@\z@\z@\z@ +\spx@tempa{spx@caution@} {div.caution_} \z@\z@\z@\z@ +\spx@tempa{spx@attention@}{div.attention_} \z@\z@\z@\z@ +\spx@tempa{spx@danger@} {div.danger_} \z@\z@\z@\z@ +\spx@tempa{spx@error@} {div.error_} \z@\z@\z@\z@ +\spx@tempa{spx@box@} {box_} {3pt}{3pt}{3pt}{3pt} + +% Shadow keys +% +% Prior to 6.2.0, an "inset" shadow caused the rendering to ignore +% rounded corners. Starting with 6.2.0, an "inset" shadow is simply +% ignored (not implemented) if any of the corner radii is positive, +% rather than forcing a rectangle+inset shadow output. +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname if#1withshadow\expandafter\endcsname + \csname if#1insetshadow\endcsname +}% +\def\spx@tempb#1#2{\newif#1\newif#2}% +% macro prefix +\spx@tempa{spx@pre@} +\spx@tempa{spx@topic@} +\spx@tempa{spx@contents@}% 8.1.0 +\spx@tempa{spx@sidebar@}% 8.1.0 +\spx@tempa{spx@note@} +\spx@tempa{spx@hint@} +\spx@tempa{spx@important@} +\spx@tempa{spx@tip@} +\spx@tempa{spx@seealso@}% 7.4.0 +\spx@tempa{spx@todo@}% 7.4.0 +\spx@tempa{spx@warning@} +\spx@tempa{spx@caution@} +\spx@tempa{spx@attention@} +\spx@tempa{spx@danger@} +\spx@tempa{spx@error@} +\spx@tempa{spx@box@} +% +\def\spx@tempa#1{% #1 = macro prefix + \expandafter\spx@tempb + \csname #1withshadowtrue\expandafter\endcsname + \csname #1withshadowfalse\expandafter\endcsname + \csname #1insetshadowtrue\expandafter\endcsname + \csname #1insetshadowfalse\expandafter\endcsname + \csname #1shadow@setter\expandafter\endcsname + \csname #1shadow@xoffset\expandafter\endcsname + \csname #1shadow@yoffset\endcsname +}% +\def\spx@tempb#1#2#3#4#5#6#7#8{% #8 = option prefix + \define@key{sphinx}{#8box-shadow}{#5##1 {} {} \@nnil}% + \def#5##1 ##2 ##3 ##4\@nnil{% + \begingroup\edef\spx@tempa{##1}\expandafter\endgroup + \ifx\spx@tempa\spxstring@none + #2% + % MEMO: at 5.1.0 and up to 6.2.0, an \edef with \number\dimexpr was + % used here. Since 6.2.0, expansion is delayed to time of use as for + % the other dimensions handled above. This is synched with an added + % encapsulation in \dimexpr...\relax by the "setup" from + % sphinxpackageboxes.sty. + \else #1% + \def#6{##1}% + \if\relax\detokenize{##2}\relax\let#7#6\else\def#7{##2}\fi + \if\relax\detokenize{##3}\relax#4\else#3\fi + \fi + }% + #5none {} {} \@nnil % no shadow by default (except for topic, see below) +} +\spx@tempa{spx@pre@} {pre_} +\spx@tempa{spx@topic@} {div.topic_} +\spx@tempa{spx@contents@} {div.contents_} +\spx@tempa{spx@sidebar@} {div.sidebar_} +% This corresponds to the legacy parameters for topic/contents/sidebar, +% but they are now only kept for contents + \spx@contents@shadow@setter 4pt 4pt {} \@nnil +% topic and sidebar default to no shadow +\spx@tempa{spx@note@} {div.note_} +\spx@tempa{spx@hint@} {div.hint_} +\spx@tempa{spx@important@}{div.important_} +\spx@tempa{spx@tip@} {div.tip_} +\spx@tempa{spx@seealso@} {div.seealso_} +\spx@tempa{spx@todo@} {div.todo_} +\spx@tempa{spx@warning@} {div.warning_} +\spx@tempa{spx@caution@} {div.caution_} +\spx@tempa{spx@attention@}{div.attention_} +\spx@tempa{spx@danger@} {div.danger_} +\spx@tempa{spx@error@} {div.error_} +\spx@tempa{spx@box@} {box_} + +% Support for legacy shadowsize (topic/contents/sidebar) +% This definition was broken due to a typo at 5.1.0 and got fixed at 6.1.2 +% MEMO: at 6.2.0 this no longer does \number\dimexpr in an \edef. Reason is to +% keep in sync with div.topic_box-shadow handling of xoffset and yoffset. +\define@key{sphinx}{shadowsize}{% + \def\spx@topic@shadow@xoffset{#1}% + \let\spx@contents@shadow@xoffset\spx@topic@shadow@xoffset + \let\spx@sidebar@shadow@xoffset \spx@topic@shadow@xoffset + \let\spx@topic@shadow@yoffset \spx@topic@shadow@xoffset + \let\spx@contents@shadow@yoffset\spx@topic@shadow@xoffset + \let\spx@sidebar@shadow@yoffset \spx@topic@shadow@xoffset + \ifdim\dimexpr\spx@topic@shadow@xoffset=\z@ + \spx@topic@withshadowfalse + \spx@contents@withshadowfalse + \spx@sidebar@withshadowfalse + \else + \spx@topic@withshadowtrue + \spx@topic@insetshadowfalse + \spx@contents@withshadowtrue + \spx@contents@insetshadowfalse + \spx@sidebar@withshadowtrue + \spx@sidebar@insetshadowfalse + \fi +}% + +% Color keys, TeXextras key, keys for admonition titles with icon +% +% Historical remarks to be removed at some point: +% +% Some problems due to legacy naming scheme which had diverging conventions +% for code-blocks (VerbatimBorderColor, VerbatimColor) and admonitions +% (sphinxwarningBorderColor, sphinxwarningBgColor, etc...) regarding the +% internal names of the used colors. Unfortunately VerbatimColor and for +% example sphinxwarningBgColor are also documented at user level, they are not +% only internally used. +% +% For topic directive, "legacy" (around 2016-2017) had no interface for +% colours, so some internals could be changed with no breakage during 5.x up +% to 6.2.0. For example topic (shadowbox) could be unified with admonitions +% (sphinxheavybox), and the "setup" macros could all be moved into a single +% one in the sphinxpackageboxes.sty file, with only one argument holding the +% directive type. +% +% It was then needed only by sphinxlatexliterals.sty to let its emitted +% \spx@verb@boxes@fcolorbox@setup incorporate some extra adjustment. +% +% 7.4.0 removes usages of booleans relative to usage of a colour for +% background or border which were there to optimize the boxing code from +% sphinxpackageboxes.sty when colours where not needed. These were internal +% macros so their removal should not be considered breaking. +% We keep the infrastructure for "shadowcolor" and "textcolor" because the +% defaults for them remain not to have specific colour. +% +% 7.4.0 adds keys for admonition titles: for background and foreground colors, +% and for icons (whose defaults are picked from Free Fontawesome 5). +\def\spx@tempa#1{% + \expandafter\spx@tempb + \csname if#1withshadowcolor\expandafter\endcsname + \csname if#1withtextcolor\endcsname +}% +\def\spx@tempb#1#2{\newif#1\newif#2}% +% macro prefix +\spx@tempa{spx@pre@} +\spx@tempa{spx@topic@} +\spx@tempa{spx@contents@} +\spx@tempa{spx@sidebar@} +\spx@tempa{spx@note@} +\spx@tempa{spx@hint@} +\spx@tempa{spx@important@} +\spx@tempa{spx@tip@} +\spx@tempa{spx@seealso@} +\spx@tempa{spx@todo@} +\spx@tempa{spx@warning@} +\spx@tempa{spx@caution@} +\spx@tempa{spx@attention@} +\spx@tempa{spx@danger@} +\spx@tempa{spx@error@} +\spx@tempa{spx@box@} +% +\def\spx@tempa#1{% #1 = macro prefix + \expandafter\spx@tempb + \csname #1withshadowcolortrue\expandafter\endcsname + \csname #1withtextcolortrue\expandafter\endcsname + \csname #1TeXextras\endcsname +} +% 7.4.0 adds options for a title. They have an action only for admonitions, +% seealso and todo directives. +\def\spx@tempb#1#2#3#4#5{% #4 = option prefix, #5 = color name prefix + \define@key{sphinx}{#4border-TeXcolor}% + {\spx@defineorletcolor{#5BorderColor}##1\relax}% + \define@key{sphinx}{#4background-TeXcolor}% + {\spx@defineorletcolor{#5BgColor}##1\relax}% + \define@key{sphinx}{#4title-background-TeXcolor}% + {\spx@defineorletcolor{#5TtlBgColor}##1\relax}% + \define@key{sphinx}{#4title-foreground-TeXcolor}% + {\spx@defineorletcolor{#5TtlFgColor}##1\relax}% + \define@key{sphinx}{#4title-icon}% + {\@namedef{#5TtlIcon}{##1}}% + \define@key{sphinx}{#4box-shadow-TeXcolor}% + {#1\spx@defineorletcolor{#5ShadowColor}##1\relax}% + \define@key{sphinx}{#4TeXcolor}% + {#2\spx@defineorletcolor{#5TextColor}##1\relax}% + \define@key{sphinx}{#4TeXextras}% + {\def#3{##1}}% +} +% macro prefix option prefix color name prefix +\spx@tempa{spx@pre@} {pre_} {Verbatim} + % (memo: internal VerbatimShadowColor was formerly sphinxVerbatimShadowColor) + % internal legacy color name is VerbatimColor not VerbatimBgColor, so redefine: + \define@key{sphinx}{pre_background-TeXcolor}% + {\spx@defineorletcolor{VerbatimColor}#1\relax}% + % Keep legacy option names working + \expandafter\let\expandafter\KV@sphinx@VerbatimBorderColor + \csname KV@sphinx@pre_border-TeXcolor\endcsname + \expandafter\let\expandafter\KV@sphinx@VerbatimColor + \csname KV@sphinx@pre_background-TeXcolor\endcsname +% (6.2.0 modified some internal namings for the colors of topic boxes) +% macro prefix option prefix color name prefix +% There was no legacy interface for topic/contents/sidebar +% 8.1.0 allows separate styling for topic/contents/sidebar +\spx@tempa{spx@topic@} {div.topic_} {sphinxtopic} +\spx@tempa{spx@contents@} {div.contents_} {sphinxcontents} +\spx@tempa{spx@sidebar@} {div.sidebar_} {sphinxsidebar} +\spx@tempa{spx@note@} {div.note_} {sphinxnote} +\spx@tempa{spx@hint@} {div.hint_} {sphinxhint} +\spx@tempa{spx@important@}{div.important_} {sphinximportant} +\spx@tempa{spx@tip@} {div.tip_} {sphinxtip} +\spx@tempa{spx@seealso@} {div.seealso_} {sphinxseealso} +\spx@tempa{spx@todo@} {div.todo_} {sphinxtodo} +\spx@tempa{spx@warning@} {div.warning_} {sphinxwarning} +\spx@tempa{spx@caution@} {div.caution_} {sphinxcaution} +\spx@tempa{spx@attention@}{div.attention_} {sphinxattention} +\spx@tempa{spx@danger@} {div.danger_} {sphinxdanger} +\spx@tempa{spx@error@} {div.error_} {sphinxerror} +\spx@tempa{spx@box@} {box_} {sphinxbox} + % Keep legacy sphinxsetup color options interface for "strong" admonitions + \def\spx@tempa#1#2{% #1 = option prefix, #2 = legacy option prefix + \expandafter\let\csname KV@sphinx@#2BorderColor\expandafter\endcsname + \csname KV@sphinx@#1border-TeXcolor\endcsname + \expandafter\let\csname KV@sphinx@#2BgColor\expandafter\endcsname + \csname KV@sphinx@#1background-TeXcolor\endcsname + } + \spx@tempa{div.warning_} {warning} + \spx@tempa{div.caution_} {caution} + \spx@tempa{div.attention_} {attention} + \spx@tempa{div.danger_} {danger} + \spx@tempa{div.error_} {error} + + % Keep legacy sphinxsetup BorderColor for =note, hint, ... + % Add "legacy" names BgColor (added at 7.4.0) and TextColor + \def\spx@tempa#1#2{% #1 = CSS like option prefix, #2 = legacy option prefix + \expandafter\let\csname KV@sphinx@#2BorderColor\expandafter\endcsname + \csname KV@sphinx@#1border-TeXcolor\endcsname + \expandafter\let\csname KV@sphinx@#2BgColor\expandafter\endcsname + \csname KV@sphinx@#1background-TeXcolor\endcsname + \expandafter\let\csname KV@sphinx@#2TextColor\expandafter\endcsname + \csname KV@sphinx@#1TeXcolor\endcsname + } + \spx@tempa{div.note_} {note} + \spx@tempa{div.hint_} {hint} + \spx@tempa{div.important_} {important} + \spx@tempa{div.tip_} {tip} + + % Add "legacy" hintTeXextras etc... + \def\spx@tempa#1#2{% #1 = CSS like option prefix, #2 = legacy option prefix + \expandafter\let\csname KV@sphinx@#2TeXextras\expandafter\endcsname + \csname KV@sphinx@#1TeXextras\endcsname + } + \spx@tempa{div.note_} {note} + \spx@tempa{div.hint_} {hint} + \spx@tempa{div.important_} {important} + \spx@tempa{div.tip_} {tip} + + % At 7.4.0, let topic/contents boxes acquire background and border colours + % and give the shadow some colour other than black + % 8.1.0 styles separately topic/contents/sidebar + % topic has no shadow but we keep 7.4.0 color in case it gets needed + \setkeys{sphinx}{% + div.topic_border-TeXcolor=sphinx-admonition-bordercolor, + div.topic_background-TeXcolor=sphinx-admonition-bgcolor, + div.topic_box-shadow-TeXcolor={RGB}{108,108,108}, + div.contents_border-TeXcolor=sphinx-admonition-bordercolor, + div.contents_background-TeXcolor=sphinx-admonition-bgcolor, + div.contents_box-shadow-TeXcolor={RGB}{108,108,108}, + div.sidebar_border-TeXcolor=sphinx-admonition-bordercolor, + div.sidebar_background-TeXcolor=sphinx-admonition-bgcolor, + div.sidebar_box-shadow-TeXcolor=sphinx-admonition-bordercolor!80,% #9eacaf + } + + +% 7.4.0 lets all types of admonitions style especially their titlss. +% The Sphinx default colours for admonition titles are copied from PR #12486 +% which modified sphinx13.css (see also earlier #12439) +% The actual code using the colours and icons whose defaults are set here +% is to be found in sphinxlatexadmonitions.sty. +% +% MEMO: unfortunately xcolor does NOT implement HSL but only HSB! +% So the sphinx13.css colours specified via hsl() got converted to RGB here +\definecolor{sphinx-admonition-title-bgcolor}{RGB}{229,229,229} % hsl(0, 0%, 90%); +\definecolor{sphinx-admonition-title-fgcolor}{RGB}{127,127,127} % hsl(0, 0%, 50%); +\definecolor{sphinx-warning-title-bgcolor} {RGB}{248,228,210} % hsl(28.5, 74%, 90%); +\definecolor{sphinx-warning-title-fgcolor} {RGB}{221,122,33} % hsl(28.5, 74%, 50%); +\definecolor{sphinx-note-title-bgcolor} {RGB}{208,222,250} % hsl(219.5, 84%, 90%); +\definecolor{sphinx-note-title-fgcolor} {RGB}{20,93,234} % hsl(219.5, 84%, 50%); +\definecolor{sphinx-success-title-bgcolor} {RGB}{220,239,230} % hsl(150, 36.7%, 90%); +\definecolor{sphinx-success-title-fgcolor} {RGB}{81,174,128} % hsl(150, 36.7%, 50%); +\definecolor{sphinx-error-title-bgcolor} {RGB}{238,220,220} % hsl(0, 37%, 90%); +\definecolor{sphinx-error-title-fgcolor} {RGB}{174,80,80} % hsl(0, 37%, 50%); +\definecolor{sphinx-todo-title-bgcolor} {RGB}{226,204,254} % hsl(266.8, 100%, 90%); +\definecolor{sphinx-todo-title-fgcolor} {RGB}{113,0,255} % hsl(266.8, 100%, 50%); + +% Now use the above colours as default settings, following the choices +% done in sphinx13.css +\setkeys{sphinx}{ + div.note_title-background-TeXcolor=sphinx-note-title-bgcolor, + div.note_title-foreground-TeXcolor=sphinx-note-title-fgcolor, +% + div.hint_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.hint_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.tip_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.tip_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.seealso_title-background-TeXcolor=sphinx-success-title-bgcolor, + div.seealso_title-foreground-TeXcolor=sphinx-success-title-fgcolor, + div.todo_title-background-TeXcolor=sphinx-todo-title-bgcolor, + div.todo_title-foreground-TeXcolor=sphinx-todo-title-fgcolor, +% + div.important_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.important_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, + div.caution_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.caution_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, + div.warning_title-background-TeXcolor=sphinx-warning-title-bgcolor, + div.warning_title-foreground-TeXcolor=sphinx-warning-title-fgcolor, +% + div.attention_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.attention_title-foreground-TeXcolor=sphinx-error-title-fgcolor, + div.danger_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.danger_title-foreground-TeXcolor=sphinx-error-title-fgcolor, + div.error_title-background-TeXcolor=sphinx-error-title-bgcolor, + div.error_title-foreground-TeXcolor=sphinx-error-title-fgcolor, +% +% 8.1.0 add title rows, but will not use icons per default, so +% the fgcolor setting will be used only if user uses title-icon key + div.topic_title-background-TeXcolor=sphinx-admonition-title-bgcolor, + div.topic_title-foreground-TeXcolor=sphinx-admonition-title-fgcolor, + div.contents_title-background-TeXcolor=sphinx-admonition-title-bgcolor, + div.contents_title-foreground-TeXcolor=sphinx-admonition-title-fgcolor, + div.sidebar_title-background-TeXcolor=sphinx-note-title-bgcolor, + div.sidebar_title-foreground-TeXcolor=sphinx-note-title-fgcolor, +} + +% 7.4.0 Support for icons in admonition titles +% We try to +% - get Sphinx PDF builds to process fine in absence of fontawesome5 +% - use fontawesome5 if present, but not if user prefers another package +% - provide an interface for using other LaTeX code for icons +% - provide an interface for using some other package than fontawesome5 +% Indeed we can't load fontawesome5 unconditionally even if available, +% as it proves incompatible with fontawesome package. +% We thus must delay its loading. +\IfFileExists{fontawesome5.sty}{% + \DeclareStringOption[fontawesome5]{iconpackage}% +}% +{% + \IfFileExists{fontawesome.sty} + {\DeclareStringOption[fontawesome]{iconpackage}} + {\DeclareStringOption[none]{iconpackage}}% +}% +\newcommand\spx@faIcon[2][]{}% +% The above \spx@faIcon which gobbles one mandatory and one optional +% argument is put into use only if both fontawesome5 and fontawesome +% LaTeX packages are not available, as part of the defaults for the +% div.*_title-icon keys (these keys can be redefined via the sphinxsetup +% interface). +% +\def\spxstring@fontawesome{fontawesome} +\def\spxstring@fontawesomev{fontawesome5} +\AtBeginDocument{% + \ifx\spx@opt@iconpackage\spxstring@none + \else + \IfFileExists{\spx@opt@iconpackage.sty} + {\RequirePackage{\spx@opt@iconpackage}% + \ifx\spx@opt@iconpackage\spxstring@fontawesomev + \renewcommand\spx@faIcon{\faIcon}% + \else + \ifx\spx@opt@iconpackage\spxstring@fontawesome + \renewcommand\spx@faIcon[2][]{\faicon{##2}}% + % The \ifdefined's are a bit silly because we know that + % fontawesome.sty does not provide it, but perhaps + % there can be some new release of that package? + \ifdefined\faicon@lightbulb\else + \let\faicon@lightbulb\faLightbulbO + \fi + \ifdefined\faicon@radiation\else + \let\faicon@radiation\faBolt + \fi + \ifdefined\faicon@pen\else + \let\faicon@pen\faPencil + \fi + % if neither has been required, \spx@faIcon will simply swallow + % its argument and it is up to user + % to set the various div.*_title-icon keys appropriately. + \fi\fi % + }% + {% + \sphinxbuildwarning{badiconpackage}% + \PackageWarningNoLine{sphinx}{% + You have set iconpackage=\spx@opt@iconpackage\MessageBreak + But \spx@opt@iconpackage.sty is not found by LaTeX} + }% + \fi +} + +\setkeys{sphinx}{ +% Icon defaults. + div.note_title-icon = \spx@faIcon{info-circle}, + div.hint_title-icon = \spx@faIcon[regular]{lightbulb}, + div.tip_title-icon = \spx@faIcon[regular]{lightbulb}, + div.seealso_title-icon = \spx@faIcon{share}, + div.todo_title-icon = \spx@faIcon{pen}, + div.important_title-icon = \spx@faIcon{pause-circle}, + div.caution_title-icon = \spx@faIcon{radiation}, + div.warning_title-icon = \spx@faIcon{exclamation-triangle}, + div.attention_title-icon = \spx@faIcon{exclamation-triangle}, + div.danger_title-icon = \spx@faIcon{radiation}, + div.error_title-icon = \spx@faIcon{times-circle}, +% MEMO: the new at 8.1.0 defaults for contents/topic/sidebar directives +% use no icons, they use \sphinxdotitlerow which detects automatically +% whether title-icon key has been set or not. +} + +\newif\ifspx@opt@box@addstrut +\expandafter\def\csname KV@sphinx@box_addstrut\endcsname#1{% + \csname spx@opt@box@addstrut#1\endcsname +} +\expandafter\def\csname KV@sphinx@box_addstrut@default\endcsname{% + \spx@opt@box@addstruttrue +} + +\DeclareDefaultOption{\@unknownoptionerror} +\ProcessKeyvalOptions* +% don't allow use of maxlistdepth via \sphinxsetup. +\DisableKeyvalOption{sphinx}{maxlistdepth} +\DisableKeyvalOption{sphinx}{numfigreset} +\DisableKeyvalOption{sphinx}{nonumfigreset} +\DisableKeyvalOption{sphinx}{mathnumfig} +\DisableKeyvalOption{sphinx}{booktabs} +\DisableKeyvalOption{sphinx}{borderless} +\DisableKeyvalOption{sphinx}{rowcolors} +% FIXME: this is unrelated to an option, move this elsewhere +% To allow hyphenation of first word in narrow contexts; no option, +% customization to be done via 'preamble' key +\newcommand*\sphinxAtStartPar{\leavevmode\nobreak\hskip\z@skip} +% No need for the \hspace{0pt} trick (\hskip\z@skip) with luatex +\ifdefined\directlua\let\sphinxAtStartPar\@empty\fi +% user interface: options can be changed midway in a document! +\newcommand\sphinxsetup{\setkeys{sphinx}} + + +%% MISCELLANEOUS CONTEXT +% +% flag to be set in a framed environment +% (defined here as currently needed by three sphinxlatex....sty files and +% even if not needed if such files are replaced, the definition does no harm) +\newif\ifspx@inframed +% +% \spx@ifcaptionpackage (defined at begin document) +% is needed currently in macros from: +% sphinxlatexliterals.sty (sphinxVerbatim) +% sphinxlatextables.sty (for some macros used in the table templates) +% +% \sphinxcaption is mark-up injected by the tabular and tabulary templates +% it is defined in sphinxlatextables.sty +% +% store the original \caption macro for usage with figures inside longtable +% and tabulary cells. Make sure we get the final \caption in presence of +% caption package, whether the latter was loaded before or after sphinx. +\AtBeginDocument{% + \let\spx@originalcaption\caption + \@ifpackageloaded{caption} + {\let\spx@ifcaptionpackage\@firstoftwo + \caption@AtBeginDocument*{\let\spx@originalcaption\caption}% +% in presence of caption package, drop our own \sphinxcaption whose aim was to +% ensure same width of caption to all kinds of tables (tabular(y), longtable), +% because caption package has its own width (or margin) option + \def\sphinxcaption{\caption}% + }% + {\let\spx@ifcaptionpackage\@secondoftwo}% +} + +%% PASS OPTIONS +% +% pass options to hyperref; it must not have been loaded already +\RequirePackage{sphinxoptionshyperref} +% pass options to geometry; it must not have been loaded already +\RequirePackage{sphinxoptionsgeometry} + + +%% COLOR (general) +% +% FIXME: these two should be deprecated +% +% FIXME: \normalcolor should be used and \py@NormalColor never defined +\def\py@NormalColor{\color{black}} +% FIXME: \color{TitleColor} should be used directly and \py@TitleColor +% should never get defined. +\def\py@TitleColor{\color{TitleColor}} + + +%% PACKAGES +% +% as will be indicated below, secondary style files load some more packages +% +% For \text macro (sphinx.util.texescape) +% also for usage of \firstchoice@true(false) in sphinxlatexgraphics.sty +\RequirePackage{amstext} +% It was passed "warn" option from latex template in case it is already loaded +% via some other package before \usepackage{sphinx} in preamble +\RequirePackage{textcomp} +% For the H specifier. Do not \restylefloat{figure}, it breaks Sphinx code +% for allowing figures in tables. +\RequirePackage{float} +% For floating figures in the text. Better to load after float. +\RequirePackage{wrapfig} +% Provides \captionof, used once by latex writer (\captionof{figure}) +\RequirePackage{capt-of} +% Support hlist directive +\RequirePackage{multicol} + + +%% GRAPHICS +% +% It will always be needed, so let's load it here +\RequirePackage{graphicx} +\RequirePackage{sphinxlatexgraphics} + + +%% FRAMED ENVIRONMENTS +% +% \sphinxbox added at 6.2.0, its definition is in sphinxpackageboxes. +% +% Alias all \sphinxsetup "box_" keys to become \sphinxboxsetup no-prefix keys +\@tfor\x:={border-width}% + {border-top-width}{border-right-width}{border-bottom-width}{border-left-width}% + {box-decoration-break}% This one is actually useless, as \sphinxbox + % creates an unbreakable horizontal box, not a breakable vertical + % box. And as is well-known it is very complicated (not to say + % impossible) to create in LaTeX breakable horizontal boxes. No + % package offers them. See the complications for the support of + % verbatimforcewraps in sphinxlatexliterals.sty or see the source + % code of the soul or soulutf8 packages. + {padding}% + {padding-top}{padding-right}{padding-bottom}{padding-left}% + {border-radius}% + {border-top-left-radius}{border-top-right-radius}% + {border-bottom-right-radius}{border-bottom-left-radius}% + {box-shadow}% + {border-TeXcolor}{background-TeXcolor}{box-shadow-TeXcolor}{TeXcolor}% + {TeXextras}{addstrut}{addstrut@default}% +\do{\expandafter\let\csname KV@sphinxbox@\x\expandafter\endcsname + \csname KV@sphinx@box_\x\endcsname} +% Let \sphinxboxsetup also prepare a "reset", which will be used by nested +% boxes; currently and by laziness this is implemented simply by accumulating +% all passed options inside some storage, in the order they were given, rather +% than saving the box would-be parameters. Advantage is that this will not +% have to be modified if additional keys are added in future (e.g. for +% elliptic corners). Storing obeys TeX groups. (these details would be +% relevant only for some genuine independent LaTeX package and manual user +% authored mark-up, not Sphinx auto mark-up). +\newcommand\sphinxboxsetup[1]{% + \setkeys{sphinxbox}{#1}% + \expandafter\def\expandafter\spx@boxes@sphinxbox@defaults\expandafter + {\spx@boxes@sphinxbox@defaults,#1}% +} +\def\spx@boxes@sphinxbox@reset{% + \begingroup\def\x{\endgroup\setkeys{sphinxbox}}% + \expandafter\x\expandafter{\spx@boxes@sphinxbox@defaults}% +} +% Some of these defaults got already set. But we now list them all explicitly +% for a complete initial configuration of reset storage. +% At 7.4.0, \fboxrule and \fboxsep replaced by 0.4pt and 3pt which are anyhow +% the defaults for these LaTeX dimensions. +\let\spx@boxes@sphinxbox@defaults\@gobble +\sphinxboxsetup{% + border-width=0.4pt, + padding=3pt, + border-radius=0.4pt, + box-shadow=none, +% MEMO: as xcolor is loaded, \spx@defineorletcolor has a "\colorlet" branch +% which makes this syntax acceptable and avoids duplicating here the values. + border-TeXcolor=VerbatimBorderColor, + background-TeXcolor=VerbatimColor, +% 7.4.0 modified the color of the shadow (anyhow box-shadow is set above to none +% so no shadow is drawn), to be as the new shadow colour of topic boxes. + box-shadow-TeXcolor={RGB}{108,108,108}, + TeXextras={}, + addstrut=false, + }% +\RequirePackage{sphinxpackageboxes} +\RequirePackage{sphinxlatexadmonitions} +\RequirePackage{sphinxlatexliterals} +\RequirePackage{sphinxlatexshadowbox} + + +%% CONTAINERS +% +\RequirePackage{sphinxlatexcontainers} + + +%% PYGMENTS +% stylesheet for highlighting with pygments +\RequirePackage{sphinxhighlight} + + +%% TABLES +% +\RequirePackage{sphinxlatextables} + + +%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS +% +\RequirePackage{sphinxlatexnumfig} + + +%% LISTS +% +\RequirePackage{sphinxlatexlists} + + +%% FOOTNOTES +% +% Support scopes for footnote numbering +% This is currently stepped at each input file +\newcounter{sphinxscope} +\newcommand{\sphinxstepscope}{\stepcounter{sphinxscope}} +% We ensure \thesphinxscope expands to digits tokens, independently of language +\renewcommand{\thesphinxscope}{\number\value{sphinxscope}} +\newcommand\sphinxthefootnotemark[2]{% + % this is used to make reference to an explicitly numbered footnote not on same page + % #1=label of footnote text, #2=page number where footnote text was printed + \ifdefined\pagename + \pagename\space#2, % <- space + \else + p. #2, % <- space + \fi #1% no space +} +% support large numbered footnotes in minipage; but this is now obsolete +% from systematic use of savenotes environment around minipages +\def\thempfootnote{\arabic{mpfootnote}} +% This package is needed to support hyperlinked footnotes in tables and +% framed contents, and to allow code-blocks in footnotes. +\RequirePackage{sphinxpackagefootnote} + + +%% INDEX, BIBLIOGRAPHY, APPENDIX, TABLE OF CONTENTS +% +\RequirePackage{sphinxlatexindbibtoc} + + +%% STYLING +% +\RequirePackage{sphinxlatexstylepage} +\RequirePackage{sphinxlatexstyleheadings} +\RequirePackage{sphinxlatexstyletext} + + +%% MODULE RELEASE DATA AND OBJECT DESCRIPTIONS +% +\RequirePackage{sphinxlatexobjects} + + +% FIXME: this line should be dropped, as "9" is default anyhow. +\ifdefined\pdfcompresslevel\pdfcompresslevel = 9 \fi + + +\endinput diff --git a/docs/build/latex/sphinx.xdy b/docs/build/latex/sphinx.xdy new file mode 100644 index 0000000000000000000000000000000000000000..8df526e51717e061cfd3f5cfdeb941a7bf8f16ac --- /dev/null +++ b/docs/build/latex/sphinx.xdy @@ -0,0 +1,230 @@ +;;; -*- mode: lisp; coding: utf-8; -*- + +;; Unfortunately xindy is out-of-the-box hyperref-incompatible. This +;; configuration is a workaround, which requires to pass option +;; hyperindex=false to hyperref. +;; textit and emph not currently used, spxpagem replaces former textbf +(define-attributes (("textbf" "textit" "emph" "spxpagem" "default"))) +(markup-locref :open "\textbf{\hyperpage{" :close "}}" :attr "textbf") +(markup-locref :open "\textit{\hyperpage{" :close "}}" :attr "textit") +(markup-locref :open "\emph{\hyperpage{" :close "}}" :attr "emph") +(markup-locref :open "\spxpagem{\hyperpage{" :close "}}" :attr "spxpagem") +(markup-locref :open "\hyperpage{" :close "}" :attr "default") + +(require "numeric-sort.xdy") + +;; xindy base module latex.xdy loads tex.xdy and the latter instructs +;; xindy to ignore **all** TeX macros in .idx entries, except those +;; explicitly described in merge rule. But when after applying all +;; merge rules an empty string results, xindy raises an error: + +;; ERROR: CHAR: index 0 should be less than the length of the string + +;; For example when using pdflatex with utf-8 characters the index +;; file will contain \IeC macros and they will get ignored except if +;; suitable merge rules are loaded early. The texindy script coming +;; with xindy provides this, but only for Latin scripts. The texindy +;; man page says to use rather xelatex or lualatex in case of Cyrillic +;; scripts. + +;; Sphinx contributes LICRcyr2utf8.xdy to provide support for Cyrillic +;; scripts for the pdflatex engine. + +;; Another issue caused by xindy ignoring all TeX macros except those +;; explicitly declared reveals itself when attempting to index ">>>", +;; as the ">" is converted to "\textgreater{}" by Sphinx's LaTeX +;; escaping. + +;; To fix this, Sphinx does **not** use texindy, and does not even +;; load the xindy latex.xdy base module. + +;(require "latex.xdy") + +;; Rather it incorporates some suitable extracts from latex.xdy and +;; tex.xdy with additional Sphinx contributed rules. + +;; But, this means for pdflatex and Latin scripts that the xindy file +;; tex/inputenc/uf8.xdy is not usable because it refers to the macro +;; \IeC only sporadically, and as tex.xdy is not loaded, a rule such as +;; (merge-rule "\'e" "é" :string) +;; does not work, it must be +;; (merge-rule "\IeC {\'e}" "é" :string) +;; So Sphinx contributes LICRlatin2utf8.xdy to mitigate that problem. + +;;;;;;;; extracts from tex.xdy (discarding most original comments): + +;;; +;;; TeX conventions +;;; + +;; Discard leading and trailing white space. Collapse multiple white +;; space characters to blank. + +(merge-rule "^ +" "" :eregexp) +(merge-rule " +$" "" :eregexp) +(merge-rule " +" " " :eregexp) + +;; Handle TeX markup + +(merge-rule "\\([{}$%&#])" "\1" :eregexp) + +;;;;;;;; end of extracts from xindy's tex.xdy + +;;;;;;;; extracts from latex.xdy: + +;; Standard location classes: arabic and roman numbers, and alphabets. + +(define-location-class "arabic-page-numbers" ("arabic-numbers")) +(define-location-class "roman-page-numbers" ("roman-numbers-lowercase")) +(define-location-class "Roman-page-numbers" ("roman-numbers-uppercase")) +(define-location-class "alpha-page-numbers" ("alpha")) +(define-location-class "Alpha-page-numbers" ("ALPHA")) + +;; Output Markup + +(markup-letter-group-list :sep "~n~n \indexspace~n") + +(markup-indexentry :open "~n \item " :depth 0) +(markup-indexentry :open "~n \subitem " :depth 1) +(markup-indexentry :open "~n \subsubitem " :depth 2) + +(markup-locclass-list :open ", " :sep ", ") +(markup-locref-list :sep ", ") + +;;;;;;;; end of extracts from latex.xdy + +;; The LaTeX \index command turns \ into normal character so the TeX macros +;; written to .idx files are not followed by a blank. This is different +;; from non-ascii letters which end up (with pdflatex) as \IeC macros in .idx +;; file, with a blank space after \IeC + +;; Details of the syntax are explained at +;; https://xindy.sourceforge.net/doc/manual-3.html +;; In absence of :string, "xindy uses an auto-detection mechanism to decide, +;; if the pattern is a regular expression or not". But it is not obvious to +;; guess, for example "\\_" is not detected as RE but "\\P\{\}" is, so for +;; being sure we apply the :string switch everywhere and do not use \\ etc... + +;; Go back from sphinx.util.texescape TeX macros to UTF-8 + +(merge-rule "\sphinxleftcurlybrace{}" "{" :string) +(merge-rule "\sphinxrightcurlybrace{}" "}" :string) +(merge-rule "\_" "_" :string) +(merge-rule "{[}" "[" :string) +(merge-rule "{]}" "]" :string) +(merge-rule "\textbackslash{}" "\" :string) ; " for Emacs syntax highlighting +(merge-rule "\textasciitilde{}" "~~" :string); the ~~ escape is needed here +(merge-rule "\textasciicircum{}" "^" :string) +(merge-rule "\sphinxhyphen{}" "-" :string) +(merge-rule "\textquotesingle{}" "'" :string) +(merge-rule "\textasciigrave{}" "`" :string) +(merge-rule "\textless{}" "<" :string) +(merge-rule "\textgreater{}" ">" :string) +(merge-rule "\P{}" "¶" :string) +(merge-rule "\S{}" "§" :string) +(merge-rule "\texteuro{}" "€" :string) +(merge-rule "\(\infty\)" "∞" :string) +(merge-rule "\(\pm\)" "±" :string) +(merge-rule "\(\rightarrow\)" "→" :string) +(merge-rule "\(\checkmark\)" "✓" :string) +(merge-rule "\textendash{}" "–" :string) +(merge-rule "\textbar{}" "|" :string) +(merge-rule "\(\sp{\text{0}}\)" "⁰" :string) +(merge-rule "\(\sp{\text{1}}\)" "¹" :string) +(merge-rule "\(\sp{\text{2}}\)" "²" :string) +(merge-rule "\(\sp{\text{3}}\)" "³" :string) +(merge-rule "\(\sp{\text{4}}\)" "⁴" :string) +(merge-rule "\(\sp{\text{5}}\)" "⁵" :string) +(merge-rule "\(\sp{\text{6}}\)" "⁶" :string) +(merge-rule "\(\sp{\text{7}}\)" "⁷" :string) +(merge-rule "\(\sp{\text{8}}\)" "⁸" :string) +(merge-rule "\(\sp{\text{9}}\)" "⁹" :string) +(merge-rule "\(\sb{\text{0}}\)" "₀" :string) +(merge-rule "\(\sb{\text{1}}\)" "₁" :string) +(merge-rule "\(\sb{\text{2}}\)" "₂" :string) +(merge-rule "\(\sb{\text{3}}\)" "₃" :string) +(merge-rule "\(\sb{\text{4}}\)" "₄" :string) +(merge-rule "\(\sb{\text{5}}\)" "₅" :string) +(merge-rule "\(\sb{\text{6}}\)" "₆" :string) +(merge-rule "\(\sb{\text{7}}\)" "₇" :string) +(merge-rule "\(\sb{\text{8}}\)" "₈" :string) +(merge-rule "\(\sb{\text{9}}\)" "₉" :string) +(merge-rule "\IeC {\textalpha }" "α" :string) +(merge-rule "\IeC {\textbeta }" "β" :string) +(merge-rule "\IeC {\textgamma }" "γ" :string) +(merge-rule "\IeC {\textdelta }" "δ" :string) +(merge-rule "\IeC {\textepsilon }" "ε" :string) +(merge-rule "\IeC {\textzeta }" "ζ" :string) +(merge-rule "\IeC {\texteta }" "η" :string) +(merge-rule "\IeC {\texttheta }" "θ" :string) +(merge-rule "\IeC {\textiota }" "ι" :string) +(merge-rule "\IeC {\textkappa }" "κ" :string) +(merge-rule "\IeC {\textlambda }" "λ" :string) +(merge-rule "\IeC {\textmu }" "μ" :string) +(merge-rule "\IeC {\textnu }" "ν" :string) +(merge-rule "\IeC {\textxi }" "ξ" :string) +(merge-rule "\IeC {\textomicron }" "ο" :string) +(merge-rule "\IeC {\textpi }" "π" :string) +(merge-rule "\IeC {\textrho }" "ρ" :string) +(merge-rule "\IeC {\textsigma }" "σ" :string) +(merge-rule "\IeC {\texttau }" "τ" :string) +(merge-rule "\IeC {\textupsilon }" "υ" :string) +(merge-rule "\IeC {\textphi }" "φ" :string) +(merge-rule "\IeC {\textchi }" "χ" :string) +(merge-rule "\IeC {\textpsi }" "ψ" :string) +(merge-rule "\IeC {\textomega }" "ω" :string) +(merge-rule "\IeC {\textAlpha }" "Α" :string) +(merge-rule "\IeC {\textBeta }" "Β" :string) +(merge-rule "\IeC {\textGamma }" "Γ" :string) +(merge-rule "\IeC {\textDelta }" "Δ" :string) +(merge-rule "\IeC {\textEpsilon }" "Ε" :string) +(merge-rule "\IeC {\textZeta }" "Ζ" :string) +(merge-rule "\IeC {\textEta }" "Η" :string) +(merge-rule "\IeC {\textTheta }" "Θ" :string) +(merge-rule "\IeC {\textIota }" "Ι" :string) +(merge-rule "\IeC {\textKappa }" "Κ" :string) +(merge-rule "\IeC {\textLambda }" "Λ" :string) +(merge-rule "\IeC {\textMu }" "Μ" :string) +(merge-rule "\IeC {\textNu }" "Ν" :string) +(merge-rule "\IeC {\textTheta }" "Θ" :string) +(merge-rule "\IeC {\textIota }" "Ι" :string) +(merge-rule "\IeC {\textKappa }" "Κ" :string) +(merge-rule "\IeC {\textLambda }" "Λ" :string) +(merge-rule "\IeC {\textMu }" "Μ" :string) +(merge-rule "\IeC {\textNu }" "Ν" :string) +(merge-rule "\IeC {\textXi }" "Ξ" :string) +(merge-rule "\IeC {\textOmicron }" "Ο" :string) +(merge-rule "\IeC {\textPi }" "Π" :string) +(merge-rule "\IeC {\textRho }" "Ρ" :string) +(merge-rule "\IeC {\textSigma }" "Σ" :string) +(merge-rule "\IeC {\textTau }" "Τ" :string) +(merge-rule "\IeC {\textUpsilon }" "Υ" :string) +(merge-rule "\IeC {\textPhi }" "Φ" :string) +(merge-rule "\IeC {\textChi }" "Χ" :string) +(merge-rule "\IeC {\textPsi }" "Ψ" :string) +(merge-rule "\IeC {\textOmega }" "Ω" :string) +(merge-rule "\IeC {\textohm }" "Ω" :string) + +;; This xindy module provides some basic support for "see" +(require "makeindex.xdy") + +;; This creates one-letter headings and works fine with utf-8 letters. +;; For Cyrillic with pdflatex works thanks to LICRcyr2utf8.xdy +(require "latin-lettergroups.xdy") + +;; currently we don't (know how to easily) separate "Numbers" from +;; "Symbols" with xindy as is the case with makeindex. +(markup-index :open "\begin{sphinxtheindex} +\let\lettergroup\sphinxstyleindexlettergroup +\let\lettergroupDefault\sphinxstyleindexlettergroupDefault +\let\spxpagem\sphinxstyleindexpagemain +\let\spxentry\sphinxstyleindexentry +\let\spxextra\sphinxstyleindexextra + +" + :close " + +\end{sphinxtheindex} +" + :tree) + diff --git a/docs/build/latex/sphinxhighlight.sty b/docs/build/latex/sphinxhighlight.sty new file mode 100644 index 0000000000000000000000000000000000000000..170f55710ec5527a3199954b94ef78edfc2c8b45 --- /dev/null +++ b/docs/build/latex/sphinxhighlight.sty @@ -0,0 +1,130 @@ +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesPackage{sphinxhighlight}[2022/06/30 stylesheet for highlighting with pygments] +% Its contents depend on pygments_style configuration variable. + + +\makeatletter +\def\PYG@reset{\let\PYG@it=\relax \let\PYG@bf=\relax% + \let\PYG@ul=\relax \let\PYG@tc=\relax% + \let\PYG@bc=\relax \let\PYG@ff=\relax} +\def\PYG@tok#1{\csname PYG@tok@#1\endcsname} +\def\PYG@toks#1+{\ifx\relax#1\empty\else% + \PYG@tok{#1}\expandafter\PYG@toks\fi} +\def\PYG@do#1{\PYG@bc{\PYG@tc{\PYG@ul{% + \PYG@it{\PYG@bf{\PYG@ff{#1}}}}}}} +\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+\PYG@do{#2}} + +\@namedef{PYG@tok@w}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.73,0.73}{##1}}} +\@namedef{PYG@tok@c}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@cs}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}\def\PYG@bc##1{{\setlength{\fboxsep}{0pt}\colorbox[rgb]{1.00,0.94,0.94}{\strut ##1}}}} +\@namedef{PYG@tok@k}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kt}{\def\PYG@tc##1{\textcolor[rgb]{0.56,0.13,0.00}{##1}}} +\@namedef{PYG@tok@o}{\def\PYG@tc##1{\textcolor[rgb]{0.40,0.40,0.40}{##1}}} +\@namedef{PYG@tok@ow}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nb}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nf}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}} +\@namedef{PYG@tok@nc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}} +\@namedef{PYG@tok@nn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.05,0.52,0.71}{##1}}} +\@namedef{PYG@tok@ne}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@nv}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@no}{\def\PYG@tc##1{\textcolor[rgb]{0.38,0.68,0.84}{##1}}} +\@namedef{PYG@tok@nl}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.13,0.44}{##1}}} +\@namedef{PYG@tok@ni}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.84,0.33,0.22}{##1}}} +\@namedef{PYG@tok@na}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@nt}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.45}{##1}}} +\@namedef{PYG@tok@nd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.33,0.33,0.33}{##1}}} +\@namedef{PYG@tok@s}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sd}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@si}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.44,0.63,0.82}{##1}}} +\@namedef{PYG@tok@se}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sr}{\def\PYG@tc##1{\textcolor[rgb]{0.14,0.33,0.53}{##1}}} +\@namedef{PYG@tok@ss}{\def\PYG@tc##1{\textcolor[rgb]{0.32,0.47,0.09}{##1}}} +\@namedef{PYG@tok@sx}{\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}} +\@namedef{PYG@tok@m}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@gh}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.00,0.50}{##1}}} +\@namedef{PYG@tok@gu}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.50,0.00,0.50}{##1}}} +\@namedef{PYG@tok@gd}{\def\PYG@tc##1{\textcolor[rgb]{0.63,0.00,0.00}{##1}}} +\@namedef{PYG@tok@gi}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.63,0.00}{##1}}} +\@namedef{PYG@tok@gr}{\def\PYG@tc##1{\textcolor[rgb]{1.00,0.00,0.00}{##1}}} +\@namedef{PYG@tok@ge}{\let\PYG@it=\textit} +\@namedef{PYG@tok@gs}{\let\PYG@bf=\textbf} +\@namedef{PYG@tok@ges}{\let\PYG@bf=\textbf\let\PYG@it=\textit} +\@namedef{PYG@tok@gp}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.78,0.36,0.04}{##1}}} +\@namedef{PYG@tok@go}{\def\PYG@tc##1{\textcolor[rgb]{0.20,0.20,0.20}{##1}}} +\@namedef{PYG@tok@gt}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.27,0.87}{##1}}} +\@namedef{PYG@tok@err}{\def\PYG@bc##1{{\setlength{\fboxsep}{\string -\fboxrule}\fcolorbox[rgb]{1.00,0.00,0.00}{1,1,1}{\strut ##1}}}} +\@namedef{PYG@tok@kc}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kd}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kn}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@kr}{\let\PYG@bf=\textbf\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@bp}{\def\PYG@tc##1{\textcolor[rgb]{0.00,0.44,0.13}{##1}}} +\@namedef{PYG@tok@fm}{\def\PYG@tc##1{\textcolor[rgb]{0.02,0.16,0.49}{##1}}} +\@namedef{PYG@tok@vc}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vg}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vi}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@vm}{\def\PYG@tc##1{\textcolor[rgb]{0.73,0.38,0.84}{##1}}} +\@namedef{PYG@tok@sa}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sb}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sc}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@dl}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@s2}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@sh}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@s1}{\def\PYG@tc##1{\textcolor[rgb]{0.25,0.44,0.63}{##1}}} +\@namedef{PYG@tok@mb}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mf}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mh}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mi}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@il}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@mo}{\def\PYG@tc##1{\textcolor[rgb]{0.13,0.50,0.31}{##1}}} +\@namedef{PYG@tok@ch}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cm}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@cpf}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} +\@namedef{PYG@tok@c1}{\let\PYG@it=\textit\def\PYG@tc##1{\textcolor[rgb]{0.25,0.50,0.56}{##1}}} + +\def\PYGZbs{\char`\\} +\def\PYGZus{\char`\_} +\def\PYGZob{\char`\{} +\def\PYGZcb{\char`\}} +\def\PYGZca{\char`\^} +\def\PYGZam{\char`\&} +\def\PYGZlt{\char`\<} +\def\PYGZgt{\char`\>} +\def\PYGZsh{\char`\#} +\def\PYGZpc{\char`\%} +\def\PYGZdl{\char`\$} +\def\PYGZhy{\char`\-} +\def\PYGZsq{\char`\'} +\def\PYGZdq{\char`\"} +\def\PYGZti{\char`\~} +% for compatibility with earlier versions +\def\PYGZat{@} +\def\PYGZlb{[} +\def\PYGZrb{]} +\makeatother + +% Sphinx redefinitions +% Originally to obtain a straight single quote via package textcomp, then +% to fix problems for the 5.0.0 inline code highlighting (captions!). +% The \text is from amstext, a dependency of sphinx.sty. It is here only +% to avoid build errors if for some reason expansion is in math mode. +\def\PYGZbs{\text\textbackslash} +\def\PYGZus{\_} +\def\PYGZob{\{} +\def\PYGZcb{\}} +\def\PYGZca{\text\textasciicircum} +\def\PYGZam{\&} +\def\PYGZlt{\text\textless} +\def\PYGZgt{\text\textgreater} +\def\PYGZsh{\#} +\def\PYGZpc{\%} +\def\PYGZdl{\$} +\def\PYGZhy{\sphinxhyphen}% defined in sphinxlatexstyletext.sty +\def\PYGZsq{\text\textquotesingle} +\def\PYGZdq{"} +\def\PYGZti{\text\textasciitilde} +\makeatletter +% use \protected to allow syntax highlighting in captions +\protected\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+{\PYG@do{#2}}} +\makeatother diff --git a/docs/build/latex/sphinxhowto.cls b/docs/build/latex/sphinxhowto.cls new file mode 100644 index 0000000000000000000000000000000000000000..8d7dd0ee7185687b4404c3e0480b20e1ed0fd4eb --- /dev/null +++ b/docs/build/latex/sphinxhowto.cls @@ -0,0 +1,102 @@ +% +% sphinxhowto.cls for Sphinx (https://www.sphinx-doc.org/) +% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{sphinxhowto}[2019/12/01 v2.3.0 Document class (Sphinx howto)] + +% 'oneside' option overriding the 'twoside' default +\newif\if@oneside +\DeclareOption{oneside}{\@onesidetrue} +% Pass remaining document options to the parent class. +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} +\ProcessOptions\relax + +% Default to two-side document +\if@oneside +% nothing to do (oneside is the default) +\else +\PassOptionsToClass{twoside}{\sphinxdocclass} +\fi + +\LoadClass{\sphinxdocclass} + +% Set some sane defaults for section numbering depth and TOC depth. You can +% reset these counters in your preamble. +% +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{2}% i.e. section and subsection + +% Adapt \and command to the flushright context of \sphinxmaketitle, to +% avoid ragged line endings if author names do not fit all on one single line +\DeclareRobustCommand{\and}{% + \end{tabular}\kern-\tabcolsep + \allowbreak + \hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}% +}% +% If it is desired that each author name be on its own line, use in preamble: +%\DeclareRobustCommand{\and}{% +% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}% +%}% +% Change the title page to look a bit better, and fit in with the fncychap +% ``Bjarne'' style a bit better. +% +\newcommand{\sphinxmaketitle}{% + \noindent\rule{\linewidth}{1pt}\par + \begingroup % for PDF information dictionary + \def\endgraf{ }\def\and{\& }% + \pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup + \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}% + \endgroup + \begin{flushright} + \sphinxlogo + \py@HeaderFamily + {\Huge \@title }\par + {\itshape\large \py@release \releaseinfo}\par + \vspace{25pt} + {\Large + \begin{tabular}[t]{c} + \@author + \end{tabular}\kern-\tabcolsep}\par + \vspace{25pt} + \@date \par + \py@authoraddress \par + \end{flushright} + \@thanks + \setcounter{footnote}{0} + \let\thanks\relax\let\maketitle\relax + %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} +} + +\newcommand{\sphinxtableofcontents}{% + \begingroup + \parskip \z@skip + \sphinxtableofcontentshook + \tableofcontents + \endgroup + \noindent\rule{\linewidth}{1pt}\par + \vspace{12pt}% +} +\newcommand\sphinxtableofcontentshook{} +\pagenumbering{arabic} + +% Fix the bibliography environment to add an entry to the Table of +% Contents. +% For an article document class this environment is a section, +% so no page break before it. +% +\newenvironment{sphinxthebibliography}[1]{% + % \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}% + \addcontentsline{toc}{section}{\ifdefined\refname\refname\else\ifdefined\bibname\bibname\fi\fi}}{\end{thebibliography}} + + +% Same for the indices. +% The memoir class already does this, so we don't duplicate it in that case. +% +\@ifclassloaded{memoir} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}} + {\newenvironment{sphinxtheindex}{% + \phantomsection % needed because no chapter, section, ... is created by theindex + \begin{theindex}% + \addcontentsline{toc}{section}{\indexname}}{\end{theindex}}} diff --git a/docs/build/latex/sphinxlatexadmonitions.sty b/docs/build/latex/sphinxlatexadmonitions.sty new file mode 100644 index 0000000000000000000000000000000000000000..76fef5a8c4f4e251985995cd994c3a5b0fece4f0 --- /dev/null +++ b/docs/build/latex/sphinxlatexadmonitions.sty @@ -0,0 +1,403 @@ +%% NOTICES AND ADMONITIONS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexadmonitions}[2024/10/11 v8.1.1 admonitions] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - sphinxseealso environment added at 6.1.0. +% +% - sphinxtodo environment added at 7.4.0. +% +% - sphinxadmonition (environment) +% This is a dispatch which formerly configured +% +% - note, hint, important, tip to use sphinxlightbox (or optionally +% sphinxheavybox since 6.2.0), +% - warning, caution, attention, danger, error to use sphinxheavybox. +% +% Since 7.4.0 all admonitions use sphinxheavybox. +% +% - All environments sphinxnote, sphinxwarning, etc... can be redefined as +% will by user. Thay have a single parameter #1 which is the title. +% +% - Also redefinable by user are the one-argument commands +% * \sphinxstylenotetitle, +% * \sphinxstylewarningtitle, +% * etc.... one for each admonition type (also seealso and todo). +% +% - At 7.4.0, all commands of previous item use \sphinxdotitlerow. +% (the 7.4.0 name, still usable, was \sphinxdotitlerowwithicon; the 8.1.0 +% version is also used for topic, contents and sidebar directives, see +% sphinxlatexshadowbox.sty, and handles both "with icon" and "without +% icon" situations). +% +% The sphinxlightbox environment is kept for backward compatiblity, for user +% custom code which used it via custom definitions done in preamble or via +% raw latex directive. +% MEMO: here is for example how sphinxnote was formerly defined: +% (where #1 is the localized string Note, followed with a colon) +% \newenvironment{sphinxnote}[1] +% {\begin{sphinxlightbox}\sphinxstrong{#1} } +% {\end{sphinxlightbox}} +% Use this if you want to revert the 7.4.0 switch to usage of sphinxheavybox. +% (the 7.4.0 redefined \sphinxstylenotetitle will not work in sphinxlightbox, +% so \sphinxstrong{#1} which was its former default is used above). + +% Dependencies (they do not need to be defined at time of loading): +% +% - of course the various colour and dimension options handled via sphinx.sty +% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty +% - \savenotes/\spewnotes from sphinxpackagefootnote.sty +% - \ifspx@inframed defined in sphinx.sty +% - \spx@boxes@fcolorbox@setup from sphinxpackageboxes.sty +% +\RequirePackage{framed} +% Those are required either before or after by sphinx.sty anyhow, but for +% clarity we list them here: +\RequirePackage{sphinxlatexgraphics} +\RequirePackage{sphinxpackagefootnote} +\RequirePackage{sphinxpackageboxes} +% +% Provides: (also in sphinxlatexliterals.sty) +% Only needed here by legacy (deprecated) sphinxlightbox environment. +\providecommand*\sphinxvspacefixafterfrenchlists{% + \ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi +} + +% This \dimen register is a legacy relic from Sphinx 1.5 which is used now +% only for sphinxlightbox. It is set in the sphinxadmonition environment. +\newdimen\spx@notice@border +% sphinxlightbox is now also a legacy relic, not used by Sphinx anymore +\newenvironment{sphinxlightbox}{% + \par + \noindent{\color{spx@notice@bordercolor}% + \rule{\linewidth}{\spx@notice@border}}% + \par\nobreak + {\parskip\z@skip\noindent}% + } + {% + % counteract previous possible negative skip (French lists!): + % (we can't cancel that any earlier \vskip introduced a potential pagebreak) + \sphinxvspacefixafterfrenchlists + \nobreak\vbox{\noindent\kern\@totalleftmargin + {\color{spx@notice@bordercolor}% + \rule[\dimexpr.4\baselineskip-\spx@notice@border\relax] + {\linewidth}{\spx@notice@border}}\hss}\allowbreak + }% end of sphinxlightbox environment definition + +% Since 1.5 these environments are named individually sphinxnote, sphinxhint, +% etc... to allow user to redefine them entirely. +% +% The Sphinx definitions for note/hint/important/tip notices were done like +% this, prior to 6.2.0: +% +% \newenvironment{sphinxhint}[1] +% {\begin{sphinxlightbox}\sphinxstrong{#1} }{\end{sphinxlightbox}} +% +% Then from 6.2.0 to 7.4.0 (exclusive) a more complex definition decided +% to use either sphinxlightbox or sphinxheavybox according to whether +% some CSS-like options had been used, for example for a background color. +% +% 6.2.0 also added one layer of mark-up via \sphinxnotetitle etc..., because +% the former \sphinxstrong{#1} used a too generic \sphinxstrong. +% +% At 7.4.0, sphinxheavybox environment is default for all types of notices +% and also for the seealso and todo directives. +% +% Code adapted from framed.sty's "snugshade" environment. +% Nesting works (inner frames do not allow page breaks). +\newenvironment{sphinxheavybox}{\par + % (MEMO: it is not a problem here if there is no sphinxShadowColor, + % as it used only if set) + \spx@boxes@fcolorbox@setup{\spx@noticetype}% + % Those are used by sphinxVerbatim if the \ifspx@inframed boolean is true + \setlength{\FrameRule}{0.5\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom\relax}% + % MEMO: prior to 5.1.0 \FrameSep was determined as 0.6\baselineskip - + % \FrameRule, and there was no possibility for user to adjust padding. + % Then \fcolorbox was used with \fboxrule set to \FrameRule and \fboxsep + % set to \FrameSep. + % The 5.1.0 default calculation of padding parameters maintains PDF output + % identical to legacy behaviour, as long as padding is not set by user. + \setlength{\FrameSep}{0.5\dimexpr\spx@boxes@padding@top+\spx@boxes@padding@bottom\relax}% + % "setup" macro has prepared the \spx@boxes@... dimen registers + \advance\spx@image@maxheight + -\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom + +\spx@boxes@padding@top+\spx@boxes@padding@bottom + +\baselineskip\relax % will happen again if nested, needed indeed! + % MEMO: the next comment is before boxing was extended to allow padding and + % multiple border-widths, not to mention shadows... + % configure framed.sty's parameters to obtain same vertical spacing + % as for "light" boxes. We need for this to manually insert parskip glue and + % revert a skip done by framed before the frame. + \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% + \vspace{\FrameHeightAdjust} + % copied/adapted from framed.sty's snugshade + % but now using in place of \fcolorbox the Sphinx sophisticated own + \def\FrameCommand##1{% + \hskip\@totalleftmargin + % "setup" macro MUST have been called before + \spx@boxes@fcolorbox{##1}% + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth + }% + % 6.2.0 adds support for div._box-decoration-break=slice. + % (it is yet undecided if slice style should inhibit a bottom shadow) + \csname ifspx@\spx@noticetype @border@open\endcsname + \def\FirstFrameCommand + {\spx@boxes@fcolorbox@setup@openbottom\FrameCommand}% + \def\MidFrameCommand + {\spx@boxes@fcolorbox@setup@openboth \FrameCommand}% + \def\LastFrameCommand + {\spx@boxes@fcolorbox@setup@opentop \FrameCommand}% + \fi + \savenotes + % use a minipage if we are already inside a framed environment + \ifspx@inframed + \noindent\begin{minipage}{\linewidth} + \else + % handle case where notice is first thing in a list item (or is quoted) + \if@inlabel + \noindent\par\vspace{-\baselineskip} + \else + \vspace{\parskip} + \fi + \fi + \MakeFramed {\spx@inframedtrue + \advance\hsize-\width \@totalleftmargin\z@ \linewidth\hsize + % minipage initialization copied from LaTeX source code. + \@pboxswfalse + \let\@listdepth\@mplistdepth \@mplistdepth\z@ + \@minipagerestore + \@setminipage }% + \color@begingroup % workaround to an upstream framed.sty bug + } + {% + \par\unskip + \color@endgroup % matches the \color@begingroup + \@minipagefalse + \endMakeFramed + \ifspx@inframed\end{minipage}\fi + % set footnotes at bottom of page + \spewnotes + % arrange for similar spacing below frame as for "light" boxes. + \vskip .4\baselineskip + }% end of sphinxheavybox environment definition + +% - Since 1.5 these environments are named individually to allow user to +% redefine them entirely. +% +% - Since 5.1.0, sphinxheavybox is more versatile and four border widths, four +% padding widths, four corner radii, optional shadow, and three colors can all +% be modified via CSS-named alike options. +% +% - Since 6.2.0, also note/hint/important/tip notices can use these options +% and then they go automatically via sphinxheavybox. If only the legacy options +% are used, they keep using sphinxlightbox. +% +% - Since 6.2.0, \sphinxwarningtitle etc... add one level of mark-up (they +% expand to \sphinxstrong{#1} which was former hard-coded mark-up). +% Example: +% \renewcommand{\sphinxwarningtitle}[1]{\textbf{#1}\par\smallskip +% {\color{sphinxwarningBorderColor}\hrule height1pt}\smallskip} +% +% - Since 7.4.0, all types of notices use sphinxheavybox and the default +% for \sphinxstyletitle is mapped to using \sphinxdotitlerowwithicon{} +% +% MEMO: except for the generic admonition directive (which uses "note" type) +% the argument #1 in these environments has a postfixed colon originating +% in Sphinx LaTeX writer legacy code. The +% \sphinxremovefinalcolon utility in sphinxlatexstyletext.sty can be used as +% \sphinxremovefinalcolon{#1} from inside the definitions of +% \sphinxstylenotetitle et al. commands. + +% Important: even prior to 5.1.0 it was not really possible to use directly +% sphinxheavybox if not triggered from sphinxadmonition, because some +% parameters were defined in sphinxadmonition. This meant that the +% sphinxwarning, sphinxcaution etc... environments (defined below) could not +% be used directly in a document, they had to be triggered via +% sphinxadmonition. The sole data since 5.1.0 needed by sphinxheavybox is the +% type of the notice which sphinxadmonition stores into \spx@noticetype. +% +% In order to facilitate recycling or imitation of the sphinx +% environments, 7.4.0 inserts an extra \def\spx@noticetype{} in their +% definitions, so that they can be used independently of sphinxadmonition +% dispatcher. +% +% MEMO: direct usage of these environments does not execute the div._TeXextras +% and div._TexColor code, there are only done from the sphinxadmonition wrapper. +\newenvironment{sphinxnote}[1] + {\def\spx@noticetype{note}\begin{sphinxheavybox}\sphinxstylenotetitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxhint}[1] + {\def\spx@noticetype{hint}\begin{sphinxheavybox}\sphinxstylehinttitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxtip}[1] + {\def\spx@noticetype{tip}\begin{sphinxheavybox}\sphinxstyletiptitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinximportant}[1] + {\def\spx@noticetype{important}\begin{sphinxheavybox}\sphinxstyleimportanttitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxwarning}[1] + {\def\spx@noticetype{warning}\begin{sphinxheavybox}\sphinxstylewarningtitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxcaution}[1] + {\def\spx@noticetype{caution}\begin{sphinxheavybox}\sphinxstylecautiontitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxattention}[1] + {\def\spx@noticetype{attention}\begin{sphinxheavybox}\sphinxstyleattentiontitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxdanger}[1] + {\def\spx@noticetype{danger}\begin{sphinxheavybox}\sphinxstyledangertitle{#1}} + {\end{sphinxheavybox}} +\newenvironment{sphinxerror}[1] + {\def\spx@noticetype{error}\begin{sphinxheavybox}\sphinxstyleerrortitle{#1}} + {\end{sphinxheavybox}} +% The "see also" was quite plain until 7.4.0 as it simply did +% \newenvironment{sphinxseealso}[1]{\sphinxstyleseealsotitle{#1}}{} +% Here we need to manually insert execution of div.seealso_TeX{color,extras} values +\newenvironment{sphinxseealso}[1] + {\def\spx@noticetype{seealso}% + \begin{sphinxheavybox}\sphinxstyleseealsotitle{#1}% + \ifspx@seealso@withtextcolor\color{sphinxseealsoTextColor}\fi + \spx@seealso@TeXextras + } + {\end{sphinxheavybox}} +% There was no sphinxtodo environment until 7.4.0 because sphinx.ext.todo +% generated \begin{sphinxadmonition}{note}{Todo:} mark-up. +\newcounter{sphinxtodo}% to provide targets from todolist directive output +\newenvironment{sphinxtodo}[1] + {\refstepcounter{sphinxtodo}\def\spx@noticetype{todo}% + \begin{sphinxheavybox}\sphinxstyletodotitle{#1}% + \ifspx@todo@withtextcolor\color{sphinxtodoTextColor}\fi + \spx@todo@TeXextras + } + {\end{sphinxheavybox}} + + +% the main dispatch for all types of notices +\newenvironment{sphinxadmonition}[2]{% #1=type, #2=heading + % can't use #1 directly in definition of end part + \def\spx@noticetype {#1}% + % those next three are a remnant of legacy code; they are not used at + % all by sphinxheavybox, and their usage could be disposed of by sphinxlightbox + % but we keep for backward compatibility and also because it may be simpler + % for user redefinitions to employ for example "spx@notice@bgcolor" and not + % the more bulky "sphinx\spx@noticetype BgColor". + \sphinxcolorlet{spx@notice@bordercolor}{sphinx#1BorderColor}% + \sphinxcolorlet{spx@notice@bgcolor}{sphinx#1BgColor}% + % At 7.4.0 there are no \spx@@boder macros anymore only top, left, + % bottom, right. For this legacy \spx@notice@border only needed by + % sphinxlightbox (which is not used by own Sphinx environments anymore) + % we thus use here @top + \spx@notice@border \dimexpr\csname spx@#1@border@top\endcsname\relax + % trigger the sphinx environment, #2=heading is passed as argument + \begin{sphinx#1}{#2}% + % MEMO: the heading #2 will be typeset before the next lines are executed + % 6.2.0 support of div._TeX{color,extras} options + \csname ifspx@\spx@noticetype @withtextcolor\endcsname + \color{sphinx\spx@noticetype TextColor}% + \fi + % Other code to be executed at start of contents (after title) + \csname spx@\spx@noticetype @TeXextras\endcsname + } + % workaround some LaTeX "feature" of \end command (i.e. can't use "sphinx#1" here) + {\edef\spx@temp{\noexpand\end{sphinx\spx@noticetype}}\spx@temp} + +% TODO: allow these next three settings to be customized individually. +% This can however already be done at user level by \renewcommand +% inside renew'ed environments sphinxnote, sphinxhint etc... +\newcommand\sphinxtitlerowtoppadding{5pt} +\newcommand\sphinxtitlerowbottompadding{3pt} +\newcommand\sphinxtitlerowaftericonspacecmd{\hskip0.5em\relax} +% 7.4.0 used this longer name: +\newcommand\sphinxdotitlerowwithicon{\sphinxdotitlerow} +\newcommand\sphinxdotitlerow[2]{% #1=type, #2=heading (without final colon) + \begingroup + \kern-\spx@boxes@padding@top + \parskip\z@skip % the \parskip business is a workaround to a vertical + % glue issue showing in LaTeX earlier than 2023-06-01 + \noindent + \kern-\spx@boxes@padding@left % must have been configured by a prior + % \spx@boxes@fcolorbox@setup{} + % inherit settings from the enclosing box and modify what is needed + \spx@boxes@border@top =\z@ + \spx@boxes@border@right =\z@ + \spx@boxes@border@bottom =\z@ + \spx@boxes@border@left =\z@ + \spx@boxes@radius@bottomright@x=\z@ + \spx@boxes@radius@bottomright@y=\z@ + \spx@boxes@radius@bottomleft@x=\z@ + \spx@boxes@radius@bottomleft@x=\z@ + \spx@boxes@padding@top =\sphinxtitlerowtoppadding\relax + \spx@boxes@padding@bottom=\sphinxtitlerowbottompadding\relax + \spx@boxes@withshadowfalse + \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1TtlBgColor}% + \spx@boxes@fcolorbox{% + \parbox[t]{\linewidth}{% 7.4.0 used \makebox, but wrapping of long titles + % is needed for generic admonition or topic box. + \sphinxAtStartPar + % 8.1.0 auto-drops extra space if no icon + \sbox\z@{\@nameuse{sphinx#1TtlIcon}}% + \ifdim\wd\z@>\z@ + \textcolor{sphinx#1TtlFgColor}{% + \@nameuse{sphinx#1TtlIcon}% + % The next macro is located here for legacy reasons of earlier + % functioning of \spx@faIcon. When fontawesome{5,}.sty both + % are unavailable, it (formerly) gobbled this next macro. + % We leave it here now although it could be moved to after + % the closing brace. + \sphinxtitlerowaftericonspacecmd + }% + \fi + \sphinxstrong{#2}% + \strut + \par + }% + }% + \kern-\spx@boxes@padding@right + \par + \endgroup + \vskip-\parskip + \kern\spx@boxes@padding@top +} + +% #1 holds the localized name of the notice, postfixed with a colon. +% \sphinxremovefinalcolon{#1} will typeset #1 without the colon. +% Legacy definitions (done in sphinxlatexstyletext.sty) were all using +% a boring plain \sphinxstrong{#1}, now we use a coloured title row. +\newcommand\sphinxstylenotetitle [1]{\sphinxdotitlerow{note}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylehinttitle [1]{\sphinxdotitlerow{hint}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleimportanttitle[1]{\sphinxdotitlerow{important}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyletiptitle [1]{\sphinxdotitlerow{tip}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylewarningtitle [1]{\sphinxdotitlerow{warning}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstylecautiontitle [1]{\sphinxdotitlerow{caution}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleattentiontitle[1]{\sphinxdotitlerow{attention}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyledangertitle [1]{\sphinxdotitlerow{danger}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleerrortitle [1]{\sphinxdotitlerow{error}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyleseealsotitle [1]{\sphinxdotitlerow{seealso}{\sphinxremovefinalcolon{#1}}} +\newcommand\sphinxstyletodotitle [1]{\sphinxdotitlerow{todo}{\sphinxremovefinalcolon{#1}}} +% +% A utility to remove a final colon. Removing last token is not easy in +% LaTeX, and there are additional complications: +% - some languages will make the : "active" in document body, +% - the generic admonition ends up using "note", so for \sphinxnotetitle to +% use it safely, the utility has to allow an input not having any final colon. +% - a bit far-fetched but maybe there is more than one colon inside the input +% (possible from a generic admonition title). +% Hence the scary code. +\newcommand\sphinxremovefinalcolon[1]{% #1 is the "active" : TeX token +% Prior to 7.4.0 this was defined with \protected\def but we do not +% see what usefulness this could have. +\renewcommand\sphinxremovefinalcolon[1]{% + % complications due to : possibly "active" + \begingroup\ifnum\catcode`:=\active + \def\x####1#1\relax{####1}% + \else\def\x####1:\relax{####1}\fi + \expandafter\endgroup\x##1\relax + % trick to let \x work also if input ##1 has no ending colon + \@gobblefour#1\relax:\relax\relax\relax + }% +}% end of wrapper to inject active : +\begingroup\catcode`:\active\expandafter\endgroup\sphinxremovefinalcolon: + +\endinput diff --git a/docs/build/latex/sphinxlatexcontainers.sty b/docs/build/latex/sphinxlatexcontainers.sty new file mode 100644 index 0000000000000000000000000000000000000000..012d9ee7372bb0e72a9514c3ad861ad03fb97d56 --- /dev/null +++ b/docs/build/latex/sphinxlatexcontainers.sty @@ -0,0 +1,22 @@ +%% CONTAINER DIRECTIVES +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexcontainers}[2021/05/03 containers] + +% The purpose of this file is to provide a dummy environment sphinxclass which +% will be inserted for each class in each container directive. The class name +% will be passed as the argument to the environment. +% +% For a class foo, the user can define customised handling of that class by +% defining the sphinxclassfoo LaTeX environment. + +\newenvironment{sphinxuseclass}[1]{% + \def\sphinxClassFunctionName{sphinxclass#1}% + \ltx@ifundefined{\sphinxClassFunctionName}% + {}% undefined so do nothing + {\expandafter\begin\expandafter{\sphinxClassFunctionName}}% +}{% + \ltx@ifundefined{\sphinxClassFunctionName}% + {}% we did nothing so we keep doing nothing + {\expandafter\end\expandafter{\sphinxClassFunctionName}}% +}% diff --git a/docs/build/latex/sphinxlatexgraphics.sty b/docs/build/latex/sphinxlatexgraphics.sty new file mode 100644 index 0000000000000000000000000000000000000000..f0c7c25f0ca115ef3ff7e14ba25f2cc63f0a89dc --- /dev/null +++ b/docs/build/latex/sphinxlatexgraphics.sty @@ -0,0 +1,123 @@ +%% GRAPHICS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexgraphics}[2024/08/13 v8.1.0 graphics] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - macros: +% +% - \sphinxfigcaption +% - \sphinxincludegraphics +% +% - environments: +% +% - sphinxfigure-in-table +% +% May change: +% +% - \sphinxcaption (at begin document) +% +% Also provides: +% +% - \sphinxsafeincludegraphics (default of \sphinxincludegraphics since 2.0) +% - \spx@image@maxheight dimension (used by sphinxlatexadmonitions.sty) +% - \spx@image@box scratch box register (also used by sphinxlatexliterals.sty) +% +% Requires: +% \RequirePackage{graphicx}% done in sphinx.sty +\RequirePackage{amstext}% needed for \firstchoice@true(false) + +% \sphinxincludegraphics resizes images larger than the TeX \linewidth (which +% is adjusted in indented environments), or taller than a certain maximal +% height (usually \textheight and this is reduced in the environments which use +% framed.sty to avoid infinite loop if image too tall). +% +% In case height or width options are present the rescaling is done +% (since 2.0), in a way keeping the width:height ratio either native from +% image or from the width and height options if both were present. +% +\newdimen\spx@image@maxheight +\AtBeginDocument{\spx@image@maxheight\textheight} + +% box scratch register +\newbox\spx@image@box +\newcommand*{\sphinxsafeincludegraphics}[2][]{% + % #1 contains possibly width=, height=, but no scale= since 1.8.4 + \setbox\spx@image@box\hbox{\includegraphics[#1,draft]{#2}}% + \in@false % use some handy boolean flag + \ifdim \wd\spx@image@box>\linewidth + \in@true % flag to remember to adjust options and set box dimensions + % compute height which results from rescaling width to \linewidth + % and keep current aspect ratio. multiply-divide in \numexpr uses + % temporarily doubled precision, hence no overflow. (of course we + % assume \ht is not a few sp's below \maxdimen...(about 16384pt). + \edef\spx@image@rescaledheight % with sp units + {\the\numexpr\ht\spx@image@box + *\linewidth/\wd\spx@image@box sp}% + \ifdim\spx@image@rescaledheight>\spx@image@maxheight + % the rescaled height will be too big, so it is height which decides + % the rescaling factor + \def\spx@image@requiredheight{\spx@image@maxheight}% dimen register + \edef\spx@image@requiredwidth % with sp units + {\the\numexpr\wd\spx@image@box + *\spx@image@maxheight/\ht\spx@image@box sp}% + % TODO: decide if this commented-out block could be needed due to + % rounding in numexpr operations going up + % \ifdim\spx@image@requiredwidth>\linewidth + % \def\spx@image@requiredwidth{\linewidth}% dimen register + % \fi + \else + \def\spx@image@requiredwidth{\linewidth}% dimen register + \let\spx@image@requiredheight\spx@image@rescaledheight% sp units + \fi + \else + % width is ok, let's check height + \ifdim\ht\spx@image@box>\spx@image@maxheight + \in@true + \edef\spx@image@requiredwidth % with sp units + {\the\numexpr\wd\spx@image@box + *\spx@image@maxheight/\ht\spx@image@box sp}% + \def\spx@image@requiredheight{\spx@image@maxheight}% dimen register + \fi + \fi % end of check of width and height + \ifin@ + \setbox\spx@image@box + \hbox{\includegraphics + [#1,% contains only width and/or height which are overruled next + % but in future may contain page=N hence must be kept + width=\spx@image@requiredwidth,height=\spx@image@requiredheight]% + {#2}}% + % \includegraphics does not set box dimensions to the exactly + % requested ones, see https://github.com/latex3/latex2e/issues/112 + \wd\spx@image@box\spx@image@requiredwidth + \ht\spx@image@box\spx@image@requiredheight + \leavevmode\box\spx@image@box + \else + % here we do not modify the options, no need to adjust width and height + % on output, they will be computed exactly as with "draft" option + \setbox\spx@image@box\box\voidb@x % clear memory + \includegraphics[#1]{#2}% + \fi +}% +% Use the "safe" one by default (2.0) +\def\sphinxincludegraphics{\sphinxsafeincludegraphics} + + +%% FIGURE IN TABLE +% +\newenvironment{sphinxfigure-in-table}[1][\linewidth]{% + \def\@captype{figure}% + \sphinxsetvskipsforfigintablecaption + \begin{minipage}{#1}% +}{\end{minipage}} +% tabulary expands twice contents, we need to prevent double counter stepping +\newcommand*\sphinxfigcaption + {\ifx\equation$%$% this is trick to identify tabulary first pass + \firstchoice@false\else\firstchoice@true\fi + \spx@originalcaption } +\newcommand*\sphinxsetvskipsforfigintablecaption + {\abovecaptionskip\smallskipamount + \belowcaptionskip\smallskipamount} + +\endinput diff --git a/docs/build/latex/sphinxlatexindbibtoc.sty b/docs/build/latex/sphinxlatexindbibtoc.sty new file mode 100644 index 0000000000000000000000000000000000000000..052d31ee2d1763a018b9a92a063ea4eebbce9cf2 --- /dev/null +++ b/docs/build/latex/sphinxlatexindbibtoc.sty @@ -0,0 +1,69 @@ +%% INDEX, BIBLIOGRAPHY, APPENDIX, TABLE OF CONTENTS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexindbibtoc}[2021/01/27 index, bib., toc] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - environments: (backup defaults or get redefined) +% +% - sphinxtheindex (direct mark-up or via python.ist or sphinx.xdy) +% - sphinxthebibliography +% +% - macros: (defines defaults) +% +% - \sphinxmaketitle +% - \sphinxtableofcontents +% - \sphinxnonalphabeticalgroupname +% - \sphinxsymbolsname +% - \sphinxnumbersname +% - \sphinxcite +% +% Requires: +\RequirePackage{makeidx} + +% fix the double index and bibliography on the table of contents +% in jsclasses (Japanese standard document classes) +\ifx\@jsc@uplatextrue\@undefined\else + \renewenvironment{sphinxtheindex} + {\cleardoublepage\phantomsection + \begin{theindex}} + {\end{theindex}} + + \renewenvironment{sphinxthebibliography}[1] + {\cleardoublepage% \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}} + {\end{thebibliography}} +\fi + +% disable \@chappos in Appendix in pTeX +\ifx\kanjiskip\@undefined\else + \let\py@OldAppendix=\appendix + \renewcommand{\appendix}{ + \py@OldAppendix + \gdef\@chappos{} + } +\fi + +% make commands known to non-Sphinx document classes +\providecommand*{\sphinxmaketitle}{\maketitle} +\providecommand*{\sphinxtableofcontents}{\tableofcontents} +\ltx@ifundefined{sphinxthebibliography} + {\newenvironment + {sphinxthebibliography}{\begin{thebibliography}}{\end{thebibliography}}% + } + {}% else clause of \ltx@ifundefined +\ltx@ifundefined{sphinxtheindex} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}}% + {}% else clause of \ltx@ifundefined + +% for usage with xindy: this string gets internationalized in preamble +\newcommand*{\sphinxnonalphabeticalgroupname}{} +% redefined in preamble, headings for makeindex produced index +\newcommand*{\sphinxsymbolsname}{} +\newcommand*{\sphinxnumbersname}{} + +\protected\def\sphinxcite{\cite} + + +\endinput diff --git a/docs/build/latex/sphinxlatexlists.sty b/docs/build/latex/sphinxlatexlists.sty new file mode 100644 index 0000000000000000000000000000000000000000..4db3af2496fbbee74477aca102a7fd39782f1661 --- /dev/null +++ b/docs/build/latex/sphinxlatexlists.sty @@ -0,0 +1,131 @@ +%% ALPHANUMERIC LIST ITEMS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexlists}[2021/12/20 lists] + +% Provides support for this output mark-up from Sphinx latex writer: +% - \sphinxsetlistlabels +% - \sphinxlineitem +% and for the maxlistdepth key of sphinxsetup +% Dependencies: the \spx@opt@maxlistdepth from sphinx.sty + +% We need some helpers macros +\newtoks\spx@lineitemlabel +\long\def\sphinx@gobto@sphinxlineitem#1\sphinxlineitem{} +% TeX/LaTeX has no (easy to use) built-in "peek-ahead" mechanism, but +% we would like to know if next token is another \sphinxlineitem (this +% can happen in glossary entries with multiple terms for same definition) +% so we simply grab next token (assuming it is not {tokens} originally) +\newcommand\sphinxlineitem[2]{% + % safe test of whether #2 is \sphinxlineitem + \sphinx@gobto@sphinxlineitem#2\@gobbletwo\sphinxlineitem\unless + \iftrue + % case with sphinxlineitem immediately followed by another \sphinxlineitem: + % accumulate successive terms until actual definition or sub-list is found + \spx@lineitemlabel\expandafter{\the\spx@lineitemlabel\strut#1\\}% + \else + % now issue the \item command with possibly multi-line contents + % these weird incantations with \kern are related to how LaTeX + % handles \item generally + \item[\kern\labelwidth\kern-\itemindent\kern-\leftmargin + {\parbox[t]{\dimexpr\linewidth+\leftmargin\relax}{% + \raggedright + \the\spx@lineitemlabel% accumulated terms before this one, CR separated + \strut#1}}% due to LaTeX internals no \par token allowed here, + % but the \parbox will insert one tacitly at end + \kern-\labelsep]% + \spx@lineitemlabel{}% + % this causes the label to be typeset (filling up the line), clearing up + % things in case a nested list follows. + \leavevmode + \fi #2% +}% + + +\newcommand\sphinxsetlistlabels[5] +{% #1 = style, #2 = enum, #3 = enumnext, #4 = prefix, #5 = suffix + % #2 and #3 are counters used by enumerate environment e.g. enumi, enumii. + % #1 is a macro such as \arabic or \alph + % prefix and suffix are strings (by default empty and a dot). + \@namedef{the#2}{#1{#2}}% + \@namedef{label#2}{#4\@nameuse{the#2}#5}% + \@namedef{p@#3}{\@nameuse{p@#2}#4\@nameuse{the#2}#5}% +}% + + +%% MAXLISTDEPTH +% +% remove LaTeX's cap on nesting depth if 'maxlistdepth' key used. +% This is a hack, which works with the standard classes: it assumes \@toodeep +% is always used in "true" branches: "\if ... \@toodeep \else .. \fi." + +% will force use the "false" branch (if there is one) +\def\spx@toodeep@hack{\fi\iffalse} + +% do nothing if 'maxlistdepth' key not used or if package enumitem loaded. +\ifnum\spx@opt@maxlistdepth=\z@\expandafter\@gobbletwo\fi +\AtBeginDocument{% +\@ifpackageloaded{enumitem}{\remove@to@nnil}{}% + \let\spx@toodeepORI\@toodeep + \def\@toodeep{% + \ifnum\@listdepth<\spx@opt@maxlistdepth\relax + \expandafter\spx@toodeep@hack + \else + \expandafter\spx@toodeepORI + \fi}% +% define all missing \@list... macros + \count@\@ne + \loop + \ltx@ifundefined{@list\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \expandafter\let + \csname @list\romannumeral\the\count@\expandafter\endcsname + \csname @list\romannumeral\the\numexpr\count@-\@ne\endcsname + % workaround 2.6--3.2d babel-french issue (fixed in 3.2e; no change needed) + \ltx@ifundefined{leftmargin\romannumeral\the\count@} + {\expandafter\let + \csname leftmargin\romannumeral\the\count@\expandafter\endcsname + \csname leftmargin\romannumeral\the\numexpr\count@-\@ne\endcsname}{}% + \advance\count@\@ne + \repeat +% define all missing enum... counters and \labelenum... macros and \p@enum.. + \count@\@ne + \loop + \ltx@ifundefined{c@enum\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \newcounter{enum\romannumeral\the\count@}% + \expandafter\def + \csname labelenum\romannumeral\the\count@\expandafter\endcsname + \expandafter + {\csname theenum\romannumeral\the\numexpr\count@\endcsname.}% + \expandafter\def + \csname p@enum\romannumeral\the\count@\expandafter\endcsname + \expandafter + {\csname p@enum\romannumeral\the\numexpr\count@-\@ne\expandafter + \endcsname\csname theenum\romannumeral\the\numexpr\count@-\@ne\endcsname.}% + \advance\count@\@ne + \repeat +% define all missing labelitem... macros + \count@\@ne + \loop + \ltx@ifundefined{labelitem\romannumeral\the\count@} + {\iffalse}{\iftrue\advance\count@\@ne}% + \repeat + \loop + \ifnum\count@>\spx@opt@maxlistdepth\relax\else + \expandafter\let + \csname labelitem\romannumeral\the\count@\expandafter\endcsname + \csname labelitem\romannumeral\the\numexpr\count@-\@ne\endcsname + \advance\count@\@ne + \repeat + \PackageInfo{sphinx}{maximal list depth extended to \spx@opt@maxlistdepth}% +\@gobble\@nnil +} + +\endinput diff --git a/docs/build/latex/sphinxlatexliterals.sty b/docs/build/latex/sphinxlatexliterals.sty new file mode 100644 index 0000000000000000000000000000000000000000..11991d9c3e81187ae4bf8af68ebb7e2a3f27ed41 --- /dev/null +++ b/docs/build/latex/sphinxlatexliterals.sty @@ -0,0 +1,1000 @@ +%% LITERAL BLOCKS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexliterals}[2024/07/01 v7.4.0 code-blocks and parsed literals] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - macros: +% - \sphinxLiteralBlockLabel +% - \sphinxSetupCaptionForVerbatim +% - \sphinxSetupCodeBlockInFootnote +% - \sphinxhref +% - \sphinxnolinkurl +% - \sphinxresetverbatimhllines +% - \sphinxunactivateextrasandspace +% - \sphinxupquote +% - \sphinxurl +% +% - environments: +% - sphinxVerbatim +% - sphinxVerbatimintable +% - sphinxalltt +% +% Dependency: +% +% - hyperref (for \phantomsection and \capstart) (loaded later) +% +% Executes \RequirePackage for: +% +% - framed +% - fancyvrb +% - alltt +% - upquote +% - needspace +% - sphinxpackageboxes +\RequirePackage{sphinxpackageboxes} +% 7.4.0 removes unneeded usage of \spx@boxes@border + +% also in sphinxlatexadmonitions.sty: +% This is a workaround to a "feature" of French lists, when literal block +% follows immediately; usable generally (does only \par then), a priori... +\providecommand*\sphinxvspacefixafterfrenchlists{% + \ifvmode\ifdim\lastskip<\z@ \vskip\parskip\fi\else\par\fi +} + +% For framing allowing pagebreaks +\RequirePackage{framed} +% For source code +% MEMO: fancyvrb is used mainly to +% 1- control horizontal and vertical spacing +% 2- optional line numbering +% 3- optional line emphasizing +% 4- while still allowing expansion of Pygments latex mark-up +% Other aspects such as framing, caption handling, codeline wrapping are +% added on top of it. We should stop using fancyvrb and implement +% 1, 2, 3, 4 by own Sphinx fully native Verbatim. This would greatly simplify +% in particular wrapping long code lines in a way allowing page breaks. +\RequirePackage{fancyvrb} +% For parsed-literal blocks. +\RequirePackage{alltt} +% Display "real" single quotes in literal blocks. +\RequirePackage{upquote} +% Skip to next page if not enough space at bottom +\RequirePackage{needspace} + +% Based on use of "fancyvrb.sty"'s Verbatim. +% - with framing allowing page breaks ("framed.sty") +% - with breaking of long lines (exploits Pygments mark-up), +% - with possibly of a top caption, non-separable by pagebreak. +% - and usable inside tables or footnotes ("sphinxpackagefootnote.sty"). + +% for emphasizing lines +\define@key{FV}{hllines}{\def\sphinx@verbatim@checkifhl##1{\in@{, ##1,}{#1}}} +% sphinxVerbatim must be usable by third party without requiring hllines set-up +\def\sphinxresetverbatimhllines{\def\sphinx@verbatim@checkifhl##1{\in@false}} +\sphinxresetverbatimhllines + +% Prior to Sphinx 1.5, \Verbatim and \endVerbatim were modified by Sphinx. +% The aliases defined here are used in sphinxVerbatim environment and can +% serve as hook-points with no need to modify \Verbatim itself. +\let\OriginalVerbatim \Verbatim +\let\endOriginalVerbatim\endVerbatim + +% for captions of literal blocks +% at start of caption title +\newcommand*{\fnum@literalblock}{\literalblockname\nobreakspace\theliteralblock} +% this will be overwritten in document preamble by Babel translation +\newcommand*{\literalblockname}{Listing } +% file extension needed for \caption's good functioning, the file is created +% only if a \listof{literalblock}{foo} command is encountered, which is +% analogous to \listoffigures, but for the code listings (foo = chosen title.) +\newcommand*{\ext@literalblock}{lol} + +% if forced use of minipage encapsulation is needed (e.g. table cells) +\newif\ifsphinxverbatimwithminipage \sphinxverbatimwithminipagefalse + +% Framing macro for use with framed.sty's \FrameCommand +% MEMO: the sophisticated code in \spx@fcolorbox/\spx@CustomFBox +% is here for good reasons +% - be responsive to indented list environments in the manner of +% the "framed" (\fbox) and "shaded" (\colorbox) environments of +% framed.sty; indeed code here is an evolution related to \fcolorbox +% - attach non-detachable continuation hints above/below frame +% - draw the frame and fill the background color in a manner avoiding +% problems in some pdf viewers +% - do background coloring differently from color.sty/xcolor.sty macros +% (even core internal ones) to work around issues at page breaks +% as the framed contents are split into chunks with possibly unpaired +% "color push" or "color pop" +% About the produced output: +% - it obeys current indentation, +% - frame with 4 padding parameters and 4 border-width parameters +% - the contents use the full available text width, limited by indentation, +% - #1 = will be typeset above frame, in a non detachable way, +% - #2 = will be typeset below frame, in a non detachable way, +% - #3 = will be typeset within the frame. +% #1 and #2 are expected to be already typeset \hbox'es. +% #3 are the contents, and in the context of usage of fancyvrb+framed, +% it will arrive here already transformed into horizontal boxes, +% interline penalties and glues. +% +\long\def\spx@verb@FrameCommand #1#2#3{% + % The \spx@verb@boxes@fcolorbox@setup MUST have been executed beforehand. + % These \hskips are for fancyvrb.sty measuring and will make the + % framing "adapt" to an indented context. + \hskip\@totalleftmargin + \hskip-\spx@boxes@border@left\hskip-\spx@boxes@padding@left + \spx@verb@fcolorbox {#1}{#2}{#3}% + \hskip-\spx@boxes@padding@right\hskip-\spx@boxes@border@right + \hskip-\linewidth \hskip-\@totalleftmargin \hskip\columnwidth +}% +\long\def\spx@verb@fcolorbox #1#2#3{% + % The \spx@verb@boxes@fcolorbox@setup MUST have been executed beforehand. +% + % MEMO: in the context of framed.sty this will always expand inside some + % \hbox isolated from other code, so we can use \box\z@, \box\tw@,... + % with no need of extra group. +% + % MEMO: this code was originally using \color@b@x but the latter has + % problematic features regarding color in a context like here where #3 + % may contain an unbalanced "color push". +% + \setbox\z@\hbox{#3}% + \edef\spx@verb@fcolorbox@width@sp + {\number\dimexpr\wd\z@+\spx@boxes@border@left + +\spx@boxes@padding@left + +\spx@boxes@padding@right + +\spx@boxes@border@right\relax sp}% + \vbox{#1% continuation hint attached above frame, uses \spx@verb@fcolorbox@width@sp + % the boxes@fcolorbox constructs an \hbox with bbox containing the border + % \spx@verb@boxes@fcolorbox@setup MUST have been executed beforehand. + \spx@boxes@fcolorbox{\box\z@}% + % This \nointerlineskip to maintain legacy spacing when a \hrule was + % formerly last prior item in vertical list. TODO: remove this at 6.0.0 ? + \nointerlineskip + #2% continuation hint attached below frame, uses \spx@verb@fcolorbox@width@sp + }% end of \vbox +}% +\def\spx@verb@fcolorbox@put@c#1{% hide width from framed.sty measuring + \moveright.5\dimexpr\spx@verb@fcolorbox@width@sp\hb@xt@\z@{\hss#1\hss}% +}% +\def\spx@verb@fcolorbox@put@r#1{% right align with contents, width hidden + \moveright\dimexpr\spx@verb@fcolorbox@width@sp-% + \spx@boxes@padding@right-% + \spx@boxes@border@right\hb@xt@\z@{\hss#1}% +}% +\def\spx@verb@fcolorbox@put@l#1{% left align with contents, width hidden + \moveright\dimexpr\spx@boxes@border@left+% + \spx@boxes@padding@left\hb@xt@\z@{#1\hss}% +}% +% +\def\sphinxVerbatim@Continued{% + \csname spx@verb@fcolorbox@put@\spx@opt@verbatimcontinuedalign\endcsname + {{\normalcolor\sphinxstylecodecontinued\literalblockcontinuedname}}% +}% +\def\sphinxVerbatim@Continues{% + \csname spx@verb@fcolorbox@put@\spx@opt@verbatimcontinuesalign\endcsname + {{\normalcolor\sphinxstylecodecontinues\literalblockcontinuesname}}% +}% +\def\sphinxVerbatim@Title{% + \spx@verb@fcolorbox@put@c{\unhcopy\sphinxVerbatim@TitleBox}% +}% +\let\sphinxVerbatim@Before\@empty +\let\sphinxVerbatim@After\@empty +% Defaults are redefined in document preamble according to language +\newcommand*\literalblockcontinuedname{continued from previous page}% +\newcommand*\literalblockcontinuesname{continues on next page}% +% +\def\sphinxVerbatim@FrameCommand{% + \spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@After +}% +\def\sphinxVerbatim@FirstFrameCommand{% + \ifspx@pre@border@open + \spx@boxes@fcolorbox@setup@openbottom + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Before\sphinxVerbatim@Continues +}% +\def\sphinxVerbatim@MidFrameCommand{% + \ifspx@pre@border@open + \spx@boxes@fcolorbox@setup@openboth + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@Continues +}% +\def\sphinxVerbatim@LastFrameCommand{% + \ifspx@pre@border@open + \spx@boxes@fcolorbox@setup@opentop + \fi + \spx@verb@FrameCommand\sphinxVerbatim@Continued\sphinxVerbatim@After +}% +% +\def\spx@verb@boxes@fcolorbox@setup{% + % Prepares usage of \spx@boxes@fcolorbox + % Extras to remap legacy color names VerbatimBorderColor and VerbatimColor + % to a common naming scheme with admonitions (and topic directive), as + % expected by \spx@boxes@fcolorbox@setup from sphinxpackageboxes.sty. + \sphinxcolorlet{sphinxpreBorderColor}{VerbatimBorderColor}% + \sphinxcolorlet{sphinxpreBgColor}{VerbatimColor}% + % This VerbatimShadowColor is not a legacy name nor user documented but is + % an outcome of sphinx.sty batch definitions for CSS option support. + \sphinxcolorlet{sphinxpreShadowColor}{VerbatimShadowColor}% + \spx@boxes@fcolorbox@setup{pre}% + \ifspx@opt@verbatimwithframe + \else + \spx@boxes@border@top\z@ + \spx@boxes@border@right\z@ + \spx@boxes@border@bottom\z@ + \spx@boxes@border@left\z@ + % MEMO: rounded corners still make sense in presence of a background + % color, so we do not force the fcolorbox@rectangle here + \fi +}% + +% For linebreaks inside Verbatim environment from package fancyvrb. +\newbox\sphinxcontinuationbox +\newbox\sphinxvisiblespacebox +\newcommand*\sphinxafterbreak {\copy\sphinxcontinuationbox} + +% Take advantage of the already applied Pygments mark-up to insert +% potential linebreaks for TeX processing. +% {, <, #, %, $, ' and ": go to next line. +% _, }, ^, &, >, -, ~, and \: stay at end of broken line. +% Use of \textquotesingle for straight quote. +% FIXME: convert this to package options ? +\newcommand*\sphinxbreaksbeforelist {% + \do\PYGZob\{\do\PYGZlt\<\do\PYGZsh\#\do\PYGZpc\%% {, <, #, %, + \do\PYGZdl\$\do\PYGZdq\"% $, " + \def\PYGZsq + {\discretionary{}{\sphinxafterbreak\textquotesingle}{\textquotesingle}}% ' +} +\newcommand*\sphinxbreaksafterlist {% + \do\PYGZus\_\do\PYGZcb\}\do\PYGZca\^\do\PYGZam\&% _, }, ^, &, + \do\PYGZgt\>\do\PYGZhy\-\do\PYGZti\~% >, -, ~ + \do\PYGZbs\\% \ +} +\newcommand*\sphinxbreaksatspecials {% + \def\do##1##2% + {\def##1{\discretionary{}{\sphinxafterbreak\char`##2}{\char`##2}}}% + \sphinxbreaksbeforelist + \def\do##1##2% + {\def##1{\discretionary{\char`##2}{\sphinxafterbreak}{\char`##2}}}% + \sphinxbreaksafterlist +} + +\def\sphinx@verbatim@nolig@list {\do \`}% +% Some characters . , ; ? ! / are neither pygmentized nor "tex-escaped". +% This macro makes them "active" and they will insert potential linebreaks. +% Not compatible with math mode (cf \sphinxunactivateextras, which uses +% these lists to make sure activated characters get de-activated). +\newcommand*\sphinxbreaksbeforeactivelist {}% none +\newcommand*\sphinxbreaksafteractivelist {\do\.\do\,\do\;\do\?\do\!\do\/} +\newcommand*\sphinxbreaksviaactive {% + \def\do##1{\lccode`\~`##1% + \lowercase{\def~}{\discretionary{}{\sphinxafterbreak\char`##1}{\char`##1}}% + \catcode`##1\active}% + \sphinxbreaksbeforeactivelist + \def\do##1{\lccode`\~`##1% + \lowercase{\def~}{\discretionary{\char`##1}{\sphinxafterbreak}{\char`##1}}% + \catcode`##1\active}% + \sphinxbreaksafteractivelist + \lccode`\~`\~ +} + +% If the linebreak is at a space, the latter will be displayed as visible +% space at end of first line, and a continuation symbol starts next line. +\def\spx@verbatim@space {% + \nobreak\hskip\z@skip + \discretionary{\copy\sphinxvisiblespacebox}{\sphinxafterbreak} + {\kern\fontdimen2\font}% +}% + +% if the available space on page is less than \literalblockneedspace, insert pagebreak +\newcommand{\sphinxliteralblockneedspace}{5\baselineskip} +\newcommand{\sphinxliteralblockwithoutcaptionneedspace}{1.5\baselineskip} +% The title (caption) is specified from outside as macro \sphinxVerbatimTitle. +% \sphinxVerbatimTitle is reset to empty after each use of Verbatim. +\newcommand*\sphinxVerbatimTitle {} +% This box to typeset the caption before framed.sty multiple passes for framing. +\newbox\sphinxVerbatim@TitleBox +% This box to measure contents if nested as inner \MakeFramed requires then +% minipage encapsulation but too long contents then break outer \MakeFramed +\newbox\sphinxVerbatim@ContentsBox +% Holder macro for labels of literal blocks. Set-up by LaTeX writer. +\newcommand*\sphinxLiteralBlockLabel {} +\newcommand*\sphinxSetupCaptionForVerbatim [1] +{% + \sphinxvspacefixafterfrenchlists + \needspace{\sphinxliteralblockneedspace}% +% insert a \label via \sphinxLiteralBlockLabel +% reset to normal the color for the literal block caption + \def\sphinxVerbatimTitle + {\py@NormalColor\sphinxcaption{\sphinxLiteralBlockLabel #1}}% +} +\newcommand*\sphinxSetupCodeBlockInFootnote {% + \fvset{fontsize=\footnotesize}\let\caption\sphinxfigcaption + \sphinxverbatimwithminipagetrue % reduces vertical spaces + % we counteract (this is in a group) the \@normalsize from \caption + \let\normalsize\footnotesize\let\@parboxrestore\relax + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% +} +\newcommand*{\sphinxverbatimsmallskipamount}{\smallskipamount} +% serves to implement line highlighting +\newcommand\sphinxFancyVerbFormatLine[1]{% + \expandafter\sphinx@verbatim@checkifhl\expandafter{\the\FV@CodeLineNo}% + \ifin@ + \sphinxVerbatimHighlightLine{#1}% + \else + \sphinxVerbatimFormatLine{#1}% + \fi +}% +\let\spx@original@set@color\set@color +\newcommand\sphinxVerbatimHighlightLine[1]{% +% This is morally a \colorbox (with a \fboxsep which would be 0pt) +% but some issues of potential colour disappearance at pagebreaks +% require workaround such as the one done here. + \leavevmode + % MEMO: usage of original \colorbox would insert a \set@color here + % and this then places a "color pop" at the end of the \box\z@. + % But this could pair erroneously with an unmatched "color push" + % as #1 is maybe only a part (already hboxed) of a codeline + % if (default) verbatimwrapslines=true + % (cf \spx@verb@@PreProcessLine; refs: #8686) + % MEMO: formerly we did something with \fboxsep in relation to the LaTeX + % bug graphics/4524 for \colorbox, but as we don't use \colorbox... + \setbox\z@\hb@xt@\linewidth{\strut#1\hss}% + % MEMO: \colorbox would lead to \color{sphinxVerbatimHighlightColor} + % plus \color@block, which results in doubled (a color.sty feature) + % color command send to device driver and more importantly has + % a "color pop" which will be after \box\z@. We avoid that for reasons + % mentioned above. + {% + \def\set@color{\let\set@color\spx@original@set@color}% + % will only set \current@color and delay the \set@color to \color@block + % as this all happens inside fancyvrb nested \hbox'es. + \color{sphinxVerbatimHighlightColor}% + % will use \current@color and pop it **before** \box\z@ + \color@block{\wd\z@}{\ht\z@}{\dp\z@}\box\z@ + }% + % we added a group only for \FV@RightListNumber not be influenced by the + % \current@color, if \fvset has been used to set numbers to the right. +}% +% MEMO: fancyvrb has options obeytabs and tabsize. Anyhow tab characters +% do not make it to the tex file, they have been converted to spaces earlier. +% But, if this was not the case, the support would be implemented here via +% \newcommand\sphinxVerbatimFormatLine[1]{\FV@ObeyTabs{\strut #1}}% +\newcommand\sphinxVerbatimFormatLine[1]{\strut#1}% +% MEMO: if verbatimwrapslines is set to true (default) the #1 above is +% simply \box\spx@tempboxb, from the next two macros. +% The next two macros are a deep hack of fancyvrb.sty core line processing in +% order to wrap too long lines, either at spaces and natural break-points, +% (soft wrap) or optionally at any character (hard wrap). This requires deep +% hack to work around the \hbox'es wrappers of fancyvrb.sty as they would +% prevent page breaks. Formerly Sphinx obtained wrapping by inserting the +% material into a vertical box (which was later again boxed -- twice -- by +% fancyvrb thinking it was a single line...) but this was incompatible with +% allowing page breaks (refs: #8686). +% We use core TeX techniques to pre-process a paragraph then recover its +% constituents lines (as boxes, not as tokens) and hand them over to original +% fancyvrb line process. It is mandatory to update \FV@ProcessLine and +% \@tempboxa globally to get fancyvrb internals into working to our +% satisfaction. +% This will get disrupted if anything adding vertical penalties or glues +% is activated via some \vadjust from inside the Pygmentized code lines. +\def\spx@verb@@ProcessLines{% + \unskip + \unpenalty + \setbox\spx@tempboxb\lastbox +\ifvoid\spx@tempboxb\else + {\spx@verb@@ProcessLines}% + \FV@ProcessLine{\box\spx@tempboxb}% + \global\let\FV@ProcessLine\FV@ProcessLine + \global\setbox\@tempboxa=\box\@tempboxa + \aftergroup\spx@verb@@InhibitLineNumber +\fi +}% +\def\spx@verb@@InhibitLineNumber{% + \let\FV@LeftListNumber\relax + \let\FV@RightListNumber\relax +}% +% This will replace fancyvrb's \FV@@PreProcessLine +% Instead of boxing \FV@Line (which contains the Pygmentized line tokens), we +% first typeset it in a vertical box of the suitable width (taking into +% account nested lists) to activate the TeX built-in paragraph builder, then +% we recover individual lines as horizontal boxes and feed them to fancyvrb +% native line processing (which may add line numbers). The interline +% penalties and vertical glue to maintain baseline distance will be added +% again by this process so in recursive \spx@verb@@ProcessLines which starts +% from bottom and makes its way up to first part of the wrapped line we do not +% need to worry about them. An additional initial measuring step is needed if +% user issued verbatimforcewraps=true, which elaborates on the same technique. +% If hard wraps get activated, they get implemented via hacked \PYG macros. +\def\spx@verb@@PreProcessLine{% + \FV@StepLineNo + \FV@Gobble + \def\spx@verb@FV@Line{\FV@Line}% + \ifspx@opt@verbatimforcewraps + \spx@verb@DecideIfWillDoForceWrap + \fi +% MEMO: \everypar{} was issued earlier (and due to \@setminipage +% would have been only \@minipagefalse\everypar{} otherwise). + \setbox\spx@tempboxa=\vtop{\hsize\linewidth + \raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ +% MEMO: fancyvrb has options obeytabs and tabsize. Anyhow tab characters +% do not make it to the tex file, they have been converted to spaces earlier. +% But, if this was not the case, the support would be implemented here via +% \FV@ObeyTabs{\strut\spx@verb@FV@Line\strut}% +% And one would need a similar change in the measuring phase done by +% \spx@verb@DecideIfWillDoForceWrap + \strut\spx@verb@FV@Line\strut +% MEMO: since LaTeX 2021-06-01, there might be some hooks executed at +% start and end of paragraphs (in future: PDF tagging), but we need an +% explicit \par here for that. Else the kernel hooks at start of paragraph +% are executed but not the ones at its end. + \par + }% + \setbox\spx@tempboxa=\vtop{\unvbox\spx@tempboxa + \setbox\spx@tempboxb\lastbox + {\spx@verb@@ProcessLines}% + \FV@ProcessLine{\box\spx@tempboxb}% + \global\let\FV@ProcessLine\FV@ProcessLine + \global\setbox\@tempboxa=\box\@tempboxa + }% + \unvbox\spx@tempboxa +}% +% +% The normal line wrapping allows breaks at spaces and ascii non +% letters, non digits. The \raggedright above means there will be +% an overfilled line only if some non-breakable "word" was +% encountered, which is longer than a line (it is moved always to +% be on its own on a new line). +% +% The "forced" line wrapping will parse the tokens to add potential +% breakpoints at each character. As some strings are highlighted, +% we have to apply the highlighting character per character, which +% requires to manipulate the output of the Pygments LaTeXFormatter. +% +% Doing this at latex level is complicated. The contents should +% be as expected: i.e. some active characters from +% \sphinxbreaksviaactive, some Pygments character escapes such as +% \PYGZdl{}, and the highlighting \PYG macro with always 2 +% arguments. No other macros should be there, except perhaps +% zero-parameter macros. In particular: +% - the texcomments Pygments option must be set to False +% +% With pdflatex, Unicode input gives multi-bytes characters +% where the first byte is active. We support the "utf8" macros +% only. "utf8x" is not supported. +% +% The highlighting macro \PYG will be applied character per +% character. Highlighting via a colored background gives thus a +% chain of small colored boxes which may cause some artefact in +% some pdf viewers. Can't do anything here if we do want the line +% break to be possible. +% +% First a measurement step is done of what would the standard line +% wrapping give (i.e line breaks only at spaces and non-letter, +% non-digit ascii characters), cf TeX by Topic for the basic +% dissecting technique: TeX unfortunately when building a vertical +% box does not store in an accessible way what was the maximal +% line-width during paragraph building. +% +% MEMO: in future use perhaps rather \RawNoindent/\RawParEnd, but +% ltpara (LaTeX 2021-06-01) is not yet in final form (June 2022). +% +% Avoid LaTeX 2021 alteration of \@@par which potentially could break our +% measurement step (typically if the para/after hook is configured to use +% \vspace). Of course, breakage could happen only from user or package +% adding things to basic Sphinx latex. And perhaps spring LaTeX 2021 will +% provide a non-hooked \@@par, but this should work anyway and can't be +% beaten for speed. +\ltx@ifundefined{tex_par:D} +% We could use \@ifl@t@r\fmtversion{2020/02/02}{use \tex_par:D}{use \@@par}. + {\let\spx@par\@@par}% \@@par is then expected to be TeX's original \par + {\expandafter\let\expandafter\spx@par\csname tex_par:D\endcsname} +% More hesitation for avoiding the at-start-of-par hooks for our +% measurement : 1. with old LaTeX, we can not avoid hooks from everyhook +% or similar packages, 2. and perhaps the hooks add stuff which we should +% actually measure. Ideally, hooks are for inserting things in margin +% which do not change spacing. Most everything else in fact should not be +% executed in our scratch box for measurement, such as counter stepping. +\ltx@ifundefined{tex_everypar:D} + {\let\spx@everypar\everypar} + {\expandafter\let\expandafter\spx@everypar\csname tex_everypar:D\endcsname} +% +% If the max width exceeds the linewidth by more than verbatimmaxoverfull +% character widths, or if the min width plus verbatimmaxunderfull character +% widths is inferior to linewidth, then we apply the "force wrapping" with +% potential line break at each character, else we don't. +\long\def\spx@verb@DecideIfWillDoForceWrap{% + \global\let\spx@verb@maxwidth\z@ + \global\let\spx@verb@minwidth\linewidth + \setbox\spx@tempboxa + \vtop{\raggedright\hyphenpenalty\z@\exhyphenpenalty\z@ + \doublehyphendemerits\z@\finalhyphendemerits\z@ +% Avoid TeX reporting Overfull \hbox'es during this measuring phase. Setting +% \hbadness to \@M to avoid Underfull reports is unneeded due to \raggedright. + \hfuzz\maxdimen + \spx@everypar{}\noindent\strut\FV@Line\strut\spx@par + \spx@verb@getwidths}% + \ifdim\spx@verb@maxwidth> + \dimexpr\linewidth+\spx@opt@verbatimmaxoverfull\fontcharwd\font`X \relax +% The \expandafter is due to \spx@verb@wrapPYG requiring to "see" the TeX tokens +% from the pygmentize output. + \def\spx@verb@FV@Line{\expandafter\spx@verb@wrapPYG\FV@Line\spx@verb@wrapPYG}% + \else + \ifdim\spx@verb@minwidth< + \dimexpr\linewidth-\spx@opt@verbatimmaxunderfull\fontcharwd\font`X \relax + \def\spx@verb@FV@Line{\expandafter\spx@verb@wrapPYG\FV@Line\spx@verb@wrapPYG}% + \fi + \fi +}% +% auxiliary paragraph dissector to get max and min widths +% but minwidth must not take into account the last line +\def\spx@verb@getwidths {% + \unskip\unpenalty + \setbox\spx@tempboxb\lastbox + \ifvoid\spx@tempboxb + \else + \setbox\spx@tempboxb\hbox{\unhbox\spx@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@tempboxb sp}% + \fi + \expandafter\spx@verb@getwidths@loop + \fi +}% +\def\spx@verb@getwidths@loop {% + \unskip\unpenalty + \setbox\spx@tempboxb\lastbox + \ifvoid\spx@tempboxb + \else + \setbox\spx@tempboxb\hbox{\unhbox\spx@tempboxb}% + \ifdim\spx@verb@maxwidth<\wd\spx@tempboxb + \xdef\spx@verb@maxwidth{\number\wd\spx@tempboxb sp}% + \fi + \ifdim\spx@verb@minwidth>\wd\spx@tempboxb + \xdef\spx@verb@minwidth{\number\wd\spx@tempboxb sp}% + \fi + \expandafter\spx@verb@getwidths@loop + \fi +}% +% auxiliary macros to implement "cut long line even in middle of word" +\catcode`Z=3 % safe delimiter +\def\spx@verb@wrapPYG{% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@i +}% +\def\spx@verb@wrapPYG@i{% + \ifx\spx@nexttoken\spx@verb@wrapPYG\let\next=\@gobble\else + \ifx\spx@nexttoken\PYG\let\next=\spx@verb@wrapPYG@PYG@onebyone\else + \discretionary{}{\sphinxafterbreak}{}% + \let\next\spx@verb@wrapPYG@ii + \fi\fi + \next +}% +% Let's recognize active characters. We don't support utf8x only utf8. +% And here #1 should not have picked up (non empty) braced contents +\long\def\spx@verb@wrapPYG@ii#1{% + \ifcat\noexpand~\noexpand#1\relax% active character + \expandafter\spx@verb@wrapPYG@active + \else % non-active character, control sequence such as \PYGZdl, or empty + \expandafter\spx@verb@wrapPYG@one + \fi {#1}% +}% +\long\def\spx@verb@wrapPYG@active#1{% +% Let's hope expansion of active character does not really require arguments, +% as we certainly don't want to go into expanding upfront token stream anyway. + \expandafter\spx@verb@wrapPYG@iii#1{}{}{}{}{}{}{}{}{}Z#1% +}% +\long\def\spx@verb@wrapPYG@iii#1#2Z{% + \ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@four\else + \ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@three\else + \ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@two\else + \let\next=\spx@verb@wrapPYG@one + \fi\fi\fi + \next +}% +\long\def\spx@verb@wrapPYG@one #1{#1\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@two #1#2{#1#2\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@three #1#2#3{#1#2#3\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@four #1#2#3#4{#1#2#3#4\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +% Replace \PYG by itself applied one character at a time! This way breakpoints +% can be inserted. +\def\spx@verb@wrapPYG@PYG@onebyone#1#2#3{% #1 = \PYG, #2 = highlight spec, #3 = tokens + \def\spx@verb@wrapPYG@PYG@spec{{#2}}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i#3Z% +}% +\def\spx@verb@wrapPYG@PYG@i{% + \ifx\spx@nexttokenZ\let\next=\spx@verb@wrapPYG@PYG@done\else + \discretionary{}{\sphinxafterbreak}{}% + \let\next\spx@verb@wrapPYG@PYG@ii + \fi + \next +}% +\def\spx@verb@wrapPYG@PYG@doneZ{\futurelet\spx@nexttoken\spx@verb@wrapPYG@i}% +\long\def\spx@verb@wrapPYG@PYG@ii#1{% + \ifcat\noexpand~\noexpand#1\relax% active character + \expandafter\spx@verb@wrapPYG@PYG@active + \else % non-active character, control sequence such as \PYGZdl, or empty + \expandafter\spx@verb@wrapPYG@PYG@one + \fi {#1}% +}% +\long\def\spx@verb@wrapPYG@PYG@active#1{% +% Let's hope expansion of active character does not really require arguments, +% as we certainly don't want to go into expanding upfront token stream anyway. + \expandafter\spx@verb@wrapPYG@PYG@iii#1{}{}{}{}{}{}{}{}{}Z#1% +}% +\long\def\spx@verb@wrapPYG@PYG@iii#1#2Z{% + \ifx\UTFviii@four@octets#1\let\next=\spx@verb@wrapPYG@PYG@four\else + \ifx\UTFviii@three@octets#1\let\next=\spx@verb@wrapPYG@PYG@three\else + \ifx\UTFviii@two@octets#1\let\next=\spx@verb@wrapPYG@PYG@two\else + \let\next=\spx@verb@wrapPYG@PYG@one + \fi\fi\fi + \next +}% +\long\def\spx@verb@wrapPYG@PYG@one#1{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@two#1#2{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@three#1#2#3{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\long\def\spx@verb@wrapPYG@PYG@four#1#2#3#4{% + \expandafter\PYG\spx@verb@wrapPYG@PYG@spec{#1#2#3#4}% + \futurelet\spx@nexttoken\spx@verb@wrapPYG@PYG@i +}% +\catcode`Z 11 % +% +\g@addto@macro\FV@SetupFont{% + \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% + \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% +}% +\newenvironment{sphinxVerbatim}{% + % first, let's check if there is a caption + \ifx\sphinxVerbatimTitle\empty + \sphinxvspacefixafterfrenchlists + \parskip\z@skip + \vskip\sphinxverbatimsmallskipamount + % there was no caption. Check if nevertheless a label was set. + \ifx\sphinxLiteralBlockLabel\empty\else + % we require some space to be sure hyperlink target from \phantomsection + % will not be separated from upcoming verbatim by a page break + \needspace{\sphinxliteralblockwithoutcaptionneedspace}% + \phantomsection\sphinxLiteralBlockLabel + \fi + \else + \parskip\z@skip + \if t\spx@opt@literalblockcappos + \vskip\spx@abovecaptionskip + \def\sphinxVerbatim@Before + {\sphinxVerbatim@Title\nointerlineskip + \kern\dimexpr-\dp\strutbox+\sphinxbelowcaptionspace + % MEMO: prior to 7.4.0 a test was done for presence or + % not of a frame and if not top padding was removed if + % no background color. A background color is now always + % assumed, so this got removed. + % caption package adds \abovecaptionskip vspace, remove it + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax}% + \else + \vskip\sphinxverbatimsmallskipamount + \def\sphinxVerbatim@After + {\nointerlineskip\kern\dimexpr\dp\strutbox + % MEMO: 7.4.0 removes here too an optional removal of bottom padding + \spx@ifcaptionpackage{-\abovecaptionskip}{}\relax + \sphinxVerbatim@Title}% + \fi + \def\@captype{literalblock}% + \capstart + % \sphinxVerbatimTitle must reset color + \setbox\sphinxVerbatim@TitleBox + \hbox{\begin{minipage}{\linewidth}% + % caption package may detect wrongly if top or bottom, so we help it + \spx@ifcaptionpackage + {\caption@setposition{\spx@opt@literalblockcappos}}{}% + \sphinxVerbatimTitle + \end{minipage}}% + \fi + \global\let\sphinxLiteralBlockLabel\empty + \global\let\sphinxVerbatimTitle\empty + % the "FrameCommand"'s are also responsible to attach the "Title". + \let\FrameCommand \sphinxVerbatim@FrameCommand + % those will also check status of the pre_box-decoration-break option + \let\FirstFrameCommand\sphinxVerbatim@FirstFrameCommand + \let\MidFrameCommand \sphinxVerbatim@MidFrameCommand + \let\LastFrameCommand \sphinxVerbatim@LastFrameCommand + % + \ifspx@opt@verbatimhintsturnover\else + \let\sphinxVerbatim@Continued\@empty + \let\sphinxVerbatim@Continues\@empty + \fi + % initialization for \spx@boxes@fcolorbox from sphinxpackageboxes.sty + % it will take into account status of verbatimwithframe Boolean + \spx@verb@boxes@fcolorbox@setup + \ifspx@opt@verbatimwrapslines + % deep hack into fancyvrb's internal processing of input lines + \let\FV@@PreProcessLine\spx@verb@@PreProcessLine + % space character will allow line breaks + \let\FV@Space\spx@verbatim@space + % allow breaks at special characters using \PYG... macros. + \sphinxbreaksatspecials + % breaks at punctuation characters . , ; ? ! and / (needs catcode activation) + \fvset{codes*=\sphinxbreaksviaactive}% + \fi + \let\FancyVerbFormatLine\sphinxFancyVerbFormatLine + \VerbatimEnvironment + % workaround to fancyvrb's check of current list depth + \def\@toodeep {\advance\@listdepth\@ne}% + % The list environment is needed to control perfectly the vertical space. + % Note: \OuterFrameSep used by framed.sty is later set to \topsep hence 0pt. + % - if caption: distance from last text baseline to caption baseline is + % A+(B-F)+\ht\strutbox, A = \abovecaptionskip (default 10pt), B = + % \baselineskip, F is the framed.sty \FrameHeightAdjust macro, default 6pt. + % Formula valid for F < 10pt. + % - distance of baseline of caption to top of frame is like for tables: + % \sphinxbelowcaptionspace (=0.5\baselineskip) + % - if no caption: distance of last text baseline to code frame is S+(B-F), + % with S = \sphinxverbatimtopskip (=\smallskip) + % - and distance from bottom of frame to next text baseline is + % \baselineskip+\parskip. + % The \trivlist is used to avoid possible "too deeply nested" error. + \itemsep \z@skip + \topsep \z@skip + \partopsep \z@skip + % trivlist will set \parsep to \parskip (which itself is set to zero above) + % \leftmargin will be set to zero by trivlist + \rightmargin\z@ + \parindent \z@% becomes \itemindent. Default zero, but perhaps overwritten. + \trivlist\item\relax + \ifspx@inframed\setbox\sphinxVerbatim@ContentsBox\vbox\bgroup + \@setminipage\hsize\linewidth + % use bulk of minipage paragraph shape restores (this is needed + % in indented contexts, at least for some) + \textwidth\hsize \columnwidth\hsize \@totalleftmargin\z@ + \leftskip\z@skip \rightskip\z@skip \@rightskip\z@skip + \else + \ifsphinxverbatimwithminipage\noindent\begin{minipage}{\linewidth}\fi + \MakeFramed {% adapted over from framed.sty's snugshade environment + \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage + }% + \fi + % For grid placement from \strut's in \FancyVerbFormatLine + \lineskip\z@skip + % active comma should not be overwritten by \@noligs + \ifspx@opt@verbatimwrapslines + \let\verbatim@nolig@list \sphinx@verbatim@nolig@list + \fi + % optimization: as codelines will be handled inside boxes, \everypar is + % never reset, and it issues \@minipagefalse repeatedly (from \@setminipage). + % As fancyvrb Verbatim will do \@minipagefalse itself, let's simplify things. + \everypar{}% + \color@begingroup % protect against color leaks (upstream framed.sty bug) + \ifspx@pre@withtextcolor\color{VerbatimTextColor}\fi % mostly shadowed by + % Pygments highlighting anyhow + \spx@pre@TeXextras + % will fetch its optional arguments if any + \OriginalVerbatim +}% +{% + \endOriginalVerbatim + \color@endgroup % matches the \color@begingroup + \ifspx@inframed + \egroup % finish \sphinxVerbatim@ContentsBox vbox + \nobreak % update page totals +%%%% +% MEMO (2022/07/09, while preparing 5.1.0 LaTeX CSS-style sphinxsetup options) +% This test will systematically cause to abandon framing if the code-block +% is near bottom of a warning-type notice which TeX has not yet decided whether +% it fits on current page and which is near bottom of page. Indeed the +% \pagetotal will already be very near \pagegoal. This is probably a not +% intended behaviour, and perhaps the whole thing should be removed? Indeed +% the result is surprising then because the notice will be split, code-block +% will be on page 2 and will have no background-color, no border. + \ifdim\dimexpr + \ht\sphinxVerbatim@ContentsBox+ + \dp\sphinxVerbatim@ContentsBox+ + \ht\sphinxVerbatim@TitleBox+ + \dp\sphinxVerbatim@TitleBox+ + % 6.2.0 uses here the dimen registers from sphinxpackageboxes.sty, + % they got setup by \spx@verb@boxes@fcolorbox@setup + \spx@boxes@padding@top+ + \spx@boxes@padding@bottom+ + \ifspx@opt@verbatimwithframe \spx@boxes@border@top+ + \spx@boxes@border@bottom+\fi + % try to account for external frame parameters + % MEMO: this is because the sphinxheavybox (for warning admonitions) + % environment sets \FrameSep and \FrameRule + % TODO: fix this bad implicit dependency + \FrameSep+\FrameRule+ + % Usage here of 2 baseline distances is empirical. + % In border case where code-block fits barely in remaining space, + % it gets framed and looks good but the outer frame may continue + % on top of next page and give (if no contents after code-block) + % an empty framed line, as testing showed. + 2\baselineskip+ + % now add all to accumulated page totals and compare to \pagegoal + \pagetotal+\pagedepth>\pagegoal + % long contents: do not \MakeFramed. Do make a caption (either before or + % after) if title exists. Continuation hints across pagebreaks dropped. + % FIXME? a bottom caption may end up isolated at top of next page + % (no problem with a top caption, which is default) + \spx@opt@verbatimwithframefalse + \def\sphinxVerbatim@Title{\noindent\box\sphinxVerbatim@TitleBox\par}% + \sphinxVerbatim@Before + \noindent\unvbox\sphinxVerbatim@ContentsBox\par + \sphinxVerbatim@After + \else + % short enough contents: use \MakeFramed. As it is nested, this requires + % minipage encapsulation. + \noindent\begin{minipage}{\linewidth}% + \MakeFramed {% Use it now with the fetched contents + \advance\hsize-\width\@totalleftmargin\z@\linewidth\hsize\@setminipage + }% + \unvbox\sphinxVerbatim@ContentsBox + % the \@minipagefalse is superfluous, actually. + \par\unskip\@minipagefalse\endMakeFramed + \end{minipage}% + \fi + \else % non-nested \MakeFramed + \par\unskip\@minipagefalse\endMakeFramed % from framed.sty snugshade + \ifsphinxverbatimwithminipage\end{minipage}\fi + \fi + \endtrivlist +} +\newenvironment {sphinxVerbatimNoFrame} + {\spx@opt@verbatimwithframefalse + \VerbatimEnvironment + \begin{sphinxVerbatim}} + {\end{sphinxVerbatim}} +\newenvironment {sphinxVerbatimintable} + {% don't use a frame if in a table cell + \spx@opt@verbatimwithframefalse + \sphinxverbatimwithminipagetrue + % the literal block caption uses \sphinxcaption which is wrapper of \caption, + % but \caption must be modified because longtable redefines it to work only + % for the own table caption, and tabulary has multiple passes + \let\caption\sphinxfigcaption + % reduce above caption skip + \def\spx@abovecaptionskip{\sphinxverbatimsmallskipamount}% + \VerbatimEnvironment + \begin{sphinxVerbatim}} + {\end{sphinxVerbatim}} + + +%% PARSED LITERALS +% allow long lines to wrap like they do in code-blocks + +% this should be kept in sync with definitions in sphinx.util.texescape +\newcommand*\sphinxbreaksattexescapedchars{% + \def\do##1##2% put potential break point before character + {\def##1{\discretionary{}{\sphinxafterbreak\char`##2}{\char`##2}}}% + \do\{\{\do\textless\<\do\#\#\do\%\%\do\$\$% {, <, #, %, $ + \def\do##1##2% put potential break point after character + {\def##1{\discretionary{\char`##2}{\sphinxafterbreak}{\char`##2}}}% + \do\_\_\do\}\}\do\textasciicircum\^\do\&\&% _, }, ^, &, + \do\textgreater\>\do\textasciitilde\~% >, ~ + \do\textbackslash\\% \ +} +\newcommand*\sphinxbreaksviaactiveinparsedliteral{% + \sphinxbreaksviaactive % by default handles . , ; ? ! / + \lccode`\~`\~ % + % update \dospecials as it is used by \url + % but deactivation will already have been done hence this is unneeded: + % \expandafter\def\expandafter\dospecials\expandafter{\dospecials + % \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist\do\-}% +} +\newcommand*\sphinxbreaksatspaceinparsedliteral{% + \lccode`~32 \lowercase{\let~}\spx@verbatim@space\lccode`\~`\~ +} +\newcommand*{\sphinxunactivateextras}{\let\do\@makeother + \sphinxbreaksbeforeactivelist\sphinxbreaksafteractivelist}% +% the \catcode13=5\relax (deactivate end of input lines) is left to callers +\newcommand*{\sphinxunactivateextrasandspace}{\catcode32=10\relax + \sphinxunactivateextras}% +% alltt uses a monospace font and linebreaks at dashes (which are escaped +% to \sphinxhyphen{} which expands to -\kern\z@) are inhibited with pdflatex. +% Not with xelatex (cf \defaultfontfeatures in latex writer), so: +\newcommand*{\sphinxhypheninparsedliteral}{\sphinxhyphennobreak} +% now for the modified alltt environment +\newenvironment{sphinxalltt} +{% at start of next line to workaround Emacs/AUCTeX issue with this file +\begin{alltt}% + \ifspx@opt@parsedliteralwraps + \sbox\sphinxcontinuationbox {\spx@opt@verbatimcontinued}% + \sbox\sphinxvisiblespacebox {\spx@opt@verbatimvisiblespace}% + \let\sphinxhyphen\sphinxhypheninparsedliteral + \sphinxbreaksattexescapedchars + \sphinxbreaksviaactiveinparsedliteral + \sphinxbreaksatspaceinparsedliteral +% alltt takes care of the ' as derivative ("prime") in math mode + \everymath\expandafter{\the\everymath\sphinxunactivateextrasandspace + \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% +% not sure if displayed math (align,...) can end up in parsed-literal, anyway + \everydisplay\expandafter{\the\everydisplay + \catcode13=5 \sphinxunactivateextrasandspace + \catcode`\<=12\catcode`\>=12\catcode`\^=7\catcode`\_=8 }% + \fi } +{\end{alltt}} + + +%% INLINE MARK-UP +% + +% Protect \href's first argument in contexts such as sphinxalltt (or +% \sphinxcode). Sphinx uses \#, \%, \& ... always inside \sphinxhref. +\protected\def\sphinxhref#1#2{{% + \sphinxunactivateextrasandspace % never do \scantokens with active space! +% for the \endlinechar business, https://github.com/latex3/latex2e/issues/286 + \endlinechar\m@ne\everyeof{{\endlinechar13 #2}}% keep catcode regime for #2 + \scantokens{\href{#1}}% normalise it for #1 during \href expansion +}} +% Same for \url. And also \nolinkurl for coherence. +\protected\def\sphinxurl#1{{% + \sphinxunactivateextrasandspace\everyeof{}% (<- precaution for \scantokens) + \endlinechar\m@ne\scantokens{\url{#1}}% +}} +\protected\def\sphinxnolinkurl#1{{% + \sphinxunactivateextrasandspace\everyeof{}% + \endlinechar\m@ne\scantokens{\nolinkurl{#1}}% +}} + +% \sphinxupquote +% to obtain straight quotes we execute \@noligs as patched by upquote, and +% \scantokens is needed in cases where it would be too late for the macro to +% first set catcodes and then fetch its argument. We also make the contents +% breakable at non-escaped . , ; ? ! / using \sphinxbreaksviaactive, +% and also at \ character (which is escaped to \textbackslash{}). +\protected\def\sphinxtextbackslashbreakbefore + {\discretionary{}{\sphinxafterbreak\sphinx@textbackslash}{\sphinx@textbackslash}} +\protected\def\sphinxtextbackslashbreakafter + {\discretionary{\sphinx@textbackslash}{\sphinxafterbreak}{\sphinx@textbackslash}} +\let\sphinxtextbackslash\sphinxtextbackslashbreakafter +% - is escaped to \sphinxhyphen{} and this default ensures no linebreak +% behaviour (also with a non monospace font, or with xelatex) +\newcommand*{\sphinxhyphenininlineliteral}{\sphinxhyphennobreak} +% the macro must be protected if it ends up used in moving arguments, +% in 'alltt' \@noligs is done already, and the \scantokens must be avoided. +\protected\def\sphinxupquote#1{{\def\@tempa{alltt}% + \ifx\@tempa\@currenvir\else + \let\sphinxhyphen\sphinxhyphenininlineliteral + \ifspx@opt@inlineliteralwraps + % break at . , ; ? ! / + \sphinxbreaksviaactive + % break also at \ + \setbox8=\hbox{\textbackslash}% + \def\sphinx@textbackslash{\copy8}% + \let\textbackslash\sphinxtextbackslash + % by default, no continuation symbol on next line but may be added + \let\sphinxafterbreak\sphinxafterbreakofinlineliteral + % do not overwrite the comma set-up + \let\verbatim@nolig@list\sphinx@literal@nolig@list + \fi + % fix a space-gobbling issue due to LaTeX's original \do@noligs +% TODO: using \@noligs as patched by upquote.sty is now unneeded because +% either ` and ' are escaped (non-unicode engines) or they don't build +% ligatures (unicode engines). Thus remove this and unify handling of `, <, >, +% ' and - with the characters . , ; ? ! / as handled via +% \sphinxbreaksviaactive. +% Hence \sphinx@do@noligs will be removed, or rather replaced with code +% inserting discretionaries, as they allow a continuation symbol on start of +% next line to achieve common design with code-blocks. +% TODO: do the above TODO! +% Extend \sphinxunactivateextras for \sphinxhref as the latter may +% actually be in the scope of \sphinxupquote and does a \scantokens +% of its own. + \expandafter\def\expandafter\sphinxunactivateextras\expandafter + {\sphinxunactivateextras\verbatim@nolig@list}% + \let\do@noligs\sphinx@do@noligs + \@noligs\endlinechar\m@ne\everyeof{}% (<- in case inside \sphinxhref) + \expandafter\scantokens + \fi {{#1}}}}% extra brace pair to fix end-space gobbling issue... +\def\sphinx@do@noligs #1{\catcode`#1\active\begingroup\lccode`\~`#1\relax + \lowercase{\endgroup\def~{\leavevmode\kern\z@\char`#1 }}} +\def\sphinx@literal@nolig@list {\do\`\do\<\do\>\do\'\do\-}% +\let\sphinxafterbreakofinlineliteral\empty + + +\endinput diff --git a/docs/build/latex/sphinxlatexnumfig.sty b/docs/build/latex/sphinxlatexnumfig.sty new file mode 100644 index 0000000000000000000000000000000000000000..22fcbb03900ce532814126201132bfa53e8a780d --- /dev/null +++ b/docs/build/latex/sphinxlatexnumfig.sty @@ -0,0 +1,135 @@ +%% NUMBERING OF FIGURES, TABLES, AND LITERAL BLOCKS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexnumfig}[2024/07/31 v8.1.0 numbering] + +% Requires: remreset (old LaTeX only) +% relates to numfig and numfig_secnum_depth configuration variables + +% LaTeX 2018-04-01 and later provides \@removefromreset +\ltx@ifundefined{@removefromreset} + {\RequirePackage{remreset}} + {}% avoid warning +% Everything is delayed to \begin{document} to allow hyperref patches into +% \newcounter to solve duplicate label problems for internal hyperlinks to +% code listings (literalblock counter). User or extension re-definitions of +% \theliteralblock, et al., thus have also to be delayed. (changed at 3.5.0) +\AtBeginDocument{% +\ltx@ifundefined{c@chapter} + {\newcounter{literalblock}}% + {\newcounter{literalblock}[chapter]% + \def\theliteralblock{\ifnum\c@chapter>\z@\arabic{chapter}.\fi + \arabic{literalblock}}% + }% +\ifspx@opt@nonumfigreset + \ltx@ifundefined{c@chapter}{}{% + \@removefromreset{figure}{chapter}% + \@removefromreset{table}{chapter}% + \@removefromreset{literalblock}{chapter}% + \ifspx@opt@mathnumfig + \@removefromreset{equation}{chapter}% + \fi + }% + \def\thefigure{\arabic{figure}}% + \def\thetable {\arabic{table}}% + \def\theliteralblock{\arabic{literalblock}}% + \ifspx@opt@mathnumfig + \def\theequation{\arabic{equation}}% + \fi +\else +% See apologetic comments on TeX wizardry at bottom of file. +% The reason for this one is to catch case where there will be only +% the number with no prefix from enclosing sectioning (can happen +% with latex_toplevel_sectioning='part'). +\def\spx@preAthefigure{\expandafter\spx@magicsep@s\romannumeral-`0} +\let\spx@preBthefigure\@empty +% \ifspx@opt@usespart % <-- LaTeX writer could pass such a 'usespart' boolean +% % as sphinx.sty package option +% If document uses \part, (triggered in Sphinx by latex_toplevel_sectioning) +% LaTeX core per default does not reset chapter or section +% counters at each part. +% But if we modify this, we need to redefine \thechapter, \thesection to +% include the part number and this will cause problems in table of contents +% because of too wide numbering. Simplest is to do nothing. +% \fi +\ifnum\spx@opt@numfigreset>0 + \ltx@ifundefined{c@chapter} + {} + {\g@addto@macro\spx@preAthefigure{\ifnum\c@chapter>\z@\arabic{chapter}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}}% +\fi +\ifnum\spx@opt@numfigreset>1 + \@addtoreset{figure}{section}% + \@addtoreset{table}{section}% + \@addtoreset{literalblock}{section}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{section}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@section>\z@\arabic{section}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>2 + \@addtoreset{figure}{subsection}% + \@addtoreset{table}{subsection}% + \@addtoreset{literalblock}{subsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsection}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsection>\z@\arabic{subsection}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>3 + \@addtoreset{figure}{subsubsection}% + \@addtoreset{table}{subsubsection}% + \@addtoreset{literalblock}{subsubsection}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subsubsection}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubsection>\z@\arabic{subsubsection}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>4 + \@addtoreset{figure}{paragraph}% + \@addtoreset{table}{paragraph}% + \@addtoreset{literalblock}{paragraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{paragraph}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subparagraph>\z@\arabic{subparagraph}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\ifnum\spx@opt@numfigreset>5 + \@addtoreset{figure}{subparagraph}% + \@addtoreset{table}{subparagraph}% + \@addtoreset{literalblock}{subparagraph}% + \ifspx@opt@mathnumfig + \@addtoreset{equation}{subparagraph}% + \fi% + \g@addto@macro\spx@preAthefigure{\ifnum\c@subsubparagraph>\z@\arabic{subsubparagraph}\spx@magicsep}% + \g@addto@macro\spx@preBthefigure{\fi}% +\fi +\expandafter\g@addto@macro +\expandafter\spx@preAthefigure\expandafter{\spx@preBthefigure}% +\let\thefigure\spx@preAthefigure +\let\thetable\spx@preAthefigure +\let\theliteralblock\spx@preAthefigure +\g@addto@macro\thefigure{\arabic{figure}}% +\g@addto@macro\thetable{\arabic{table}}% +\g@addto@macro\theliteralblock{\arabic{literalblock}}% + \ifspx@opt@mathnumfig + \let\theequation\spx@preAthefigure + \g@addto@macro\theequation{E}% + \fi +\fi +}% end of big \AtBeginDocument + +% Sorry for TeX wizardry here. We need to keep expandability. Explaining +% the mechanism is not really feasible to non TeX-experts, but the idea +% is to force next `\ifnum` conditional so we can check what comes next. +% All cases are accounted for (i.e. not an equation, or an equation at top +% level, or an equation in some section at some depth). +\def\spx@magicsep{\expandafter\spx@magicsep@i\romannumeral-`0} +\def\spx@magicsep@i#1{\if#1E\spx@opt@mathnumsep\arabic{equation}\else.#1\fi} +% +\def\spx@magicsep@s#1{\if#1E\arabic{equation}\else#1\fi} +\endinput diff --git a/docs/build/latex/sphinxlatexobjects.sty b/docs/build/latex/sphinxlatexobjects.sty new file mode 100644 index 0000000000000000000000000000000000000000..e960440cafb4148c130977159844ea28d191206d --- /dev/null +++ b/docs/build/latex/sphinxlatexobjects.sty @@ -0,0 +1,365 @@ +%% MODULE RELEASE DATA AND OBJECT DESCRIPTIONS +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexobjects}[2023/07/23 documentation environments] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - environments +% +% - fulllineitems +% - productionlist +% - optionlist +% - DUlineblock (also "lineblock") +% +% - macros +% +% - \DUrole +% - various legacy support macros related to author and release +% data of documented objects and modules. + +% \moduleauthor{name}{email} +\newcommand{\moduleauthor}[2]{} + +% \sectionauthor{name}{email} +\newcommand{\sectionauthor}[2]{} + +% Allow the release number to be specified independently of the +% \date{}. This allows the date to reflect the document's date and +% release to specify the release that is documented. +% +\newcommand{\py@release}{\releasename\space\version} +\newcommand{\version}{}% part of \py@release, used by title page and headers +% \releaseinfo is used on titlepage (sphinxmanual.cls, sphinxhowto.cls) +\newcommand{\releaseinfo}{} +\newcommand{\setreleaseinfo}[1]{\renewcommand{\releaseinfo}{#1}} +% this is inserted via template and #1=release config variable +\newcommand{\release}[1]{\renewcommand{\version}{#1}} +% this is defined by template to 'releasename' latex_elements key +\newcommand{\releasename}{} +% Fix issue in case release and releasename deliberately left blank +\newcommand{\sphinxheadercomma}{, }% used in fancyhdr header definition +\newcommand{\sphinxifemptyorblank}[1]{% +% test after one expansion of macro #1 if contents is empty or spaces + \if&\expandafter\@firstofone\detokenize\expandafter{#1}&% + \expandafter\@firstoftwo\else\expandafter\@secondoftwo\fi}% +\AtBeginDocument {% + \sphinxifemptyorblank{\releasename} + {\sphinxifemptyorblank{\version}{\let\sphinxheadercomma\empty}{}} + {}% +}% + +% Allow specification of the author's address separately from the +% author's name. This can be used to format them differently, which +% is a good thing. +% +\newcommand{\py@authoraddress}{} +\newcommand{\authoraddress}[1]{\renewcommand{\py@authoraddress}{#1}} + +% {fulllineitems} is the main environment for object descriptions. +% +% With 4.0.0 \pysigline (and \pysiglinewithargsret), used in a fulllineitems +% environment the #1 will already be of the width which is computed here, i.e. +% the available width on line, so the \makebox becomes a bit superfluous +\newcommand{\py@itemnewline}[1]{% macro used as \makelabel in fulllineitems +% Memo: this presupposes \itemindent is 0pt + \kern\labelsep % because \@labels core latex box does \hskip-\labelsep + \makebox[\dimexpr\linewidth+\labelwidth\relax][l]{#1}% + \kern-\labelsep % because at end of \@labels box there is \hskip\labelsep +} + +\newenvironment{fulllineitems}{% + \begin{list}{}{\labelwidth \leftmargin + \rightmargin \z@ \topsep -\parskip \partopsep \parskip + \itemsep -\parsep + \let\makelabel=\py@itemnewline}% +}{\end{list}} + +% Signatures, possibly multi-line +% +% For legacy reasons Sphinx uses LaTeX \list and \item's for signatures +% This is delicate: +% - the actual item label is not typeset immediately by \item but later as part +% of the \everypar which will be triggered by either next paragraph or a manual +% \leavevmode, or if nothing in-between by the next \item, +% - \begingroup \item[foo] \endgroup leads to errors, +% - vertical space depends on \parskip and \itemsep values in somewhat +% subtle manners. +% +% Since the 2022/01/13 version things are simpler as \parskip is simply set +% to zero during execution of \pysigline/\pysiglinewithargsret +% +% Parameter for separation via \itemsep of multiple signatures with common desc +\newlength\sphinxsignaturesep +\setlength\sphinxsignaturesep{\smallskipamount} +% latex.py outputs mark-up like this: +% \pysigstartsignatures \pysigstopsignatures +\newcommand{\pysigstartsignatures}{% + % store current \parskip and \itemsep + \edef\pysig@restore@itemsep@and@parskip{% + \itemsep\the\itemsep\relax + \parskip\the\parskip\relax + }% + % set them to control the spacing between signatures sharing common desc + \parskip\z@skip + \itemsep\sphinxsignaturesep +} +\newcommand{\pysigstopsignatures}{% +% 1) encourage a pagebreak in an attempt to try to avoid last +% signature ending up separated from description (due to voodoo next) +\penalty-100 +% 2) some voodoo to separate last signature from description in a manner +% robust with respect to the latter being itself a LaTeX list object +\leavevmode\par\kern-\baselineskip\item[\strut] +% + \leavevmode + % it is important \leavevmode was issued before the \parskip reset, and + % it is also needed for the case of an object desc itself a LaTeX \list + % now restore \itemsep and \parskip + \pysig@restore@itemsep@and@parskip +} +% Each signature is rendered as NAME[TPLIST](ARGLIST) where the +% size of is parametrized by \sphinxsignaturelistskip (0pt by default). +\newlength\sphinxsignaturelistskip +\setlength\sphinxsignaturelistskip{0pt} +\newcommand{\pysigtypelistopen}{\hskip\sphinxsignaturelistskip\sphinxcode{[}} +\newcommand{\pysigtypelistclose}{\sphinxcode{]}} +\newcommand{\pysigarglistopen}{\hskip\sphinxsignaturelistskip\sphinxcode{(}} +\newcommand{\pysigarglistclose}{\sphinxcode{)}} +% +% Use a \parbox to accommodate long argument list in signatures +% LaTeX did not imagine that an \item label could need multi-line rendering +\newlength{\py@argswidth} +\newcommand{\py@sigparams}[2]{% + % The \py@argswidth has been computed in \pysiglinewithargsret to make the + % argument list use full available width + \parbox[t]{\py@argswidth}{\raggedright #1\pysigarglistclose#2\strut}% + % final strut is to help get correct vertical separation +} +\newcommand{\py@sigparamswithtypelist}[3]{% + % similar to \py@sigparams but with different delimiters and an additional + % type parameters list given as #1, the argument list as #2 and the return + % annotation as #3 + \parbox[t]{\py@argswidth}{% + \raggedright #1\pysigtypelistclose% + \pysigarglistopen#2\pysigarglistclose% + #3\strut}% +} + +\newcommand{\pysigline}[1]{% + % as \py@argswidth is available, we use it but no "args" here + % the \relax\relax is because \py@argswidth is a "skip" variable + % this will make the label occupy the full available linewidth + \py@argswidth=\dimexpr\linewidth+\labelwidth\relax\relax + \item[{\parbox[t]{\py@argswidth}{\raggedright #1\strut}}] + \pysigadjustitemsep +} +\newcommand{\pysiglinewithargsret}[3]{% + % as #1 may contain a footnote using \label we need to make \label + % a no-op here to avoid LaTeX complaining about duplicates +\let\spx@label\label\let\label\@gobble + \settowidth{\py@argswidth}{#1\pysigarglistopen}% +\let\label\spx@label + \py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax + \item[{#1\pysigarglistopen\py@sigparams{#2}{#3}\strut}] + \pysigadjustitemsep +} +\newcommand{\pysiglinewithargsretwithtypelist}[4]{ +% #1 = name, #2 = typelist, #3 = arglist, #4 = retann +\let\spx@label\label\let\label\@gobble + \settowidth{\py@argswidth}{#1\pysigtypelistopen}% +\let\label\spx@label + \py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax + \item[{#1\pysigtypelistopen\py@sigparamswithtypelist{#2}{#3}{#4}\strut}] + \pysigadjustitemsep +} + +\def\sphinxoptionalextraspace{0.5mm} +\newcommand{\pysigwithonelineperarg}[3]{% + % render each argument on its own line + \item[#1\pysigarglistopen\strut] + \leavevmode\par\nopagebreak + % this relies on \pysigstartsignatures having set \parskip to zero + \begingroup + \let\sphinxparamcomma\sphinxparamcommaoneperline + \def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}% + % The very first \sphinxparam should not emit a \par hence a complication + % with a group and global definition here as it may occur in a \sphinxoptional + \global\let\spx@sphinxparam\sphinxparam + \gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}% + #2\par + \endgroup + \global\let\sphinxparam\spx@sphinxparam + % fulllineitems sets \labelwidth to be like \leftmargin + \nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#3} + \pysigadjustitemsep +} +\newcommand{\pysigwithonelineperargwithonelinepertparg}[4]{ + % #1 = name, #2 = typelist, #3 = arglist, #4 = retann + % render each type parameter and argument on its own line + \item[#1\pysigtypelistopen\strut] + \leavevmode\par\nopagebreak + \begingroup + \let\sphinxparamcomma\sphinxparamcommaoneperline + % \sphinxtypeparam is treated similarly to \sphinxparam but since + % \sphinxoptional is not accepted in a type parameters list, we do + % not need the hook or the global definition + \let\spx@sphinxtypeparam\sphinxtypeparam + \def\sphinxtypeparam{\def\sphinxtypeparam{\par\spx@sphinxtypeparam}\spx@sphinxtypeparam}% + #2\par + \endgroup + \nopagebreak\noindent\kern-\labelwidth\pysigtypelistclose% + % render the rest of the signature like in \pysigwithonelineperarg + \pysigarglistopen\strut\par\nopagebreak + \begingroup + \let\sphinxparamcomma\sphinxparamcommaoneperline + \def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}% + \global\let\spx@sphinxparam\sphinxparam + \gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}% + #3\par + \endgroup + \global\let\sphinxparam\spx@sphinxparam + \nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#4} + \pysigadjustitemsep +} +\newcommand{\pysiglinewithargsretwithonelinepertparg}[4]{ + % #1 = name, #2 = typelist, #3 = arglist, #4 = retann + % render each type parameter on its own line but the arguments list inline + \item[#1\pysigtypelistopen\strut] + \leavevmode\par\nopagebreak + \begingroup + \let\sphinxparamcomma\sphinxparamcommaoneperline + % \sphinxtypeparam is treated similarly to \sphinxparam but since + % \sphinxoptional is not accepted in a type parameters list, we do + % not need the hook or the global definition + \let\spx@sphinxtypeparam\sphinxtypeparam + \def\sphinxtypeparam{\def\sphinxtypeparam{\par\spx@sphinxtypeparam}\spx@sphinxtypeparam}% + #2\par + \endgroup + \nopagebreak\noindent\kern-\labelwidth\pysigtypelistclose% + % render the arguments list on one line + \pysigarglistopen#3\pysigarglistclose#4\strut + \pysigadjustitemsep +} +\newcommand{\pysigwithonelineperargwithtypelist}[4]{ + % #1 = name, #2 = typelist, #3 = arglist, #4 = retann + % render the type parameters list on one line, but each argument is rendered on its own line +\let\spx@label\label\let\label\@gobble + \settowidth{\py@argswidth}{#1\pysigtypelistopen}% +\let\label\spx@label + \py@argswidth=\dimexpr\linewidth+\labelwidth-\py@argswidth\relax\relax + \item[{#1\pysigtypelistopen\parbox[t]{\py@argswidth}{% + \raggedright #2\pysigtypelistclose\pysigarglistopen\strut}\strut}] + % render the rest of the signature like in \pysigwithonelineperarg + \begingroup + \let\sphinxparamcomma\sphinxparamcommaoneperline + \def\sphinxoptionalhook{\ifvmode\else\kern\sphinxoptionalextraspace\relax\fi}% + \global\let\spx@sphinxparam\sphinxparam + \gdef\sphinxparam{\gdef\sphinxparam{\par\spx@sphinxparam}\spx@sphinxparam}% + #3\par + \endgroup + \global\let\sphinxparam\spx@sphinxparam + \nopagebreak\noindent\kern-\labelwidth\pysigarglistclose{#4} + \pysigadjustitemsep +} +\newcommand{\pysigadjustitemsep}{% + % adjust \itemsep to control the separation with the next signature + % sharing common description + \ifsphinxsigismultiline + % inside a multiline signature, no extra vertical spacing + % ("multiline" here does not refer to possibly long + % list of arguments, but to a cpp domain feature) + \itemsep\z@skip + \else + \itemsep\sphinxsignaturesep + \fi +} +\newif\ifsphinxsigismultiline +\newcommand{\pysigstartmultiline}{\sphinxsigismultilinetrue}% +\newcommand{\pysigstopmultiline}{\sphinxsigismultilinefalse\itemsep\sphinxsignaturesep}% + +% Production lists +% +\newenvironment{productionlist}{% +% \def\sphinxoptional##1{{\Large[}##1{\Large]}} + \def\production##1##2{\\\sphinxcode{\sphinxupquote{##1}}&::=&\sphinxcode{\sphinxupquote{##2}}}% + \def\productioncont##1{\\& &\sphinxcode{\sphinxupquote{##1}}}% + \parindent=2em + \indent + \setlength{\LTpre}{0pt}% + \setlength{\LTpost}{0pt}% + \begin{longtable}[l]{lcl} +}{% + \end{longtable} +} + +% Definition lists; requested by AMK for HOWTO documents. Probably useful +% elsewhere as well, so keep in in the general style support. +% +\newenvironment{definitions}{% + \begin{description}% + \def\term##1{\item[{##1}]\mbox{}\\*[0mm]}% +}{% + \end{description}% +} + +%% FROM DOCTUTILS LATEX WRITER +% +% The following is stuff copied from docutils' latex writer. +% +\newcommand{\optionlistlabel}[1]{\normalfont\bfseries #1 \hfill}% \bf deprecated +\newenvironment{optionlist}[1] +{\begin{list}{} + {\setlength{\labelwidth}{#1}% + \setlength{\rightmargin}{1cm}% + \setlength{\leftmargin}{\rightmargin}% + \addtolength{\leftmargin}{\labelwidth}% + \addtolength{\leftmargin}{\labelsep}% + \renewcommand{\makelabel}{\optionlistlabel}}% +}{\end{list}} + +\newlength{\lineblockindentation} +\setlength{\lineblockindentation}{2.5em} +\newenvironment{lineblock}[1] +{\begin{list}{} + {\setlength{\partopsep}{\parskip}% + \addtolength{\partopsep}{\baselineskip}% + \topsep0pt\itemsep0.15\baselineskip\parsep0pt + \leftmargin#1\relax}% + \raggedright} +{\end{list}} + +% From docutils.writers.latex2e +% inline markup (custom roles) +% \DUrole{#1}{#2} tries \DUrole#1{#2} +\providecommand*{\DUrole}[2]{% + \ifcsname DUrole\detokenize{#1}\endcsname + \csname DUrole\detokenize{#1}\endcsname{#2}% + \else% backwards compatibility: try \docutilsrole#1{#2} + \ifcsname docutilsrole\detokenize{#1}\endcsname + \csname docutilsrole\detokenize{#1}\endcsname{#2}% + \else + #2% + \fi + \fi +} + +\providecommand*{\DUprovidelength}[2]{% + \ifdefined#1\else\newlength{#1}\setlength{#1}{#2}\fi +} + +\DUprovidelength{\DUlineblockindent}{2.5em} +\ifdefined\DUlineblock\else + \newenvironment{DUlineblock}[1]{% + \list{}{\setlength{\partopsep}{\parskip}% + \addtolength{\partopsep}{\baselineskip}% + \setlength{\topsep}{0pt}% + \setlength{\itemsep}{0.15\baselineskip}% + \setlength{\parsep}{0pt}% + \setlength{\leftmargin}{#1}}% + \raggedright + } + {\endlist} +\fi + +\endinput diff --git a/docs/build/latex/sphinxlatexshadowbox.sty b/docs/build/latex/sphinxlatexshadowbox.sty new file mode 100644 index 0000000000000000000000000000000000000000..53a333845aa7ecfcb515dca94335cda75bdcda53 --- /dev/null +++ b/docs/build/latex/sphinxlatexshadowbox.sty @@ -0,0 +1,178 @@ +%% TOPIC AND CONTENTS BOXES +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexshadowbox}[2024/07/28 v8.1.0 sphinxShadowBox] + +% Provides support for this output mark-up from Sphinx latex writer: +% +% - Environments: sphinxtopic, sphinxcontents, and sphinxsidebar. +% +% These wrappers replace at 8.1.0 former direct use of sphinxShadowBox +% environment which did not allow separate styling. +% +% - Commands: \sphinxstyletopictitle, \sphinxstylecontentstitle, and +% \sphinxstylesidebartitle. +% +% At 8.1.0 they default to use \sphinxdotitlerow whose definiion is done in +% sphinxlatexadmonitions.sty. There is also \sphinxstylesidebarsubtitle +% which does not use \sphinxdotitlerow. +% +% Dependencies (they do not need to be defined at time of loading): +% +% - of course the various colour and dimension options handled via sphinx.sty +% - dimension register \spx@image@maxheight from sphinxlatexgraphics.sty +% - \savenotes/\spewnotes from sphinxpackagefootnote.sty +% - \ifspx@inframed defined in sphinx.sty +% - \sphinxdotitlerow from sphinxlatexadmonitions.sty +% - \spx@boxes@fcolorbox@setup from sphinxpackageboxes.sty +% +\RequirePackage{framed} +% Those are required either before or after by sphinx.sty anyhow, but for +% clarity we list them here: +\RequirePackage{sphinxlatexgraphics} +\RequirePackage{sphinxpackagefootnote} +\RequirePackage{sphinxlatexadmonitions} +\RequirePackage{sphinxpackageboxes} + +% At 5.1.0 the code formerly here in a definition of \spx@ShadowFBox has been +% refactored to hand over to a more powerful \spx@boxes@fcolorbox provided by +% file sphinxpackageboxes.sty, it can draw rounded corners and add a background +% color. + +% At 6.2.0, \spx@ShadowFBox is so much simplified that it is now not +% separately defined but directly incorporated into the \FrameCommand +% definition done by sphinxShadowBox environment below. + +% Use framed.sty \MakeFramed/\endMakeFramed to allow page breaks for topic +% boxes. Originally Sphinx used \shadowbox from fancybox.sty but it did not +% allow pagebreaks (which was problematic for "contents" directive if there +% are many subsections). +% +% Docutils does not allow topic to be nested within topics or other body +% elements. But the LaTeX code here does allow it: +% +% - a topic inside another topic would be rendered in a minipage (thus not +% allowing pagebreaks). Its external frame would adapt perfectly to +% the *current (smaller) width for text*. +% +% - a topic inside (nested) lists or quote environments would have its frame +% take the *full width* of the page, but its text contents on the other hand +% would obey exactly the current indentation plus inner separation. This is +% in contrast with the framing used for literal blocks, also based, but in a +% more sophisticated way on usage of \MakeFramed/\endMakeFramed, and +% adjusting to current text indentation. +% +% At 8.1.0, sphinxShadowBox takes an optional argument #1 and uses it as +% \spx@boxes@fcolorbox@setup{#1} rather than \spx@boxes@fcolorbox@setup{topic}. +% Some hesitation whether to move this line to newly added sphinxtopic, +% sphinxcontents and sphinxsidebar environmments. But anyhow the environment +% also requires later knowing a few more things: sphinxTextColor and +% spx@@texextras. +% +% The #1 defaulting to topic must be such that all parameters expected by +% \spx@boxes@fcolorbox@setup actually do exist, see CSS options in sphinx.sty +% which is what defines them for contents, topic, and sidebar. +% +% Fortunately the #1 is not needed in \end{sphinxShadowBox} so we don't have +% to work around a LaTeX conception bug that such #1 can not be used as is in +% the definition of the \end part of an environment. +% +% MEMO: the "shadow" is not really drawn directly by this environment but +% indirectly via the configuration which is passed over to \spx@boxes@fcolorbox, +% which is the macro creating frame and (perhaps but not necessarily) a shadow. +\newenvironment{sphinxShadowBox}[1][topic]% + {% + \spx@boxes@fcolorbox@setup{#1}% + % we will use the dimen registers from sphinxpackageboxes.sty which now hold + % the values from options related to topic/contents + % MEMO: \spx@boxes@fcolorbox creates an \hbox but does not quit vertical + % mode; but in context of framed.sty's \FrameCommand TeX is already + % in restricted horizontal mode, so no need for a \leavevmode here. + \def\FrameCommand {\spx@boxes@fcolorbox}% + % 6.2.0 adds support for div.topic_box-decoration-break=slice. + % (it is yet undecided if slice style should inhibit a bottom shadow) + \@nameuse{ifspx@#1@border@open}% + \def\FirstFrameCommand + {\spx@boxes@fcolorbox@setup@openbottom\FrameCommand}% + \def\MidFrameCommand + {\spx@boxes@fcolorbox@setup@openboth \FrameCommand}% + \def\LastFrameCommand + {\spx@boxes@fcolorbox@setup@opentop \FrameCommand}% + \fi + \advance\spx@image@maxheight + -\dimexpr\spx@boxes@border@top+\spx@boxes@border@bottom + +\spx@boxes@padding@top+\spx@boxes@padding@bottom + +\ifdim\spx@boxes@shadow@yoffset<\z@-\fi\spx@boxes@shadow@yoffset + +\baselineskip\relax + % configure framed.sty not to add extra vertical spacing + \ltx@ifundefined{OuterFrameSep}{}{\OuterFrameSep\z@skip}% + % the \trivlist will add the vertical spacing on top and bottom which is + % typical of center environment as used in Sphinx <= 1.4.1 + % the \noindent has the effet of an extra blank line on top, to + % imitate closely the layout from Sphinx <= 1.4.1; the \FrameHeightAdjust + % will put top part of frame on this baseline. + \def\FrameHeightAdjust {\baselineskip}% + % use package footnote to handle footnotes + \savenotes + \trivlist\item\noindent + % use a minipage if we are already inside a framed environment + \ifspx@inframed\begin{minipage}{\linewidth}\fi + \MakeFramed {\spx@inframedtrue + % framed.sty puts into "\width" the added width (padding+border widths) + % adjust \hsize to what the contents must use + \advance\hsize-\width + % adjust LaTeX parameters to behave properly in indented/quoted contexts + \FrameRestore + % typeset the contents as in a minipage (Sphinx <= 1.4.1 used a minipage and + % itemize/enumerate are therein typeset more tightly, we want to keep + % that). We copy-paste from LaTeX source code but don't do a real minipage. + \@pboxswfalse + \let\@listdepth\@mplistdepth \@mplistdepth\z@ + \@minipagerestore + \@setminipage + }% + \color@begingroup % workaround upstream framed.sty bug + \@nameuse{ifspx@#1@withtextcolor}% + \color{sphinx#1TextColor}% + \fi + \@nameuse{spx@#1@TeXextras}% + }% + {% insert the "endminipage" code + \par\unskip + \color@endgroup % matches the \color@begingroup + \@minipagefalse + \endMakeFramed + \ifspx@inframed\end{minipage}\fi + \endtrivlist + % output the stored footnotes + \spewnotes + } + +% 8.1.0 +\newenvironment{sphinxtopic} + {\begin{sphinxShadowBox}[topic]}{\end{sphinxShadowBox}} +\newenvironment{sphinxcontents} + {\begin{sphinxShadowBox}[contents]}{\end{sphinxShadowBox}} +% Arguably sphinxsidebar should rather use a wrapfig or similar environment +% but this is so dysfunctional in LaTeX (except for self-written documents) +% so we prefer to not venture into such a potential quagmire and keep the +% legacy rendering using a full width display. +\newenvironment{sphinxsidebar} + {\begin{sphinxShadowBox}[sidebar]}{\end{sphinxShadowBox}} + +% TODO: decide if this should be in sphinxlatexstyletext.sty rather +% +% 8.1.0 styles topic/contents/sidebar with a title row, too. +% Prior to 8.1.0, definitions use \protected\def but there does not seem +% to be any reason so back to \newcommand. +\newcommand*\sphinxstyletopictitle[1]{\sphinxdotitlerow{topic}{#1}} +\newcommand*\sphinxstylecontentstitle[1]{\sphinxdotitlerow{contents}{#1}} +\newcommand*\sphinxstylesidebartitle[1]{\sphinxdotitlerow{sidebar}{#1}} +% No default color background for subtitle. The contents next are injected by +% LaTeX writer after a blank line in source hence will start a new paragrpah. +% The \sphinxAtStartPar here is only for coherence with other text paragraphs, +% but does not have serious necessity (its general role is to allow hyphenation +% for first word in narrow table cells). +\newcommand*\sphinxstylesidebarsubtitle[1]{\sphinxAtStartPar\textbf{#1}} + +\endinput diff --git a/docs/build/latex/sphinxlatexstyleheadings.sty b/docs/build/latex/sphinxlatexstyleheadings.sty new file mode 100644 index 0000000000000000000000000000000000000000..08773c0b65894380845cd5efd3838599c6b9a190 --- /dev/null +++ b/docs/build/latex/sphinxlatexstyleheadings.sty @@ -0,0 +1,91 @@ +%% TITLES +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexstyleheadings}[2023/02/11 headings] + +\RequirePackage[nobottomtitles*]{titlesec} +% tests showed that this setting guarantees \section title has +% 3 lines of text following it on same page if near bottom. +\renewcommand\bottomtitlespace{6\baselineskip} +% the default setting of 0.2\textheight is about 11\baselineskip +% (for 10pt letterpaper documents) and may create large voids. + +\@ifpackagelater{titlesec}{2016/03/15}% + {\@ifpackagelater{titlesec}{2016/03/21}% + {}% + {\newif\ifsphinx@ttlpatch@ok + \IfFileExists{etoolbox.sty}{% + \RequirePackage{etoolbox}% + \patchcmd{\ttlh@hang}{\parindent\z@}{\parindent\z@\leavevmode}% + {\sphinx@ttlpatch@oktrue}{}% + \ifsphinx@ttlpatch@ok + \patchcmd{\ttlh@hang}{\noindent}{}{}{\sphinx@ttlpatch@okfalse}% + \fi + }{}% + \ifsphinx@ttlpatch@ok + \typeout{^^J Package Sphinx Info: ^^J + **** titlesec 2.10.1 successfully patched for bugfix ****^^J}% + \else + \AtEndDocument{\PackageWarningNoLine{sphinx}{^^J% +******** titlesec 2.10.1 has a bug, (section numbers disappear) ......|^^J% +******** and Sphinx could not patch it, perhaps because your local ...|^^J% +******** copy is already fixed without a changed release date. .......|^^J% +******** If not, you must update titlesec! ...........................|}}% + \sphinxbuildwarning{badtitlesec}% + \fi + }% + }{} + +% Augment the sectioning commands used to get our own font family in place, +% and reset some internal data items (\titleformat from titlesec package) +\titleformat{\section}{\Large\py@HeaderFamily}% + {\py@TitleColor\thesection}{0.5em}{\py@TitleColor} +\titleformat{\subsection}{\large\py@HeaderFamily}% + {\py@TitleColor\thesubsection}{0.5em}{\py@TitleColor} +% \normalsize added as work-around to a lualatex-ja upstream problem +% https://osdn.net/projects/luatex-ja/ticket/47321 +\titleformat{\subsubsection}{\normalsize\py@HeaderFamily}% + {\py@TitleColor\thesubsubsection}{0.5em}{\py@TitleColor} +% By default paragraphs (and subsubsections) will not be numbered because +% sphinxmanual.cls and sphinxhowto.cls set secnumdepth to 2 +\titleformat{\paragraph}{\normalsize\py@HeaderFamily}% + {\py@TitleColor\theparagraph}{0.5em}{\py@TitleColor} +\titleformat{\subparagraph}{\normalsize\py@HeaderFamily}% + {\py@TitleColor\thesubparagraph}{0.5em}{\py@TitleColor} + +% Since Sphinx 1.5, users should use HeaderFamily key to 'sphinxsetup' rather +% than defining their own \py@HeaderFamily command (which is still possible). +% Memo: \py@HeaderFamily is also used by \maketitle as defined in +% sphinxmanual.cls/sphinxhowto.cls +\newcommand{\py@HeaderFamily}{\spx@opt@HeaderFamily} + +% This sets up the fancy chapter headings that make the documents look +% at least a little better than the usual LaTeX output. +\@ifpackagewith{fncychap}{Bjarne}{ + \ChNameVar {\raggedleft\normalsize \py@HeaderFamily} + \ChNumVar {\raggedleft\Large \py@HeaderFamily} + \ChTitleVar{\raggedleft\Large \py@HeaderFamily} + % This creates (numbered) chapter heads without the leading \vspace*{}: + \def\@makechapterhead#1{% + {\parindent \z@ \raggedright \normalfont + \ifnum \c@secnumdepth >\m@ne + \if@mainmatter + \DOCH + \fi + \fi + \interlinepenalty\@M + \if@mainmatter + \DOTI{#1}% + \else% + \DOTIS{#1}% + \fi + }} +}{}% <-- "false" clause of \@ifpackagewith + +% fix fncychap's bug which uses prematurely the \textwidth value +\@ifpackagewith{fncychap}{Bjornstrup} + {\AtBeginDocument{\mylen\textwidth\advance\mylen-2\myhi}}% + {}% <-- "false" clause of \@ifpackagewith + + +\endinput diff --git a/docs/build/latex/sphinxlatexstylepage.sty b/docs/build/latex/sphinxlatexstylepage.sty new file mode 100644 index 0000000000000000000000000000000000000000..53f9e4828c286383962e9426923e63ec9df979f4 --- /dev/null +++ b/docs/build/latex/sphinxlatexstylepage.sty @@ -0,0 +1,73 @@ +%% PAGE STYLING +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexstylepage}[2021/01/27 page styling] + +% Separate paragraphs by space by default. +\RequirePackage{parskip} + +% Style parameters and macros used by most documents here +\raggedbottom +\sloppy +\hbadness = 5000 % don't print trivial gripes + +% Require package fancyhdr except under memoir class +\@ifclassloaded{memoir}{}{\RequirePackage{fancyhdr}} +% Use \pagestyle{normal} as the primary pagestyle for text. +% Redefine the 'normal' header/footer style when using "fancyhdr" package: +\@ifpackageloaded{fancyhdr}{% + \ltx@ifundefined{c@chapter} + {% no \chapter, "howto" (non-Japanese) docclass + \fancypagestyle{plain}{ + \fancyhf{} + \fancyfoot[C]{{\py@HeaderFamily\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} + } + % Same as 'plain', this way we can use it in template + % FIXME: shouldn't this have a running header with Name and Release like 'manual'? + \fancypagestyle{normal}{ + \fancyhf{} + \fancyfoot[C]{{\py@HeaderFamily\thepage}} + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0pt} + } + }% + {% classes with \chapter command + \fancypagestyle{normal}{ + \fancyhf{} + \fancyfoot[RO]{{\py@HeaderFamily\thepage}} + \fancyfoot[LO]{{\py@HeaderFamily\nouppercase{\rightmark}}} + \fancyhead[RO]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}} + \if@twoside + \fancyfoot[LE]{{\py@HeaderFamily\thepage}} + \fancyfoot[RE]{{\py@HeaderFamily\nouppercase{\leftmark}}} + \fancyhead[LE]{{\py@HeaderFamily \@title\sphinxheadercomma\py@release}} + \fi + \renewcommand{\headrulewidth}{0.4pt} + \renewcommand{\footrulewidth}{0.4pt} + % define chaptermark with \@chappos when \@chappos is available for Japanese + \ltx@ifundefined{@chappos}{} + {\def\chaptermark##1{\markboth{\@chapapp\space\thechapter\space\@chappos\space ##1}{}}} + } + % Update the plain style so we get the page number & footer line, + % but not a chapter or section title. This is to keep the first + % page of a chapter `clean.' + \fancypagestyle{plain}{ + \fancyhf{} + \fancyfoot[RO]{{\py@HeaderFamily\thepage}} + \if@twoside\fancyfoot[LE]{{\py@HeaderFamily\thepage}}\fi + \renewcommand{\headrulewidth}{0pt} + \renewcommand{\footrulewidth}{0.4pt} + } + } + } + {% no fancyhdr: memoir class + % Provide default for 'normal' style simply as an alias of 'plain' style + % This way we can use \pagestyle{normal} in LaTeX template + \def\ps@normal{\ps@plain} + % Users of memoir class are invited to redefine 'normal' style in preamble + } + + +\endinput diff --git a/docs/build/latex/sphinxlatexstyletext.sty b/docs/build/latex/sphinxlatexstyletext.sty new file mode 100644 index 0000000000000000000000000000000000000000..d083cd96a83a4a51eb74f9cd789081cc090a7a25 --- /dev/null +++ b/docs/build/latex/sphinxlatexstyletext.sty @@ -0,0 +1,145 @@ +%% TEXT STYLING +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatexstyletext}[2024/07/28 v8.1.0 text styling] + +% 7.4.0 has moved all that is related to admonitions to sphinxlatexadmonitions.sty +% 8.1.0 has moved topic/contents/sidebar to sphinxlatexshadowbox.sty +% Most everything left here consists of macros which are part of the latex markup +% produced by the Sphinx LaTeX writer. + +% Some custom font markup commands. +\protected\def\sphinxstrong#1{\textbf{#1}} +\protected\def\sphinxcode#1{\texttt{#1}} +\protected\def\sphinxbfcode#1{\textbf{\sphinxcode{#1}}} +\protected\def\sphinxemail#1{\textsf{#1}} +\protected\def\sphinxtablecontinued#1{\textsf{#1}} +\protected\def\sphinxtitleref#1{\emph{#1}} +\protected\def\sphinxmenuselection#1{\emph{#1}} +\protected\def\sphinxguilabel#1{\emph{#1}} +\protected\def\sphinxkeyboard#1{\sphinxcode{#1}} +\protected\def\sphinxaccelerator#1{\underline{#1}} +\protected\def\sphinxcrossref#1{\emph{#1}} +\protected\def\sphinxtermref#1{\emph{#1}} +\protected\def\sphinxsamedocref#1{\emph{#1}} +\protected\def\sphinxparam#1{\emph{#1}} +\protected\def\sphinxtypeparam#1{\emph{#1}} +% \optional is used for ``[, arg]``, i.e. desc_optional nodes. +\long\protected\def\sphinxoptional#1{% + {\sphinxoptionalhook\textnormal{\Large[}}{#1}\hspace{0.5mm}{\textnormal{\Large]}}} +\let\sphinxoptionalhook\empty + +% additional customizable styling +\def\sphinxstyleindexentry #1{\texttt{#1}} +\def\sphinxstyleindexextra #1{ (\emph{#1})} +\def\sphinxstyleindexpageref #1{, \pageref{#1}} +\def\sphinxstyleindexpagemain#1{\textbf{#1}} +\def\spxentry{\@backslashchar spxentry}% let to \sphinxstyleindexentry in index +\def\spxextra{\@backslashchar spxextra}% let to \sphinxstyleindexextra in index +\def\sphinxstyleindexlettergroup #1% + {{\Large\sffamily#1}\nopagebreak\vspace{1mm}} +\def\sphinxstyleindexlettergroupDefault #1% + {{\Large\sffamily\sphinxnonalphabeticalgroupname}\nopagebreak\vspace{1mm}} +\protected\def\sphinxstyleothertitle #1{\textbf{#1}} +% \text.. commands do not allow multiple paragraphs +% attention, this one is not self-delimiting +\protected\def\sphinxstyletheadfamily {\sffamily} +\protected\def\sphinxstyleemphasis #1{\emph{#1}} +\protected\def\sphinxstyleliteralemphasis#1{\emph{\sphinxcode{#1}}} +\protected\def\sphinxstylestrong #1{\textbf{#1}} +\protected\def\sphinxstyleliteralstrong#1{\sphinxbfcode{#1}} +\protected\def\sphinxstyleabbreviation #1{\textsc{#1}} +\protected\def\sphinxstyleliteralintitle#1{\sphinxcode{#1}} +\newcommand*\sphinxstylecodecontinued[1]{{\footnotesize(#1)}}% +\newcommand*\sphinxstylecodecontinues[1]{{\footnotesize(#1)}}% +% figure legend comes after caption and may contain arbitrary body elements +\newenvironment{sphinxlegend}{\par\small}{\par} +% reduce hyperref "Token not allowed in a PDF string" warnings on PDF builds +\AtBeginDocument{\pdfstringdefDisableCommands{% +% all "protected" macros possibly ending up in section titles should be here +% TODO: examine if \sphinxhref, \sphinxurl, \sphinnolinkurl should be handled + \let\sphinxstyleemphasis \@firstofone + \let\sphinxstyleliteralemphasis \@firstofone + \let\sphinxstylestrong \@firstofone + \let\sphinxstyleliteralstrong \@firstofone + \let\sphinxstyleabbreviation \@firstofone + \let\sphinxstyleliteralintitle \@firstofone + \let\sphinxupquote \@firstofone + \let\sphinxstrong \@firstofone + \let\sphinxcode \@firstofone + \let\sphinxbfcode \@firstofone + \let\sphinxemail \@firstofone + \let\sphinxcrossref \@firstofone + \let\sphinxtermref \@firstofone + \let\sphinxsamedocref\@firstofone + \let\sphinxhyphen\sphinxhyphenforbookmarks + \def\PYG#1#2{#2}% (can not yet appear in section titles, but perhaps in future) +}} + +% Special characters +% +\def\sphinxparamcomma{, }% by default separate parameters with comma + space +% If the signature is rendered with one line per param, this wil be used +% instead (this \texttt makes the comma slightly more distinctive). +\def\sphinxparamcommaoneperline{\texttt{,}} +% +% The \kern\z@ is to prevent en-dash and em-dash TeX ligatures. +% A linebreak can occur after the dash in regular text (this is +% normal behaviour of "-" in TeX, it is not related to \kern\z@). +% +% Parsed-literals and inline literals also use the \sphinxhyphen +% but linebreaks there are prevented due to monospace font family. +% (xelatex needs a special addition, cf. sphinxlatexliterals.sty) +% +% Inside code-blocks, dashes are escaped via another macro, from +% Pygments latex output (search for \PYGZhy in sphinxlatexliterals.sty), +% and are configured to allow linebreaks despite the monospace font. +% (the #1 swallows the {} from \sphinxhyphen{} mark-up) +\protected\def\sphinxhyphen#1{-\kern\z@} +\protected\def\sphinxhyphennobreak#1{\mbox{-}} +% The {} from texescape mark-up is kept, else -- gives en-dash in PDF bookmark +\def\sphinxhyphenforbookmarks{-} + +% For curly braces inside \index macro +\def\sphinxleftcurlybrace{\{} +\def\sphinxrightcurlybrace{\}} + +% Declare Unicode characters used by linux tree command to pdflatex utf8/utf8x +\def\spx@bd#1#2{% + \leavevmode + \begingroup + \ifx\spx@bd@height \@undefined\def\spx@bd@height{\baselineskip}\fi + \ifx\spx@bd@width \@undefined\setbox0\hbox{0}\def\spx@bd@width{\wd0 }\fi + \ifx\spx@bd@thickness\@undefined\def\spx@bd@thickness{.6\p@}\fi + \ifx\spx@bd@lower \@undefined\def\spx@bd@lower{\dp\strutbox}\fi + \lower\spx@bd@lower#1{#2}% + \endgroup +}% +\@namedef{sphinx@u2500}% BOX DRAWINGS LIGHT HORIZONTAL + {\spx@bd{\vbox to\spx@bd@height} + {\vss\hrule\@height\spx@bd@thickness + \@width\spx@bd@width\vss}}% +\@namedef{sphinx@u2502}% BOX DRAWINGS LIGHT VERTICAL + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss\vrule\@height\spx@bd@height + \@width \spx@bd@thickness\hss}}% +\@namedef{sphinx@u2514}% BOX DRAWINGS LIGHT UP AND RIGHT + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss\raise.5\spx@bd@height + \hb@xt@\z@{\hss\vrule\@height.5\spx@bd@height + \@width \spx@bd@thickness\hss}% + \vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness + \@width.5\spx@bd@width\vss}}}% +\@namedef{sphinx@u251C}% BOX DRAWINGS LIGHT VERTICAL AND RIGHT + {\spx@bd{\hb@xt@\spx@bd@width} + {\hss + \hb@xt@\z@{\hss\vrule\@height\spx@bd@height + \@width \spx@bd@thickness\hss}% + \vbox to\spx@bd@height{\vss\hrule\@height\spx@bd@thickness + \@width.5\spx@bd@width\vss}}}% +\protected\def\sphinxunichar#1{\@nameuse{sphinx@u#1}}% + +% Tell TeX about pathological hyphenation cases: +\hyphenation{Base-HTTP-Re-quest-Hand-ler} + +\endinput diff --git a/docs/build/latex/sphinxlatextables.sty b/docs/build/latex/sphinxlatextables.sty new file mode 100644 index 0000000000000000000000000000000000000000..4114955e07108c6bdcbfaf5ba304fcd2acd2ab80 --- /dev/null +++ b/docs/build/latex/sphinxlatextables.sty @@ -0,0 +1,1241 @@ +%% TABLES (WITH SUPPORT FOR MERGED CELLS OF GENERAL CONTENTS) +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxlatextables}[2024/07/01 v7.4.0 tables]% + +% Provides support for this output mark-up from Sphinx latex writer +% and table templates: +% +% - the tabulary and longtable environments from the eponymous packages +% - the varwidth environment +% - the >{} etc mark-up possible in tabularcolumns is from array package +% which is loaded by longtable and tabulary +% - \X, \Y, T column types; others (L, C, R, J) are from tabulary package +% - \sphinxaftertopcaption +% - \sphinxatlongtableend +% - \sphinxatlongtablestart +% - \sphinxattableend +% - \sphinxattablestart +% - \sphinxcapstartof +% - \sphinxcolwidth +% - \sphinxlongtablecapskipadjust +% - \sphinxmultirow +% - \sphinxstartmulticolumn +% - \sphinxstopmulticolumn +% - \sphinxtablestrut +% - \sphinxthecaptionisattop +% - \sphinxthelongtablecaptionisattop +% - \sphinxhline +% - \sphinxcline +% - \sphinxvlinecrossing +% - \sphinxfixclines +% - \sphinxtoprule +% - \sphinxmidrule +% - \sphinxbottomrule +% - \sphinxtableatstartofbodyhook +% - \sphinxtableafterendhook +% - \sphinxthistablewithglobalstyle +% - \sphinxthistablewithbooktabsstyle +% - \sphinxthistablewithborderlessstyle +% - \sphinxthistablewithstandardstyle +% - \sphinxthistablewithcolorrowsstyle +% - \sphinxthistablewithnocolorrowsstyle +% - \sphinxthistablewithvlinesstyle +% - \sphinxthistablewithnovlinesstyle +% +% Also provides user command (see docs) +% - \sphixncolorblend +% (Sphinx 7.4.0 now requires xcolor, so \sphinxcolorblend does not check +% its availability anymore) +% +% Executes \RequirePackage for: +% +% - tabulary +% - longtable +% - varwidth +% - colortbl +% - booktabs if 'booktabs' in latex_table_style +% +% Extends tabulary and longtable via patches and custom macros to support +% merged cells possibly containing code-blocks in complex tables + +\RequirePackage{tabulary} +% tabulary has a bug with its re-definition of \multicolumn in its first pass +% which is not \long. But now Sphinx does not use LaTeX's \multicolumn but its +% own macro. Hence we don't even need to patch tabulary. See +% sphinxpackagemulticell.sty +% X or S (Sphinx) may have meanings if some table package is loaded hence +% \X was chosen to avoid possibility of conflict +\newcolumntype{\X}[2]{p{\dimexpr + (\linewidth-\spx@arrayrulewidth)*#1/#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} +\newcolumntype{\Y}[1]{p{\dimexpr + #1\dimexpr\linewidth-\spx@arrayrulewidth\relax-\tw@\tabcolsep-\spx@arrayrulewidth\relax}} +% \spx@arrayrulewidth is used internally and its meaning will be set according +% to the table type; no extra user code should modify it. In particular any +% \setlength{\spx@arrayrulewidth}{...} may break all of LaTeX... (really...) +\def\spx@arrayrulewidth{\arrayrulewidth}% 5.3.0, to be adjusted by each table +% using here T (for Tabulary) feels less of a problem than the X could be +\newcolumntype{T}{J}% +% For tables allowing pagebreaks +\RequirePackage{longtable} +% User interface to set-up whitespace before and after tables: +\newcommand*\sphinxtablepre {0pt}% +\newcommand*\sphinxtablepost{\medskipamount}% +% Space from caption baseline to top of table or frame of literal-block +\newcommand*\sphinxbelowcaptionspace{.5\sphinxbaselineskip}% +% as one can not use \baselineskip from inside longtable (it is zero there) +% we need \sphinxbaselineskip, which defaults to \baselineskip +\def\sphinxbaselineskip{\baselineskip}% +% The following is to ensure that, whether tabular(y) or longtable: +% - if a caption is on top of table: +% a) the space between its last baseline and the top rule of table is +% exactly \sphinxbelowcaptionspace +% b) the space from last baseline of previous text to first baseline of +% caption is exactly \parskip+\baselineskip+ height of a strut. +% c) the caption text will wrap at width \LTcapwidth (4in) +% - make sure this works also if "caption" package is loaded by user +% (with its width or margin option taking place of \LTcapwidth role) +% TODO: obtain same for caption of literal block: a) & c) DONE, b) TO BE DONE +% +% To modify space below such top caption, adjust \sphinxbelowcaptionspace +% To add or remove space above such top caption, adjust \sphinxtablepre: +% notice that \abovecaptionskip, \belowcaptionskip, \LTpre are **ignored** +% A. Table with longtable +\def\sphinxatlongtablestart + {\par + \vskip\parskip + \vskip\dimexpr\sphinxtablepre\relax % adjust vertical position + \vbox{}% get correct baseline from above + \LTpre\z@skip\LTpost\z@skip % set to zero longtable's own skips + \edef\sphinxbaselineskip{\dimexpr\the\dimexpr\baselineskip\relax\relax}% + \spx@inframedtrue % message to sphinxheavybox + }% +% Compatibility with caption package +\def\sphinxthelongtablecaptionisattop{% + \spx@ifcaptionpackage{\noalign{\vskip-\belowcaptionskip}}{}% +}% +% Achieves exactly \sphinxbelowcaptionspace below longtable caption +\def\sphinxlongtablecapskipadjust + {\dimexpr-\dp\strutbox + -\spx@ifcaptionpackage{\abovecaptionskip}{\sphinxbaselineskip}% + +\sphinxbelowcaptionspace\relax}% +\def\sphinxatlongtableend{\@nobreakfalse % latex3/latex2e#173 + \prevdepth\z@\vskip\sphinxtablepost\relax}% +% B. Table with tabular or tabulary +\def\sphinxattablestart{\par\vskip\dimexpr\sphinxtablepre\relax + \spx@inframedtrue % message to sphinxheavybox + }% +\let\sphinxattableend\sphinxatlongtableend +% This is used by tabular and tabulary templates +\newcommand*\sphinxcapstartof[1]{% + \vskip\parskip + \vbox{}% force baselineskip for good positioning by capstart of hyperanchor + % hyperref puts the anchor 6pt above this baseline; in case of caption + % this baseline will be \ht\strutbox above first baseline of caption + \def\@captype{#1}% + \capstart +% move back vertically, as tabular (or its caption) will compensate + \vskip-\baselineskip\vskip-\parskip +}% +\def\sphinxthecaptionisattop{% locate it after \sphinxcapstartof + \spx@ifcaptionpackage + {\caption@setposition{t}% + \vskip\baselineskip\vskip\parskip % undo those from \sphinxcapstartof + \vskip-\belowcaptionskip % anticipate caption package skip + % caption package uses a \vbox, not a \vtop, so "single line" case + % gives different result from "multi-line" without this: + \nointerlineskip + }% + {}% +}% +\def\sphinxthecaptionisatbottom{% (not finalized; for template usage) + \spx@ifcaptionpackage{\caption@setposition{b}}{}% +}% +% The aim of \sphinxcaption is to apply to tabular(y) the maximal width +% of caption as done by longtable +\def\sphinxtablecapwidth{\LTcapwidth}% +\newcommand\sphinxcaption{\@dblarg\spx@caption}% +\long\def\spx@caption[#1]#2{% + \noindent\hb@xt@\linewidth{\hss + \vtop{\@tempdima\dimexpr\sphinxtablecapwidth\relax +% don't exceed linewidth for the caption width + \ifdim\@tempdima>\linewidth\hsize\linewidth\else\hsize\@tempdima\fi +% longtable ignores \abovecaptionskip/\belowcaptionskip, so do the same here + \abovecaptionskip\sphinxabovecaptionskip % \z@skip + \belowcaptionskip\sphinxbelowcaptionskip % \z@skip + \caption[{#1}]% + {\strut\ignorespaces#2\ifhmode\unskip\@finalstrut\strutbox\fi}% + }\hss}% + \par\prevdepth\dp\strutbox +}% +\def\sphinxabovecaptionskip{\z@skip}% Do not use! Flagged for removal +\def\sphinxbelowcaptionskip{\z@skip}% Do not use! Flagged for removal +% This wrapper of \abovecaptionskip is used in sphinxVerbatim for top +% caption, and with another value in sphinxVerbatimintable +% TODO: To unify space above caption of a code-block with the one above +% caption of a table/longtable, \abovecaptionskip must not be used +% This auxiliary will get renamed and receive a different meaning +% in future. +\def\spx@abovecaptionskip{\abovecaptionskip}% +% Achieve \sphinxbelowcaptionspace below a caption located above a tabular +% or a tabulary +\newcommand\sphinxaftertopcaption +{% + \spx@ifcaptionpackage + {\par\prevdepth\dp\strutbox\nobreak\vskip-\abovecaptionskip}{\nobreak}% + \vskip\dimexpr\sphinxbelowcaptionspace\relax + \vskip-\baselineskip\vskip-\parskip +}% +% varwidth is crucial for our handling of general contents in merged cells +\RequirePackage{varwidth} +% but addition of a compatibility patch with hyperref is needed +% (tested with varwidth v 0.92 Mar 2009) +\AtBeginDocument {% + \let\@@vwid@Hy@raisedlink\Hy@raisedlink + \long\def\@vwid@Hy@raisedlink#1{\@vwid@wrap{\@@vwid@Hy@raisedlink{#1}}}% + \edef\@vwid@setup{% + \let\noexpand\Hy@raisedlink\noexpand\@vwid@Hy@raisedlink % HYPERREF ! + \unexpanded\expandafter{\@vwid@setup}}% +}% + +% NOTA BENE: since the multicolumn and multirow code was written Sphinx +% decided to prefix non public internal macros by \spx@ and in fact all +% such macros here should now be prefixed by \spx@table@, but doing the +% update is delayed to later. (written at 5.3.0) + +%%%%%%%%%%%%%%%%%%%%% +% --- MULTICOLUMN --- +% standard LaTeX's \multicolumn +% 1. does not allow verbatim contents, +% 2. interacts very poorly with tabulary. +% +% It is needed to write own macros for Sphinx: to allow code-blocks in merged +% cells rendered by tabular/longtable, and to allow multi-column cells with +% paragraphs to be taken into account sanely by tabulary algorithm for column +% widths. +% +% This requires quite a bit of hacking. First, in Sphinx, the multi-column +% contents will *always* be wrapped in a varwidth environment. The issue +% becomes to pass it the correct target width. We must trick tabulary into +% believing the multicolumn is simply separate columns, else tabulary does not +% incorporate the contents in its algorithm. But then we must clear the +% vertical rules... +% +% configuration of tabulary +\setlength{\tymin}{3\fontcharwd\font`0 }% minimal width of "squeezed" columns +\setlength{\tymax}{10000pt}% allow enough room for paragraphs to "compete" +% we need access to tabulary's final computed width. \@tempdima is too volatile +% to hope it has kept tabulary's value when \sphinxcolwidth needs it. +\newdimen\sphinx@TY@tablewidth +\def\tabulary{% + \def\TY@final{\sphinx@TY@tablewidth\@tempdima\tabular}% + \let\endTY@final\endtabular + \TY@tabular}% +% next hack is needed only if user has set latex_use_latex_multicolumn to True: +% it fixes tabulary's bug with \multicolumn defined "short" in first pass. (if +% upstream tabulary adds a \long, our extra one causes no harm) +\def\sphinx@tempa #1\def\multicolumn#2#3#4#5#6#7#8#9\sphinx@tempa + {\def\TY@tab{#1\long\def\multicolumn####1####2####3{\multispan####1\relax}#9}}% +\expandafter\sphinx@tempa\TY@tab\sphinx@tempa +% +% TN. 1: as \omit is never executed, Sphinx multicolumn does not need to worry +% like standard multicolumn about |l| vs l|. On the other hand it assumes +% columns are separated by a | ... (if not it will add extraneous +% \arrayrulewidth space for each column separation in its estimate of available +% width). +% +% Update at 5.3.0: code uses \spx@arrayrulewidth which is kept in sync with the +% table column specification (aka preamble): +% - no | in preamble: \spx@arrayrulewidth -> \z@ +% - at least a | in the preamble: \spx@arrayrulewidth -> \arrayrulewidth +% This is used for computation of merged cells widths. Mixed preambles using +% at least a | but not using it for all columns (as can be obtained via the +% tabularcolumns directive) may cause some merged cells contents to be slightly +% shifted to the left as they assume merged columns are | separated where in +% fact they perhaps are not. +% +% TN. 1b: as Sphinx multicolumn uses neither \omit nor \span, it can not +% (easily) get rid of extra macros from >{...} or <{...} between columns. At +% least, it has been made compatible with colortbl's \columncolor. +% +% TN. 2: tabulary's second pass is handled like tabular/longtable's single +% pass, with the difference that we hacked \TY@final to set in +% \sphinx@TY@tablewidth the final target width as computed by tabulary. This is +% needed only to handle columns with a "horizontal" specifier: "p" type columns +% (inclusive of tabulary's LJRC) holds the target column width in the +% \linewidth dimension. +% +% TN. 3: use of \begin{sphinxmulticolumn}...\end{sphinxmulticolumn} mark-up +% would need some hacking around the fact that groups can not span across table +% cells (the code does inserts & tokens, see TN1b). It was decided to keep it +% simple with \sphinxstartmulticolumn...\sphinxstopmulticolumn. +% +% MEMO about nesting: if sphinxmulticolumn is encountered in a nested tabular +% inside a tabulary it will think to be at top level in the tabulary. But +% Sphinx generates no nested tables, and if some LaTeX macro uses internally a +% tabular this will not have a \sphinxstartmulticolumn within it! +% +% 5.3.0 adds a check for multirow as single-row multi-column will allow a row +% colour but multi-row multi-column should not. +% Attention that this assumes \sphinxstartmulticolumn is always followed +% in latex mark-up either by \sphinxmultirow or \begin (from \begin{varwidth}). +\def\sphinxstartmulticolumn#1#2{% + \ifx\sphinxmultirow#2% + \gdef\spx@table@hackCT@inmergedcell{\spx@table@hackCT@nocolor}% + \else + \global\let\spx@table@hackCT@inmergedcell\spx@@table@hackCT@inmergedcell + \fi + \sphinx@startmulticolumn{#1}#2% +}% +\def\sphinx@startmulticolumn{% + \ifx\equation$% $ tabulary's first pass + \expandafter\sphinx@TYI@start@multicolumn + \else % either not tabulary or tabulary's second pass + \expandafter\sphinx@start@multicolumn + \fi +}% +\def\sphinxstopmulticolumn{% + \ifx\equation$% $ tabulary's first pass + \expandafter\sphinx@TYI@stop@multicolumn + \else % either not tabulary or tabulary's second pass + \ignorespaces + \fi +}% +\def\sphinx@TYI@start@multicolumn#1{% + % use \gdef always to avoid stack space build up + \gdef\sphinx@tempa{#1}\begingroup\setbox\z@\hbox\bgroup +}% +\def\sphinx@TYI@stop@multicolumn{\egroup % varwidth was used with \tymax + \xdef\sphinx@tempb{\the\dimexpr\wd\z@/\sphinx@tempa}% per column width + \endgroup + \expandafter\sphinx@TYI@multispan\expandafter{\sphinx@tempa}% +}% +\def\sphinx@TYI@multispan #1{% + \kern\sphinx@tempb\ignorespaces % the per column occupied width + \ifnum#1>\@ne % repeat, taking into account subtleties of TeX's & ... + \expandafter\sphinx@TYI@multispan@next\expandafter{\the\numexpr#1-\@ne\expandafter}% + \fi +}% +\def\sphinx@TYI@multispan@next{&\relax\sphinx@TYI@multispan}% +% +% Now the branch handling either the second pass of tabulary or the single pass +% of tabular/longtable. This is the delicate part where we gather the +% dimensions from the p columns either set-up by tabulary or by user p column +% or Sphinx \X, \Y columns. The difficulty is that to get the said width, the +% template must be inserted (other hacks would be horribly complicated except +% if we rewrote crucial parts of LaTeX's \@array !) and we can not do +% \omit\span like standard \multicolumn's easy approach. Thus we must cancel +% the \vrule separators. Also, perhaps the column specifier is of the l, c, r +% type, then we attempt an ad hoc rescue to give varwidth a reasonable target +% width. +\def\sphinx@start@multicolumn#1{% + \gdef\sphinx@multiwidth{0pt}\gdef\sphinx@tempa{#1}\sphinx@multispan{#1}% +}% +\def\sphinx@multispan #1{% + \ifnum#1=\@ne\expandafter\sphinx@multispan@end + \else\expandafter\sphinx@multispan@next + \fi {#1}% +}% +\def\sphinx@multispan@next #1{% + % trick to recognize L, C, R, J or p, m, b type columns + \ifdim\baselineskip>\z@ + \gdef\sphinx@tempb{\linewidth}% + \else + % if in an l, r, c type column, try and hope for the best + \xdef\sphinx@tempb{\the\dimexpr(\ifx\TY@final\@undefined\linewidth\else + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% + \fi + \noindent\kern\sphinx@tempb\relax + \xdef\sphinx@multiwidth + {\the\dimexpr\sphinx@multiwidth+\sphinx@tempb+\tw@\tabcolsep+\spx@arrayrulewidth}% + \spx@table@hackCT@fixcolorpanel + % silence a | column separator in our merged cell + \spx@table@hackCT@inhibitvline + % prevent column colours to interfere with our multi-column but allow row + % colour (we can't obey a \cellcolor as it has not be seen yet at this stage) + \spx@table@hackCT@inmergedcell&\relax + % repeat + \expandafter\sphinx@multispan\expandafter{\the\numexpr#1-\@ne}% +}% +\def\sphinx@multispan@end#1{% + % first, trace back our steps horizontally + \noindent\kern-\dimexpr\sphinx@multiwidth\relax + % and now we set the final computed width for the varwidth environment + \ifdim\baselineskip>\z@ + \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+\linewidth}% + \else + \xdef\sphinx@multiwidth{\the\dimexpr\sphinx@multiwidth+ + (\ifx\TY@final\@undefined\linewidth\else + \sphinx@TY@tablewidth\fi-\spx@arrayrulewidth)/\sphinx@tempa + -\tw@\tabcolsep-\spx@arrayrulewidth\relax}% + \fi + % last cell of the multi-column + \aftergroup\spx@table@hackCT@fixcolorpanel + \aftergroup\spx@table@hackCT@inmergedcell +}% +\newcommand*\sphinxcolwidth[2]{% + % this dimension will always be used for varwidth, and serves as maximum + % width when cells are merged either via multirow or multicolumn or both, + % as always their contents is wrapped in varwidth environment. + \ifnum#1>\@ne % multi-column (and possibly also multi-row) + % we wrote our own multicolumn code especially to handle that (and allow + % verbatim contents) + \ifx\equation$%$ + \tymax % first pass of tabulary (cf MEMO above regarding nesting) + \else % the \@gobble thing is for compatibility with standard \multicolumn + \sphinx@multiwidth\@gobble{#1/#2}% + \fi + \else % single column multirow + \ifx\TY@final\@undefined % not a tabulary. + \ifdim\baselineskip>\z@ + % in a p{..} type column, \linewidth is the target box width + \linewidth + \else + % l, c, r columns. Do our best. + \dimexpr(\linewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax + \fi + \else % in tabulary + \ifx\equation$%$% first pass + \tymax % it is set to a big value so that paragraphs can express themselves + \else + % second pass. + \ifdim\baselineskip>\z@ + \linewidth % in a L, R, C, J column or a p, \X, \Y ... + \else + % we have hacked \TY@final to put in \sphinx@TY@tablewidth the table width + \dimexpr(\sphinx@TY@tablewidth-\spx@arrayrulewidth)/#2- + \tw@\tabcolsep-\spx@arrayrulewidth\relax + \fi + \fi + \fi + \fi +}% +% fallback default in case user has set latex_use_latex_multicolumn to True: +% \sphinxcolwidth will use this only inside LaTeX's standard \multicolumn +\def\sphinx@multiwidth #1#2{\dimexpr % #1 to gobble the \@gobble (!) + (\ifx\TY@final\@undefined\linewidth\else\sphinx@TY@tablewidth\fi + -\spx@arrayrulewidth)*#2-\tw@\tabcolsep-\spx@arrayrulewidth\relax}% + +% \spx@table@hackCT@inhibitvline +% packages like colortbl add group levels, we need to "climb back up" to be +% able to hack the \vline and also the colortbl inserted tokens. The hack +% sets the \arrayrulewidth to \z@ to inhibit a | separator at right end +% of the cell, if present (our code does not use \omit so can not avoid the +% \vline insertion, but setting its width to zero makes it do nothing). +% Some subtlety with colour panels must be taken care of. +\def\spx@table@hackCT@inhibitvline{\ifnum\currentgrouptype=6\relax + \kern\spx@arrayrulewidth % will be compensated by extra colour panel left overhang + \arrayrulewidth\z@% trick to inhibit the {\vrule width \arrayrulewidth} + \else\aftergroup\spx@table@hackCT@inhibitvline\fi}% + +% hacking around colour matters +% Sphinx 1.6 comment: +% It turns out \CT@row@color is not expanded contrarily to \CT@column@color +% during LaTeX+colortbl preamble preparation, hence it would be possible for +% \CT@setup to discard only the column color and choose to obey or not +% row color and cell color. It would even be possible to propagate cell color +% to row color for the duration of the Sphinx multicolumn... the (provisional?) +% choice has been made to cancel the colortbl colours for the multicolumn +% duration. +% Sphinx 5.3.0 comment: +% - colortbl has no mechanism to disable colour background in a given cell: +% \cellcolor triggers one more \color, but has no possibility to revert +% a previously emitted \color, only to override it via an additional \color +% - prior to 5.3.0, Sphinx did not officially support colour in tables, +% but it did have a mechanism to protect merged cells from being partly +% covered by colour panels at various places. At 5.3.0 this mechanism +% is relaxed a bit to allow row colour for a single-row merged cell. +% +% fixcolorpanel +\def\spx@table@hackCT@fixcolorpanel{\ifnum\currentgrouptype=6\relax + \edef\spx@table@leftcolorpanelextra + % \edef as \arrayrulewidth will be set to \z@ next, + % hence also \spx@arrayrulewidth... + {\sphinxcolorpanelextraoverhang+\the\spx@arrayrulewidth}% + \else\aftergroup\spx@table@hackCT@fixcolorpanel\fi}% +% +% inmergedcell +% \spx@table@hackCT@inmergedcell will be locally set to either this +% \spx@@table@hackCT@inmergedcell or to \spx@table@hackCT@nocolor +% "\let\spx@original@CT@setup\CT@setup" is done after loading colortbl +\def\spx@@table@hackCT@inmergedcell{\ifnum\currentgrouptype=6\relax + \let\CT@setup\spx@CT@setup@inmergedcell + \else\aftergroup\spx@@table@hackCT@inmergedcell\fi +}% +\newif\ifspx@table@inmergedcell +\def\spx@CT@setup@inmergedcell #1\endgroup{% + % - obey only row color and disable effect of \sphinxcolorblend + % - turn on the inmergedcell boolean to signal to \CT@row@color + \spx@original@CT@setup + \spx@table@inmergedcelltrue % needed by \CT@row@color + % deactivate effect of \sphinxcolorblend if it happened at all + \ifdefined\blendcolors\blendcolors{}\fi + \CT@row@color + \CT@do@color + \global\let\CT@cell@color\relax + \endgroup +}% +% +% nocolor +\def\spx@table@hackCT@nocolor{\ifnum\currentgrouptype=6\relax +% sadly \CT@column@color is possibly already expanded so we can't +% simply do \let\CT@column@color\relax etc... +% admittedly we could perhaps hack \CT@color but well + \let\CT@setup\spx@CT@setup@nocolor + \else\aftergroup\spx@table@hackCT@nocolor\fi +} +\def\spx@CT@setup@nocolor#1\endgroup{% + \global\let\CT@cell@color\relax + % the above fix was added at 5.3.0 + % formerly a \cellcolor added by a raw latex directive in the merged cell + % would have caused colour to apply to the *next* cell after the merged + % one; we don't support \cellcolor from merged cells contents anyhow. + \endgroup} +% +% norowcolor +\def\spx@table@hackCT@norowcolor{% +% a bit easier although merged cells complicate the matter as they do need +% to keep the rowcolor; and we can't know yet if we are in a merged cell + \ifnum\currentgrouptype=6\relax + \ifx\CT@row@color\relax + \else + \let\spx@saved@CT@row@color\CT@row@color + \def\CT@row@color{% + \ifspx@table@inmergedcell\expandafter\spx@saved@CT@row@color\fi + }% + \fi + \else\aftergroup\spx@table@hackCT@norowcolor\fi +} +% +% \sphinxcolorblend +\def\spx@table@hackCT@colorblend{% + \ifnum\currentgrouptype=6\relax + \expandafter\blendcolors\spx@colorblendparam + % merged cells will do a \blendcolors{} to cancel the effet + % we can not know here yet if in merged cell as the boolean + % \ifspx@table@inmergedcell is not yet updated + \else + \aftergroup\spx@table@hackCT@colorblend + \fi +} +\def\sphinxcolorblend#1{\gdef\spx@colorblendparam{{#1}}\spx@table@hackCT@colorblend} + + +%%%%%%%%%%%%%%%%%% +% --- MULTIROW --- +% standard \multirow +% 1. does not allow verbatim contents, +% 2. does not allow blank lines in its argument, +% 3. its * specifier means to typeset "horizontally" which is very +% bad for paragraph content. 2016 version has = specifier but it +% must be used with p type columns only, else results are bad, +% 4. it requires manual intervention if the contents is too long to fit +% in the asked-for number of rows. +% 5. colour panels (either from \rowcolor or \columncolor) will hide +% the bottom part of multirow text, hence manual tuning is needed +% to put the multirow insertion at the _bottom_. +% +% The Sphinx solution consists in always having contents wrapped +% in a varwidth environment so that it makes sense to estimate how many +% lines it will occupy, and then ensure by insertion of suitable struts +% that the table rows have the needed height. The needed mark-up is done +% by LaTeX writer, which has its own id for the merged cells. +% +% The colour issue is "solved" by clearing colour panels in all cells, +% whether or not the multirow is single-column or multi-column. +% +% MEMO at 5.3.0: to allow a multirow cell in a single column to react to +% \columncolor correctly, it seems only way is that the contents +% are inserted by bottom cell (this is mentioned in multirow.sty doc, too). +% Sphinx could at Python level "move" the contents to that cell. But the +% mechanism used here via \sphinxtablestrut to enlarge rows to make room for +% the contents if needed becomes more challenging yet, because \sphinxtablestrut +% mark-up will be parsed by TeX *before* it sees the contents of the merged +% cell.. So it seems the best way would be to actually store the contents into +% some owned-by-Sphinx box storage which needs to be globally allocated to +% that usage ; then we need multiple such boxes, say at least 5 to cover +% 99% or use case. Or perhaps some trick with storing in a \vbox and recovering +% via some \vsplit but this becomes complicated... perhaps in future. +% +% In passing we obtain baseline alignments across rows (only if +% \arraystretch is 1, as LaTeX's does not obey \arraystretch in "p" +% multi-line contents, only first and last line...) +% +% TODO: examine the situation with \arraystretch > 1. The \extrarowheight +% is hopeless for multirow anyhow, it makes baseline alignment strictly +% impossible. +\newcommand\sphinxmultirow[2]{\begingroup + % #1 = nb of spanned rows, #2 = Sphinx id of "cell", #3 = contents + % but let's fetch #3 in a way allowing verbatim contents ! + \def\sphinx@nbofrows{#1}\def\sphinx@cellid{#2}% + \afterassignment\sphinx@multirow\let\next= +}% +\def\sphinx@multirow {% + \setbox\z@\hbox\bgroup\aftergroup\sphinx@@multirow\strut +}% +\def\sphinx@@multirow {% +% MEMO: we could check status of \CT@cell@color here, but unfortunately we +% can't know the exact height which will be covered by the cells in total +% (it may be more than our \box\z@ dimensions). We could use an \fcolorbox +% wrapper on \box\z@ but this will not extend precisely to the bottom rule. +% +% Only solution if we want to obey a raw \cellcolor, or a \columncolor, seems +% to delay unboxing the gathered contents as part of the bottom row with +% a suitable vertical adjustment... +% + % The contents, which is a varwidth environment, has been captured in + % \box0 (a \hbox). + % We have with \sphinx@cellid an assigned unique id. The goal is to give + % about the same height to all the involved rows. + % For this Sphinx will insert a \sphinxtablestrut{cell_id} mark-up + % in LaTeX file and the expansion of the latter will do the suitable thing. + \dimen@\dp\z@ + \dimen\tw@\ht\@arstrutbox + \advance\dimen@\dimen\tw@ + \advance\dimen\tw@\dp\@arstrutbox + \count@=\dimen@ % type conversion dim -> int + \count\tw@=\dimen\tw@ + \divide\count@\count\tw@ % TeX division truncates + \advance\dimen@-\count@\dimen\tw@ + % 1300sp is about 0.02pt. For comparison a rule default width is 0.4pt. + % (note that if \count@ holds 0, surely \dimen@>1300sp) + \ifdim\dimen@>1300sp \advance\count@\@ne \fi + % now \count@ holds the count L of needed "lines" + % and \sphinx@nbofrows holds the number N of rows + % we have L >= 1 and N >= 1 + % if L is a multiple of N, ... clear what to do ! + % else write L = qN + r, 1 <= r < N and we will + % arrange for each row to have enough space for: + % q+1 "lines" in each of the first r rows + % q "lines" in each of the (N-r) bottom rows + % for a total of (q+1) * r + q * (N-r) = q * N + r = L + % It is possible that q == 0. + \count\tw@\count@ + % the TeX division truncates + \divide\count\tw@\sphinx@nbofrows\relax + \count4\count\tw@ % q + \multiply\count\tw@\sphinx@nbofrows\relax + \advance\count@-\count\tw@ % r + \expandafter\xdef\csname sphinx@tablestrut_\sphinx@cellid\endcsname + {\noexpand\sphinx@tablestrut{\the\count4}{\the\count@}{\sphinx@cellid}}% + \dp\z@\z@ + % this will use the real height if it is >\ht\@arstrutbox + \sphinxtablestrut{\sphinx@cellid}\box\z@ + \endgroup % group was opened in \sphinxmultirow +}% +\newcommand*\sphinxtablestrut[1]{% + % #1 is a "cell_id", i.e. the id of a merged group of table cells + \csname sphinx@tablestrut_#1\endcsname +}% +% LaTeX typesets the table row by row, hence each execution can do +% an update for the next row. +\newcommand*\sphinx@tablestrut[3]{\begingroup + % #1 = q, #2 = (initially) r, #3 = cell_id, q+1 lines in first r rows + % if #2 = 0, create space for max(q,1) table lines + % if #2 > 0, create space for q+1 lines and decrement #2 + \leavevmode + \count@#1\relax + \ifnum#2=\z@ + \ifnum\count@=\z@\count@\@ne\fi + \else + % next row will be with a #2 decremented by one + \expandafter\xdef\csname sphinx@tablestrut_#3\endcsname + {\noexpand\sphinx@tablestrut{#1}{\the\numexpr#2-\@ne}{#3}}% + \advance\count@\@ne + \fi + \vrule\@height\ht\@arstrutbox + \@depth\dimexpr\count@\ht\@arstrutbox+\count@\dp\@arstrutbox-\ht\@arstrutbox\relax + \@width\z@ + \endgroup + % we need this to avoid colour panels hiding bottom parts of multirow text + \spx@table@hackCT@nocolor +}% + +%%%%%%%%%%%%%%%%%% +% --- STYLING --- +% + +% +% Support for colour in table +% +% Core LaTeX package (very old, part of texlive-latex-base on Debian distr.) +% providing \columncolor, \rowcolor, \cellcolor and \arrayrulecolor. +\RequirePackage{colortbl} +\let\spx@original@CT@setup\CT@setup + +% LaTeX's \cline has **strong** deficiencies +% ****************************************** +% We work around them via an added \sphinxfixclines{number of columns} in the +% table mark-up, and also extra mark-up \sphinxvlinecrossing{col no} for +% crossings not contiguous to any cline. To fix the gap at left extremity of a +% \cline, we redefine the core LaTeX \c@line because this avoids adjoining a +% small square with potential PDF viewer anti-aliasing issues. We waited +% after loading colortbl because it also redefines \c@line for it to obey the +% colour set by \arrayrulecolor. +% MEMO: booktabs package does *not* redefine \@cline so we are safe here. +\def\@cline#1-#2\@nil{% + \omit + \@multicnt#1% + \advance\@multispan\m@ne + \ifnum\@multicnt=\@ne\@firstofone{&\omit}\fi + \@multicnt#2% + \advance\@multicnt-#1% + \advance\@multispan\@ne + {\CT@arc@ +% start of Sphinx modification + \ifnum#1>\@ne\kern-\spx@arrayrulewidth\fi% fix gap at join with vertical lines +% end of Sphinx modification +% Comments: +% +% If we had the information whether the previous column ended with a | or +% not, we could decide what to do here. Alternatively the mark-up could +% use either original \cline or the one modified as here depending on case. +% One wonders why LaTeX does not provide itself the alternative as a +% complement to \cline, to use on case by case basis. +% Here we handle both at same time via using the \spx@arrayrulewidth which +% will be \z@ if no | at all so will induce here nothing. +% +% As a result Sphinx basically supports well only tables having either all +% columns |-separated, or no | at all, as it uses \spx@arrayrrulewidth in +% all columns (here and in multicolumn code). +% +% We also considered a method not modifying \c@line but it requires too +% much extra mark-up from Python LaTeX writer and/or extra LaTeX coding. +% back to LaTeX+colortbl code + \leaders\hrule\@height\arrayrulewidth\hfill}% + \cr +% the last one will need to be compensated, this is job of \sphinxclines + \noalign{\vskip-\arrayrulewidth}% +} +\def\spx@table@fixvlinejoin{% + {\CT@arc@ % this is the color command set up by \arrayrulecolor + \vrule\@height\arrayrulewidth +% side remark: LaTeX has only a single \arrayrulewidth for all kinds +% for cell borders in table, horizontal or vertical... + \@depth\z@ + \@width\spx@arrayrulewidth + }% +} +% Sphinx LaTeX writer issues one such for each vertical line separating two +% contiguous multirow cells; i.e. those crossings which can are not already +% taken care of by our modified at left extremity \cline. +% One could imagine a more \...crossingS (plural) receiving a comma delimited +% list, which would simplify the mark-up but this would complexify both the +% Python and the LaTeX coding. +\def\sphinxtablevlinecrossing#1{% + \sphinxtabledecrementrownum + \omit + \@multispan{#1}% + \hfill + \spx@table@fixvlinejoin + \cr + \noalign{\vskip-\arrayrulewidth}% +} +% This "fixclines" is also needed if no \sphinxcline emitted and is useful +% even in extreme case with no \sphinxvlinecrossing either, to give correct +% height to multirow extending across all table width assuming other rows are +% separated generally by an \hline, so as to keep coherent line spacing. +% +% It is designed to work ok even if no | separators are in the table (because +% \spx@table@fixvlinejoin uses \spx@arrayrulewidth which is \z@ in that case). +\def\sphinxtablefixclines#1{% #1 is the number of columns of the table + \sphinxtabledecrementrownum + \omit + \spx@table@fixvlinejoin% unneeded if first \cline started at column 1 but does + % not hurt; fills small gap at left-bordered table + \@multispan{#1}% + \hfill + \spx@table@fixvlinejoin% fill small gap at right-bordered table + \cr + % this final one does NO \vskip-\arrayrulewidth... that's the whole point +} +%%%% end of \cline workarounds + +% +% - passing option "table" to xcolor also loads colortbl but we needed to +% load color or xcolor prior to the handling of the options +% +% - the \rowcolors command from [table]{xcolor} has various problems: +% +% * it is rigid and does not out-of-the-box allow a more complex scheme +% such as colorA+colorB+colorC+colorB+colorC+colorB+colorC... suitable to +% distinguish a header row. +% +% * its code does not export the used colour, an information which we may +% need for example to colourize the rule via \arrayrulecolor in the +% appropriate manner, for example to colourize the booktabs induced vertical +% whitespace to avoid gaps (if one wants to). +% +% * incompatibility with tabulary: the output depends on parity of total +% number of rows! +% +% * problems with longtable: the caption will receive a background colour +% panel, if we do not deactivate the \rowcolors action during definition of +% the headers and footers; this requires extra mark-up. Besides if we +% deactivate using \hiderowcolors during header and footer formation, the +% parity of the body rows is shifted, \rownum is even, not odd, at first body +% row. And setting \rownum at start of first body row is too late for +% influencing the colour. +% +% * it has a global impact and must be reset at each table. We can not +% issue it only once and it provides no public interface (without @) to +% cancel its effect conveniently (\hiderowcolors can only be used from +% *inside* a table.) +% +% * its core mechanism which increments the row count is triggered +% if a \cline is encountered... so this offsets the alternating colours... +% ... or not if there are two \cline's in the row... +% (as we will use same mechanism we have to correct this increment). +% +% So we need our own code. + +% Provide \rownum and rownum LaTeX counter (code copied from colortbl v1.0f) +\ltx@ifundefined{rownum}{% + \ltx@ifundefined{c@rownum}% + {\newcount\rownum\let\c@rownum\rownum}% + {\let\rownum\c@rownum}% + }% +{\let\c@rownum\rownum} +\providecommand\therownum{\arabic{rownum}} + +% extra overhang for color panels to avoid visual artifacts in pdf viewers +% (particularly if borderless) +\def\sphinxcolorpanelextraoverhang{0.1pt} +\def\spx@table@leftcolorpanelextra {\sphinxcolorpanelextraoverhang} +\def\spx@table@rightcolorpanelextra{\sphinxcolorpanelextraoverhang} +% the macro to which \CT@row@color will be set for coloured rows, serves both +% in header and body, the colours must have been defined at time of use +\def\spx@table@CT@row@color{\ifspx@table@inmergedcell + \CT@color{sphinxTableMergeColor}% + \else + \CT@color{sphinxTableRowColor}% + \fi + \@tempdimb\dimexpr\col@sep+\spx@table@leftcolorpanelextra\relax + \@tempdimc\dimexpr\col@sep+\spx@table@rightcolorpanelextra\relax + }% +% used by itself this will influence a single row if \CT@everycr is the +% colortbl one, to influences all rows the \CT@everycr must be modified (see +% below) +\def\sphinxrowcolorON {\global\let\CT@row@color\spx@table@CT@row@color}% +% this one turns off row colours until the next \sphinxrowcolorON +\def\sphinxrowcolorOFF{\global\let\CT@row@color\relax}% +% this one inhibits the row colour in one cell only (can be used as +% >{\sphinxnorowcolor} for turning off row colours in a given column) +\def\sphinxnorowcolor{\spx@table@hackCT@norowcolor}% + +% \sphinxtoprule (or rather \sphinxtabletoprulehook) will be modified by +% the colorrows class to execute this one: +\def\spx@table@@toprule@rowcolorON{% + \noalign{% + % Because of tabulary 2-pass system, the colour set-up at end of table + % would contaminate the header colours at start of table, so must reset + % them here. We want all header rows to obey same colours, so we don't + % use original \CT@everycr which sets \CT@row@color to \relax. + \global\CT@everycr{\the\everycr}% + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorHeader}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorHeader}% + \sphinxrowcolorON + }% +}% + +% \sphinxtableatstartofbodyhook will be modified by colorrows class to +% execute this one; it starts the alternating colours and triggers increment +% or \rownum count at each new row (the xcolor base method for \rowcolors) +\def\spx@table@@startbodycolorrows{% + \noalign{% + \global\CT@everycr{% Nota Bene: in a longtable with \hline the \everycr is + % done two extra times! but 2 is even, so this is ok + \noalign{\global\advance\rownum\@ne % the xcolor \rowcolors base trick +% MEMO: colortbl \CT@row@color is expanded *after* the cell contents have been +% gathered and measured, so it can't be used to expose e.g. the colour to the +% cell contents macro code. Of course if it is known how the colour is chosen +% the procedure could be done from inside the cell. Simpler to expose the colour +% in a public name sphinxTableRowColor at start of the row in this \noalign. + \sphinxSwitchCaseRowColor\rownum + }% + \the\everycr + }% + \global\rownum\@ne % is done from inside table so ok with tabulary two passes + \sphinxSwitchCaseRowColor\rownum % set up color for the first body row + \sphinxrowcolorON % has been done from \sphinxtoprule location but let's do + % it again in case \sphinxtabletoprulehook has been used + % to inhibit colours in the header rows + }% end of noalign contents +} +% set the colours according to row parity; a priori #1 is \rownum, but +% the macro has been designed to be usable in user level added code +\def\sphinxSwitchCaseRowColor#1{% + \ifodd#1\relax + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorOdd}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorOdd}% + \else + \global\sphinxcolorlet{sphinxTableRowColor}{sphinxTableRowColorEven}% + \global\sphinxcolorlet{sphinxTableMergeColor}{\sphinxTableMergeColorEven}% + \fi +} + +% each \cline or \cmidrule (booktabs) consumes one \cr, offsetting the \rownum +% parity; so this macro serves to compensate and must be added to each such +% \cline or \cmidrule (see below) +\def\spx@table@@decrementrownum{\noalign{\global\advance\rownum\m@ne}} +\let\sphinxtabledecrementrownum\@empty + +% \sphinxtableafterendhook will be modified by colorrows class to execute +% this after the table +\def\spx@table@resetcolortbl{% + \sphinxrowcolorOFF + \spx@table@reset@CTeverycr +% this last bit is done in order for the \sphinxbottomrule from the "foot" +% longtable template to be able to use same code as the \sphinxbottomrule +% at end of table body; see \sphinxbooktabsspecialbottomrule code + \global\rownum\z@ +} +\def\spx@table@reset@CTeverycr{% +% we should probably be more cautious and not hard-code here the colortbl +% set-up; so the macro is defined without @ to fac + \global\CT@everycr{\noalign{\global\let\CT@row@color\relax}\the\everycr}% +} + +% At last the style macros \sphinxthistablewithstandardstyle etc... + +% They are executed before the table environments in a scope limiting +% wrapper "savenotes" environment. +% +% 0) colour support is enacted via adding code to three hooks: +% - \sphinxtabletoprulehook (implicit from \sphinxtoprule expansion) +% - \sphinxtableatstartofbodyhook (explicit from table templates) +% - \sphinxtableafterendhook (explicit from table templates) +% additionally special adjustment must be made in \sphinxcline +% +\def\sphinxtoprule{\spx@toprule\sphinxtabletoprulehook} +% \spx@toprule is what is defined by the standard, booktabs and borderless +% styles. +% The colorrows class will prepend \spx@table@toprule@rowcolorON into +% \sphinxtabletoprulehook which a priori is \@empty but can contain user added +% extra code, and is executed after \spx@toprule. +\let\sphinxtabletoprulehook \@empty +\let\sphinxtableatstartofbodyhook\@empty +\let\sphinxtableafterendhook \@empty +% +% 1) we manage these three hooks in a way allowing a custom user extra wrapper +% environment from a container class to use them as entry point for some +% custom code. The container code is done first, prior to table templates. +% So, the style macros will *prepend* the needed color-code to the existing +% custom user code, so the custom user code can override them. The custom +% user code should not redefine any of the 3 \sphinxtable...hook macros via a +% \global\def, but their contents can use \gdef. In fact they probably need +% to for the first two hooks which are executed from inside the table and +% a priori need their code to be in a \noalign which limits scope. +% +% 2) the table templates and LaTeX writer code make it so that only +% one of either +% \sphinxthistablewithcolorrowsstyle, +% or \sphinxthistablewithnocolorrowsstyle +% will be inserted explicitly depending on local :class: for table. +% The global 'colorrows' style in latex_table_style translates at bottom +% of this file into code for inserting \sphinxthistablewithcolorrowsstyle +% at end of \sphinxthistablewithglobalstyle. So it is impossible +% to have first \sphinxthistablewithnocolorrowsstyle, then +% \sphinxthistablewithcolorrowsstyle. Nevertheless we have written +% the code so that in this case colorrows would indeed activate (except +% if it was already executed before as it self-annihilates). + +% standard style +\def\sphinxthistablewithstandardstyle{% + % Those two are produced by the latex writer + \def\sphinxhline {\hline}% + % \sphinxtabledecrementrownum is a no-op which is redefined by colorrows + % to correct the \rownum increment induced by \cline in colorrows regime + \def\sphinxcline {\sphinxtabledecrementrownum\cline}% + % LaTeX's \cline needs fixing + \let\sphinxvlinecrossing\sphinxtablevlinecrossing + \let\sphinxfixclines \sphinxtablefixclines + % Those three are inserted by the table templates + \def\spx@toprule {\hline}% + \def\sphinxmidrule {\hline}% + \def\sphinxbottomrule {\hline}% + % Do not tamper with this internal + \def\spx@arrayrulewidth{\arrayrulewidth}% +} + +% booktabs style +% The \@xcmidrule patch below will do beyond its main stuff +% \sphinxadjustcmidrulebelowsep +% Indeed the poor booktabs spacing with \cmidrule (if \sphinxbooktabscmidrule +% defined below is overwritten to use it) is quite awful. Do +% \let\sphinxadjustcmidrulebelowsep\empty +% if you prefer booktabs defaults. +\def\sphinxadjustcmidrulebelowsep{\belowrulesep=\aboverulesep} +\AtBeginDocument{% patch booktabs to avoid extra vertical space from + % consecutive \sphinxcline, if defined to use \cmidrule + \ifdefined\@xcmidrule + \let\spx@original@@xcmidrule\@xcmidrule + \def\@xcmidrule{\sphinxadjustcmidrulebelowsep + % if we don't do that, two \sphinxcline in the same row + % will cause the second short rule to be shifted down + \ifx\@tempa\sphinxcline\let\@tempa\cmidrule\fi + \spx@original@@xcmidrule}% + \fi +} +% wrappers to allow customization, e.g. via a container class +% the top, mid, bottom definitions are in fact overwritten (later, below) +% byt more complex ones needed to handle booktabs+colorrows context +\def\sphinxbooktabstoprule {\toprule} +\def\sphinxbooktabsmidrule {\midrule} +\def\sphinxbooktabsbottomrule{\bottomrule} +% +\let\sphinxbooktabscmidrule \@gobble % i.e. draw no short rules at all! +% You can redefine this to use \cmidrule with various options, such +% as \cmidrule(lr), but: +% Attention, if you want this to use \cmidrule (or \cline) you must, +% if the table uses row colours, +% also include the \sphinxtabledecrementrownum token like e.g. this +% \def\sphinxbooktabscmidrule{\sphinxtabledecrementrownum\cmidrule(lr)} +% and it must be first due to internals of the \cmidrule usage of \futurelet. + +\def\sphinxthistablewithbooktabsstyle{% + \let\sphinxhline\@empty % there is no wrapper macro here so if you want to change that + % you will have to redefine \sphinxthistablewithbooktabsstyle + \def\sphinxcline {\sphinxbooktabscmidrule}% defaults to give \@gobble + \let\sphinxvlinecrossing\@gobble % no | in a booktabs-style table ! + \let\sphinxfixclines \@gobble % should not be used with booktabs + \cmidrule + \def\spx@toprule {\sphinxbooktabstoprule}% + \def\sphinxmidrule {\sphinxbooktabsmidrule}% + \def\sphinxbottomrule{\sphinxbooktabsbottomrule}% + \def\spx@arrayrulewidth{\z@}% +} +\AtBeginDocument{\@ifpackageloaded{booktabs}% + {}% + {\def\sphinxthistablewithbooktabsstyle{% + \PackageWarning{sphinx}{% +Add \string\usepackage{booktabs} to the preamble to allow\MessageBreak +local use of booktabs table style}% + \sphinxbuildwarning{booktabs}% + \sphinxthistablewithstandardstyle + }}% +}% + +% borderless style +\def\sphinxthistablewithborderlessstyle{% + \let\sphinxhline \@empty + \let\sphinxcline \@gobble + \let\sphinxvlinecrossing\@gobble + \let\sphinxfixclines \@gobble + \let\spx@toprule \@empty + \let\sphinxmidrule \@empty + \let\sphinxbottomrule \@empty + \def\spx@arrayrulewidth{\z@}% +}% + +% colorrows style +% +\let\sphinxifthistablewithcolorrowsTF\@secondoftwo +\def\sphinxthistablewithcolorrowsstyle{% + \let\sphinxifthistablewithcolorrowsTF\@firstoftwo +% this is defined to auto-silence itself (in the surrounding scope-limiting +% environment) after one execution ("colorrows" can never follow "nocolorrows") + \let\sphinxthistablewithcolorrowsstyle\@empty +% + \let\spx@table@toprule@rowcolorON \spx@table@@toprule@rowcolorON + \let\spx@table@startbodycolorrows \spx@table@@startbodycolorrows + \let\sphinxtabledecrementrownum \spx@table@@decrementrownum +% Is it the best choice to "prepend" to existing code there? + \spx@prepend\spx@table@toprule@rowcolorON\to\sphinxtabletoprulehook + \spx@prepend\spx@table@startbodycolorrows\to\sphinxtableatstartofbodyhook +% +% this one is not set to \@empty by nocolorrows, because it looks harmless +% to execute it always, as it simply resets to standard colortbl state after +% the table; so we don't need an @@ version for this one + \spx@prepend\spx@table@resetcolortbl\to\sphinxtableafterendhook +} +\def\spx@prepend#1\to#2{% attention about using this only with #2 "storage macro" + \toks@{#1}% + \toks@\expandafter\expandafter\expandafter{\expandafter\the\expandafter\toks@#2}% + \edef#2{\the\toks@}% +}% + +\def\sphinxthistablewithnocolorrowsstyle{% + \let\sphinxifthistablewithcolorrowsTF\@secondoftwo +% rather than trying to remove the code added by 'colorrows' style, we +% simply make it no-op, without even checking if really it was activated. + \let\spx@table@toprule@rowcolorON\@empty + \let\spx@table@startbodycolorrows\@empty + \let\sphinxtabledecrementrownum \@empty +% we don't worry about \sphinxtableafterendhook as the \spx@table@resetcolortbl +% done at end can not do harm; and we could also have not bothered with the +% \sphinxtabledecrementrownum as its \rownum decrement, if active, is harmless +% in non-colorrows context +} + +% (not so easy) implementation of the booktabscolorgaps option. This option +% defaults to true and is not officially documented, as already colorrows is +% only opt-in, so it is there only as a "turn-off" switch, but if nobody +% complains in next few months, it will probably be removed altogether at +% 6.0.0. The reason it exists is because of longtable aspeces described +% below. +% +% As it is used via \sphinxsetup booktabscolorgaps status is not known here +% and may change locally. So it must be implemented via delayed or +% conditional code. +% +% We do not know the order of execution of \sphinxthistablewithbooktabsstyle +% versus \sphinxthistablewithcolorrows: if booktabs is global option it +% will be executed first; but if colorrows is global option and not booktabs +% then colorrows will be executed first via \sphinxthistablewithglobalstyle +% +% Modifying things from locations such as \sphinxtabletoprulehook which are +% executed within the table is not convenient as it must use \global +% but then we would have to undo this after the table. +% +% So what we do is to prepare booktabs specific macros to incorporate +% a conditional to check the colorrows status. We must each time check +% both if colorrows is activated and if colorgaps is. We do this via +% macros without @ so they can be used easily in customization code. +% When and if booktabscolorgaps option is removed, we can then replace +% \sphinxifbooktabswithcolorgapsTF by \sphinxifthistablewithcolorrowsTF +\def\sphinxifbooktabswithcolorgapsTF{% + \if1\ifspx@opt@booktabscolorgaps + \sphinxifthistablewithcolorrowsTF{1}{0}% + \else0\fi + \expandafter\@firstoftwo + \else\expandafter\@secondoftwo + \fi +} +% as this is done without "@" it can be relatively easily be overwritten +% by user in customization code +\def\sphinxbooktabstoprule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialtoprule}% + {\toprule}% +}% +\def\sphinxbooktabscolorgapsoverhang{0.1pt}% avoid pixel/rounding effects +% auxiliary fork +\long\def\spx@table@crazyfork + #1\endfirsthead\endhead\sphinxtableatstartofbodyhook#2#3\@nil{#2} +% we fetch the next token to check if there is a header or not +% this is a bit fragile as it relies on the table templates +% and it assumes this token #1 is never braced... +% let's make this \long in case #1 is \par (should not be) +\long\def\sphinxbooktabsspecialtoprule\sphinxtabletoprulehook#1{% + \specialrule{\heavyrulewidth}{\abovetopsep}{\z@}% + % this macro contains colour init code (and defines sphinxTableRowColor) + \sphinxtabletoprulehook + % unfortunately colortbl provides no way to save/restore the + % \arrayrulecolor status, we have to code it ourselves + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ +% \@declaredcolor is not \long. Although #1 can probably never be \par with +% our templates, let's be cautious and not use the creazyfork inside the \color + \spx@table@crazyfork +% this crazy code checks if #1 is one of \endfirsthead, \endhead or +% \sphinxtableatstartofbodyhook, as criterion for table with no header + #1\endhead\sphinxtableatstartofbodyhook\@secondoftwo + \endfirsthead#1\sphinxtableatstartofbodyhook\@secondoftwo + \endfirsthead\endhead#1\@secondoftwo + \endfirsthead\endhead\sphinxtableatstartofbodyhook\@firstoftwo + \@nil + {\gdef\CT@arc@{\color{sphinxTableRowColor}}}% + {\gdef\CT@arc@{\color{sphinxTableRowColorOdd}}}% + }% end of \noalign + % \specialrule uses \noalign itself + \specialrule{\dimexpr\belowrulesep+\sphinxbooktabscolorgapsoverhang\relax}% + {\z@}{-\sphinxbooktabscolorgapsoverhang}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + #1% let's not forget to re-insert this #1 in token stream + % fortunately longtable's \endfirsthead/\endhead are not delimiters but + % are really tokens awaiting expansion... +}% +\def\sphinxbooktabsmidrule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialmidrule}% + {\midrule}% +}% +\def\sphinxbooktabsspecialmidrule{% + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ + \gdef\CT@arc@{\color{sphinxTableRowColor}}% this is RowColorHeader + }% + \specialrule{\dimexpr\aboverulesep+\sphinxbooktabscolorgapsoverhang\relax\relax}% + {-\sphinxbooktabscolorgapsoverhang}{\z@}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + \specialrule{\lightrulewidth}{\z@}{\z@}% + \noalign{\gdef\CT@arc@{\color{sphinxTableRowColorOdd}}}% + \specialrule{\dimexpr\belowrulesep+\sphinxbooktabscolorgapsoverhang\relax\relax}% + {\z@}{-\sphinxbooktabscolorgapsoverhang}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% +}% +\def\sphinxbooktabsbottomrule{% + \sphinxifbooktabswithcolorgapsTF + {\sphinxbooktabsspecialbottomrule}% + {\bottomrule}% +}% +% The colour here is already updated because of the \\ before so we must +% execute again the colour selection code, but this is not too complicated. +% What is annoying though is that \sphinxbottomrule in the longtable context +% appears both in the "foot" part and after the last body row. For the first +% occurrence the \rownum could be arbitrary if it had not been reset by each +% table using it via the \sphinxtableafterendhook (see above). This avoids +% having to modify the longtable template. But as \rownum is thus 0 in the +% "foot", the \sphinxSwitchCaseRowColor has to know how to handle negative +% inputs (in fact the -1 value), the Sphinx definition has no issue with that +% but any redefinition must be aware of this constraint. +\def\sphinxbooktabsspecialbottomrule{% + \noalign{\global\let\spx@@saved@CT@arc@\CT@arc@ + \sphinxSwitchCaseRowColor{\numexpr\rownum-\@ne\relax}% + \gdef\CT@arc@{\color{sphinxTableRowColor}}% + }% + \specialrule{\dimexpr\aboverulesep+\sphinxbooktabscolorgapsoverhang\relax}% + {-\sphinxbooktabscolorgapsoverhang}{\z@}% + \noalign{\global\let\CT@arc@\spx@@saved@CT@arc@}% + \specialrule{\heavyrulewidth}{\z@}{\belowbottomsep}% +}% +% +% MEMO: with longtable \sphinxtoprule, \sphinxmidrule and \sphinxbottomrule +% are evaluated at time of constructing the headers and footers as boxes +% (already typeset material and expanded macros; \sphinxbottomrule is also +% evaluated at very end of table body, i.e. "normally"). So the used colour +% to fill the booktabs gaps is decided during the headers and footers +% construction by longtable. Actually they are expanded twice: in firsthead +% then in head, respectively in foot and lastfoot. But in current design the +% header row colours are fixed, not alternating, so there is at least no +% coherence issue there. + +% The \spx@arrayrulewidth is used for some complex matters of merged +% cells size computations. +% tabularcolumns argument will override any global or local style and +% trigger the appropriate adjustment of \spx@arrayrulewidth. +% Notice that this will be bad if the table uses booktabs style +% but anyhow table with booktabs should not use any | separator. +\def\sphinxthistablewithvlinesstyle{% + \def\spx@arrayrulewidth{\arrayrulewidth}% + \let\sphinxvlinecrossing\sphinxtablevlinecrossing + \let\sphinxfixclines \sphinxtablefixclines +}% +\def\sphinxthistablewithnovlinesstyle{% + \def\spx@arrayrulewidth{\z@}% + \let\sphinxvlinecrossing\@gobble + % let's not bother to modify \sphinxfixclines, it works fine and is + % useful in standard style + no vline (only hlines and clines); + % besides, only one of vline or novline style macro is executed +}% + +% default is the standard style +\def\sphinxthistablewithglobalstyle{\sphinxthistablewithstandardstyle} + +\ifspx@opt@booktabs + \RequirePackage{booktabs} + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithbooktabsstyle} +\fi +\ifspx@opt@borderless + \def\sphinxthistablewithglobalstyle{\sphinxthistablewithborderlessstyle} +\fi +% colorrows appends to the current globalstyle (standard, booktabs, or borderless) +\ifspx@opt@colorrows % let the globalstyle trigger the colorrows style on top of it + \expandafter\def\expandafter\sphinxthistablewithglobalstyle\expandafter + {\sphinxthistablewithglobalstyle + \sphinxthistablewithcolorrowsstyle + } +\fi + + +\endinput diff --git a/docs/build/latex/sphinxmanual.cls b/docs/build/latex/sphinxmanual.cls new file mode 100644 index 0000000000000000000000000000000000000000..2e4b30d921c3343a19744726882b85cdf3621f5c --- /dev/null +++ b/docs/build/latex/sphinxmanual.cls @@ -0,0 +1,128 @@ +% +% sphinxmanual.cls for Sphinx (https://www.sphinx-doc.org/) +% + +\NeedsTeXFormat{LaTeX2e}[1995/12/01] +\ProvidesClass{sphinxmanual}[2019/12/01 v2.3.0 Document class (Sphinx manual)] + +% chapters starting at odd pages (overridden by 'openany' document option) +\PassOptionsToClass{openright}{\sphinxdocclass} + +% 'oneside' option overriding the 'twoside' default +\newif\if@oneside +\DeclareOption{oneside}{\@onesidetrue} +% Pass remaining document options to the parent class. +\DeclareOption*{\PassOptionsToClass{\CurrentOption}{\sphinxdocclass}} +\ProcessOptions\relax + +% Defaults two-side document +\if@oneside +% nothing to do (oneside is the default) +\else +\PassOptionsToClass{twoside}{\sphinxdocclass} +\fi + +\LoadClass{\sphinxdocclass} + +% Set some sane defaults for section numbering depth and TOC depth. You can +% reset these counters in your preamble. +% +\setcounter{secnumdepth}{2} +\setcounter{tocdepth}{1} + +% Adapt \and command to the flushright context of \sphinxmaketitle, to +% avoid ragged line endings if author names do not fit all on one single line +\DeclareRobustCommand{\and}{% + \end{tabular}\kern-\tabcolsep + \allowbreak + \hskip\dimexpr1em+\tabcolsep\@plus.17fil\begin{tabular}[t]{c}% +}% +% If it is desired that each author name be on its own line, use in preamble: +%\DeclareRobustCommand{\and}{% +% \end{tabular}\kern-\tabcolsep\\\begin{tabular}[t]{c}% +%}% +% Change the title page to look a bit better, and fit in with the fncychap +% ``Bjarne'' style a bit better. +% +\newcommand{\sphinxmaketitle}{% + \let\sphinxrestorepageanchorsetting\relax + \ifHy@pageanchor\def\sphinxrestorepageanchorsetting{\Hy@pageanchortrue}\fi + \hypersetup{pageanchor=false}% avoid duplicate destination warnings + \begin{titlepage}% + \let\footnotesize\small + \let\footnoterule\relax + \noindent\rule{\textwidth}{1pt}\par + \begingroup % for PDF information dictionary + \def\endgraf{ }\def\and{\& }% + \pdfstringdefDisableCommands{\def\\{, }}% overwrite hyperref setup + \hypersetup{pdfauthor={\@author}, pdftitle={\@title}}% + \endgroup + \begin{flushright}% + \sphinxlogo + \py@HeaderFamily + {\Huge \@title \par} + {\itshape\LARGE \py@release\releaseinfo \par} + \vfill + {\LARGE + \begin{tabular}[t]{c} + \@author + \end{tabular}\kern-\tabcolsep + \par} + \vfill\vfill + {\large + \@date \par + \vfill + \py@authoraddress \par + }% + \end{flushright}%\par + \@thanks + \end{titlepage}% + \setcounter{footnote}{0}% + \let\thanks\relax\let\maketitle\relax + %\gdef\@thanks{}\gdef\@author{}\gdef\@title{} + \clearpage + \ifdefined\sphinxbackoftitlepage\sphinxbackoftitlepage\fi + \if@openright\cleardoublepage\else\clearpage\fi + \sphinxrestorepageanchorsetting +} + +\newcommand{\sphinxtableofcontents}{% + \pagenumbering{roman}% + \begingroup + \parskip \z@skip + \sphinxtableofcontentshook + \tableofcontents + \endgroup + % before resetting page counter, let's do the right thing. + \if@openright\cleardoublepage\else\clearpage\fi + \pagenumbering{arabic}% +} + +% This is needed to get the width of the section # area wide enough in the +% library reference. Doing it here keeps it the same for all the manuals. +% +\newcommand{\sphinxtableofcontentshook}{% + \renewcommand*\l@section{\@dottedtocline{1}{1.5em}{2.6em}}% + \renewcommand*\l@subsection{\@dottedtocline{2}{4.1em}{3.5em}}% +} + +% Fix the bibliography environment to add an entry to the Table of +% Contents. +% For a report document class this environment is a chapter. +% +\newenvironment{sphinxthebibliography}[1]{% + \if@openright\cleardoublepage\else\clearpage\fi + % \phantomsection % not needed here since TeXLive 2010's hyperref + \begin{thebibliography}{#1}% + \addcontentsline{toc}{chapter}{\bibname}}{\end{thebibliography}} + +% Same for the indices. +% The memoir class already does this, so we don't duplicate it in that case. +% +\@ifclassloaded{memoir} + {\newenvironment{sphinxtheindex}{\begin{theindex}}{\end{theindex}}} + {\newenvironment{sphinxtheindex}{% + \if@openright\cleardoublepage\else\clearpage\fi + \phantomsection % needed as no chapter, section, ... created + \begin{theindex}% + \addcontentsline{toc}{chapter}{\indexname}}{\end{theindex}}} diff --git a/docs/build/latex/sphinxmessages.sty b/docs/build/latex/sphinxmessages.sty new file mode 100644 index 0000000000000000000000000000000000000000..68ebffa887dfb5a0ee10257bd15e1d73f54ff3c1 --- /dev/null +++ b/docs/build/latex/sphinxmessages.sty @@ -0,0 +1,21 @@ +% +% sphinxmessages.sty +% +% message resources for Sphinx +% +\ProvidesPackage{sphinxmessages}[2019/01/04 v2.0 Localized LaTeX macros (Sphinx team)] + +\renewcommand{\literalblockcontinuedname}{continued from previous page} +\renewcommand{\literalblockcontinuesname}{continues on next page} +\renewcommand{\sphinxnonalphabeticalgroupname}{Non\sphinxhyphen{}alphabetical} +\renewcommand{\sphinxsymbolsname}{Symbols} +\renewcommand{\sphinxnumbersname}{Numbers} +\def\pageautorefname{page} + +\addto\captionsenglish{\renewcommand{\figurename}{Fig.\@{} }} +\def\fnum@figure{\figurename\thefigure{}} + +\addto\captionsenglish{\renewcommand{\tablename}{Table }} +\def\fnum@table{\tablename\thetable{}} + +\addto\captionsenglish{\renewcommand{\literalblockname}{Listing}} \ No newline at end of file diff --git a/docs/build/latex/sphinxoptionsgeometry.sty b/docs/build/latex/sphinxoptionsgeometry.sty new file mode 100644 index 0000000000000000000000000000000000000000..d0c59f0e043626aa9e568dcad4efb5e204ed86cc --- /dev/null +++ b/docs/build/latex/sphinxoptionsgeometry.sty @@ -0,0 +1,54 @@ +%% OPTIONS FOR GEOMETRY +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxoptionsgeometry}[2021/01/27 geometry] + +% geometry +\ifx\kanjiskip\@undefined + \PassOptionsToPackage{% + hmargin={\unexpanded{\spx@opt@hmargin}},% + vmargin={\unexpanded{\spx@opt@vmargin}},% + marginpar=\unexpanded{\spx@opt@marginpar}} + {geometry} +\else + % set text width for Japanese documents to be integer multiple of 1zw + % and text height to be integer multiple of \baselineskip + % the execution is delayed to \sphinxsetup then geometry.sty + \normalsize\normalfont + \newcommand*\sphinxtextwidthja[1]{% + \if@twocolumn\tw@\fi + \dimexpr + \numexpr\dimexpr\paperwidth-\tw@\dimexpr#1\relax\relax/ + \dimexpr\if@twocolumn\tw@\else\@ne\fi zw\relax + zw\relax}% + \newcommand*\sphinxmarginparwidthja[1]{% + \dimexpr\numexpr\dimexpr#1\relax/\dimexpr1zw\relax zw\relax}% + \newcommand*\sphinxtextlinesja[1]{% + \numexpr\@ne+\dimexpr\paperheight-\topskip-\tw@\dimexpr#1\relax\relax/ + \baselineskip\relax}% + \ifx\@jsc@uplatextrue\@undefined\else + % the way we found in order for the papersize special written by + % geometry in the dvi file to be correct in case of jsbook class + \ifnum\mag=\@m\else % do nothing special if nomag class option or 10pt + \PassOptionsToPackage{truedimen}{geometry}% + \fi + \fi + \PassOptionsToPackage{% + hmarginratio={1:1},% + textwidth=\unexpanded{\sphinxtextwidthja{\spx@opt@hmargin}},% + vmarginratio={1:1},% + lines=\unexpanded{\sphinxtextlinesja{\spx@opt@vmargin}},% + marginpar=\unexpanded{\sphinxmarginparwidthja{\spx@opt@marginpar}},% + footskip=2\baselineskip,% + }{geometry}% + \AtBeginDocument + {% update a dimension used by the jsclasses + \ifx\@jsc@uplatextrue\@undefined\else\fullwidth\textwidth\fi + % for some reason, jreport normalizes all dimensions with \@settopoint + \@ifclassloaded{jreport} + {\@settopoint\textwidth\@settopoint\textheight\@settopoint\marginparwidth} + {}% <-- "false" clause of \@ifclassloaded + }% +\fi + +\endinput diff --git a/docs/build/latex/sphinxoptionshyperref.sty b/docs/build/latex/sphinxoptionshyperref.sty new file mode 100644 index 0000000000000000000000000000000000000000..caf28e8b9d0c71232b4dc7d99a55c52a0745a5a9 --- /dev/null +++ b/docs/build/latex/sphinxoptionshyperref.sty @@ -0,0 +1,35 @@ +%% Bookmarks and hyperlinks +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxoptionshyperref}[2021/01/27 hyperref] + +% to make pdf with correct encoded bookmarks in Japanese +% this should precede the hyperref package +\ifx\kanjiskip\@undefined +% for non-Japanese: make sure bookmarks are ok also with lualatex + \PassOptionsToPackage{pdfencoding=unicode}{hyperref} +\else + \RequirePackage{atbegshi} + \ifx\ucs\@undefined + \ifnum 42146=\euc"A4A2 + \AtBeginShipoutFirst{\special{pdf:tounicode EUC-UCS2}} + \else + \AtBeginShipoutFirst{\special{pdf:tounicode 90ms-RKSJ-UCS2}} + \fi + \else + \AtBeginShipoutFirst{\special{pdf:tounicode UTF8-UCS2}} + \fi +\fi + +\ifx\@jsc@uplatextrue\@undefined\else + \PassOptionsToPackage{setpagesize=false}{hyperref} +\fi + +% These options can be overridden inside 'hyperref' key +% or by later use of \hypersetup. +\PassOptionsToPackage{colorlinks,breaklinks,% + linkcolor=InnerLinkColor,filecolor=OuterLinkColor,% + menucolor=OuterLinkColor,urlcolor=OuterLinkColor,% + citecolor=InnerLinkColor}{hyperref} + +\endinput diff --git a/docs/build/latex/sphinxpackageboxes.sty b/docs/build/latex/sphinxpackageboxes.sty new file mode 100644 index 0000000000000000000000000000000000000000..234505147d5beaac7390f8831e4699ce870b71fd --- /dev/null +++ b/docs/build/latex/sphinxpackageboxes.sty @@ -0,0 +1,827 @@ +%% COLOURED BOXES +% +% change this info string if making any custom modification +\ProvidesPackage{sphinxpackageboxes}[2024/07/01 v7.4.0 advanced colored boxes] +% 7.4.0 removes usage of some booleans "...withbackgroundcolor" and +% "...withbordercolor" as well as \spx@boxes@border dimen which was +% actually really needed nowhere. This was done in sync with changes in +% sphinx.sty, sphinxlatexadmonitions.sty and sphinxlatexliterals.sty. +% +% Optionally executes \RequirePackage for: +% +% - pict2e. Ideally we would like to use the v0.4a 2020/08/16 release of this +% package as it allows dimensional arguments to its \moveto, \lineto, etc... +% Or we could use extra package "picture". We opt for custom wrappers +% \spx@moveto, \spx@lineto, ..., working with old versions. +% +% - ellipse. This package extends pict2e with elliptical arcs. Its author +% Daan Leijen also has contributed package longfbox which is part of +% TeXLive. Had I known about it, I would perhaps have based Sphinx CSS on +% top of longfbox at least partly. But this would not have spared me all +% the work in sphinx.sty, which was a long walk until 6.2.0 version. +% Besides I don't need the breakable boxes from longfbox, as Sphinx has +% its own rather advanced layer on top of framed. I would need to check if +% some thorny color issues solved by Sphinx (and not by tcolorbox) at page +% breaks are solved by longfbox as well. (I have not tested) + +% At 6.2.0 refactoring, we do not wait for at begin document to try to load +% pict2e. Actually since 6.0.0 the default is for code-blocks to use +% rounded boxes, and the only reason since then to wait "at begin document" +% was to check if user had reverted that default and in fact pict2e was not +% needed. But with \sphinxbox, we can not know for sure even in that case +% that pict2e is not needed. And even back then it would have been possible +% to user to try to employ \sphinxsetup via raw directive in document body +% and require some rounded corners (which was thus impossible to satisfy). +% Time to be much simpler and attempt unconditionally to load pict2e +% immediately. This will also have advantage that we can use +% \@ifpackageloaded{pict2e} and not have to query and save its setting later +% at begin document. +\IfFileExists{pict2e.sty} + {\RequirePackage{pict2e}} + {\PackageWarningNoLine{sphinx}{% + The package pict2e is required for rounded boxes.\MessageBreak + It does not seem to be available on your system.\MessageBreak + Options for setting radii will be ignored% + }% + % Formerly a \sphinxbuildwarning was issued but if we did that now it + % would mean that the produced PDF will always have a red banner near its + % end about pict2e not being available if indeed it is not available, even + % if user has reverted the default and dropped rounded corners. Formerly + % the serious warning was done after having checked at begin document that + % indeed a rounded corner option had been used. As we drop the check now, + % let's be more discrete and simply duplicate the earlier warning to make + % it visible near end of compilation log and console output. + \AtEndDocument{\PackageWarningNoLine{sphinx}{% + The package pict2e is required for rounded boxes.\MessageBreak + As it does not seem to be available on your system,\MessageBreak + options setting radii have all been ignored}}% + }% + +\IfFileExists{ellipse.sty} + {\RequirePackage{ellipse}} + {\PackageWarningNoLine{sphinx}{% + The package ellipse is required for elliptical corners.\MessageBreak + It does not seem to be available on your system.\MessageBreak + All non-straight corners will use circle arcs.% + }% + \AtEndDocument{\PackageWarningNoLine{sphinx}{% + The package ellipse is required for elliptical corners.\MessageBreak + As it does not seem to be available on your system,\MessageBreak + all non-straight corners have used circle arcs.}}% + }% + +% The pict2e release v0.4b of 2020/09/30 does not allocate scratch dimen +% register \@tempdimd which ellipse package uses. Thus ellipse package is +% broken since (written on March 20, 2023). Simply allocate the register +% ourself to fix that, pending some upstream fix. +\@ifpackageloaded{ellipse}{\ifdefined\@tempdimd\else\newdimen\@tempdimd\fi}{} + +% Provides box registers \spx@tempboxa, \spx@tempboxb usable in other places +\newbox\spx@tempboxa +\newbox\spx@tempboxb + +%%%%%%%%%%%%%%%% +% Internal registers, conditionals, colors to be configured by each caller +% via a preliminary "setup" call +\newif\ifspx@boxes@withshadow +\newif\ifspx@boxes@insetshadow +%%% \newif\ifspx@boxes@withbackgroundcolor % removed at 7.4.0 +\newif\ifspx@boxes@withshadowcolor +%%% \newif\ifspx@boxes@withbordercolor % removed at 7.4.0 +\newif\ifspx@boxes@shadowinbbox +% +\newdimen\spx@boxes@border@top +\newdimen\spx@boxes@border@right +\newdimen\spx@boxes@border@bottom +\newdimen\spx@boxes@border@left +% +\newdimen\spx@boxes@padding@top +\newdimen\spx@boxes@padding@right +\newdimen\spx@boxes@padding@bottom +\newdimen\spx@boxes@padding@left +% +\newdimen\spx@boxes@shadow@xoffset +\newdimen\spx@boxes@shadow@yoffset +% +\newdimen\spx@boxes@radius@topleft@x +\newdimen\spx@boxes@radius@topright@x +\newdimen\spx@boxes@radius@bottomright@x +\newdimen\spx@boxes@radius@bottomleft@x +\newdimen\spx@boxes@radius@topleft@y +\newdimen\spx@boxes@radius@topright@y +\newdimen\spx@boxes@radius@bottomright@y +\newdimen\spx@boxes@radius@bottomleft@y +% +% These colors will be set to colors defined appropriately by caller of +% \spx@boxes@fcolorbox@setup macro +% spx@boxes@bordercolor +% spx@boxes@backgroundcolor +% spx@boxes@shadowcolor +% spx@boxes@textcolor + +%%%%%%%%%%%%%%%% +% "setup" macro +% +% It must be called prior to \spx@boxes@fcolorbox for parameters of the latter +% to be initialized. +% +% It also prepares \spx@boxes@fcolorbox to expand to one of +% \spx@boxes@fcolorbox@rectangle or \spx@boxes@fcolorbox@rounded depending on +% the configuration and availability of the pict2e package. +% +% The #1 is one of: pre, topic, warning, danger, etc.... +% +% We delay until here the parsing of radii options to extract x and y +% components. +\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{% + #4\dimexpr#1\relax + #5\dimexpr#2\relax + \ifdim#5=-\maxdimen#5#4\fi + % if one of them is zero or negative set both to zero + \ifdim#4>\z@\else#4\z@#5\z@\fi + \ifdim#5>\z@\else#4\z@#5\z@\fi +}% +% if ellipse.sty is not available ignore the second component of all radii +% specifications, use circle arcs with radius the x component +\@ifpackageloaded{ellipse} + {} + {\def\spx@boxes@setradii#1 #2 #3\@nnil#4#5{#4\dimexpr#1\relax #5#4}} + +% Using \dimexpr for maximal user input flexibility. +\def\spx@boxes@fcolorbox@setup#1{% + \spx@boxes@border@top \dimexpr\@nameuse{spx@#1@border@top}\relax + \spx@boxes@border@right \dimexpr\@nameuse{spx@#1@border@right}\relax + \spx@boxes@border@bottom\dimexpr\@nameuse{spx@#1@border@bottom}\relax + \spx@boxes@border@left \dimexpr\@nameuse{spx@#1@border@left}\relax + % + \spx@boxes@padding@top \dimexpr\@nameuse{spx@#1@padding@top}\relax + \spx@boxes@padding@right \dimexpr\@nameuse{spx@#1@padding@right}\relax + \spx@boxes@padding@bottom\dimexpr\@nameuse{spx@#1@padding@bottom}\relax + \spx@boxes@padding@left \dimexpr\@nameuse{spx@#1@padding@left}\relax + % + \edef\spx@temp{\csname spx@#1@radius@topleft\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@topleft@x\spx@boxes@radius@topleft@y + \edef\spx@temp{\csname spx@#1@radius@topright\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@topright@x\spx@boxes@radius@topright@y + \edef\spx@temp{\csname spx@#1@radius@bottomright\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@bottomright@x\spx@boxes@radius@bottomright@y + \edef\spx@temp{\csname spx@#1@radius@bottomleft\endcsname\space}% + \expandafter + \spx@boxes@setradii + \spx@temp + {-\maxdimen} + \@nnil + \spx@boxes@radius@bottomleft@x\spx@boxes@radius@bottomleft@y + % + \@nameuse{ifspx@#1@withshadow}% + \spx@boxes@withshadowtrue + \spx@boxes@shadow@xoffset \dimexpr\@nameuse{spx@#1@shadow@xoffset}\relax + \spx@boxes@shadow@yoffset \dimexpr\@nameuse{spx@#1@shadow@yoffset}\relax + \else + \spx@boxes@withshadowfalse + \fi + % not nesting in previous to avoid TeX conditional subtleties + \@nameuse{ifspx@#1@insetshadow}% + \spx@boxes@insetshadowtrue + \else + \spx@boxes@insetshadowfalse + \fi + % + \sphinxcolorlet{spx@boxes@bordercolor}{sphinx#1BorderColor}% + % + \sphinxcolorlet{spx@boxes@backgroundcolor}{sphinx#1BgColor}% + % + \@nameuse{ifspx@#1@withshadowcolor}% + \spx@boxes@withshadowcolortrue + \sphinxcolorlet{spx@boxes@shadowcolor}{sphinx#1ShadowColor}% + \else + \spx@boxes@withshadowcolorfalse + \fi + % Display elements pre, topic, warning et al. by default do not include + % shadow in box (legacy; and only topic actually uses a shadow per default) + % This may be refactored still more in future, but this 6.2.0 extra helped + % reduce workload from code-blocks (pre), contents (topic) and admonitions. + % As this conditional is a priori false and should only be changed locally + % (by \sphinxbox), this line is actually superfluous. + \spx@boxes@shadowinbboxfalse + \spx@boxes@fcolorbox@setup@fcolorbox +} +\@ifpackageloaded{pict2e} +{% pict2e is available and loaded + \def\spx@boxes@fcolorbox@setup@fcolorbox{% + \if1% use rounded boxes only if needed (rx>0 iff ry>0) + \ifdim\spx@boxes@radius@topleft@x >\z@0\fi + \ifdim\spx@boxes@radius@topright@x >\z@0\fi + \ifdim\spx@boxes@radius@bottomright@x>\z@0\fi + \ifdim\spx@boxes@radius@bottomleft@x >\z@0\fi + 1\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% + \else + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rounded}% + \fi + }% end of definition of setup@fcolorbox in case of presence of pict2e +}% +{% pict2e could not be loaded, we must always use fcolorbox@rectangle + \def\spx@boxes@fcolorbox@setup@fcolorbox{% + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% + }% end of definition of setup@fcolorbox in case of absence of pict2e +}% end of "no pict2e" branch + +%%%%%%%%%%%%%%%% +% Support of box-decoration-break=slice +% +% 6.2.0 has renamed and moved this here from sphinxlatexliterals.sty, +% to facilitate supporting box-decoration-break=slice for all directives, +% not only code-block. +% +% It also modified when these post actions are executed, in order +% for openboth to be able to trigger usage of fcolorbox@rectangle. +% So now openbottom and opentop also take advantage of this possible +% optimization. +\def\spx@boxes@fcolorbox@setup@openbottom{% + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@ + \spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@ + \spx@boxes@fcolorbox@setup@fcolorbox +}% +\def\spx@boxes@fcolorbox@setup@opentop{% + \spx@boxes@border@top \z@ + \spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@ + \spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@ + \spx@boxes@fcolorbox@setup@fcolorbox +}% +\def\spx@boxes@fcolorbox@setup@openboth{% + \spx@boxes@border@top \z@ + \spx@boxes@border@bottom \z@ + \spx@boxes@radius@bottomright@x\z@ \spx@boxes@radius@bottomright@y\z@ + \spx@boxes@radius@bottomleft@x \z@ \spx@boxes@radius@bottomleft@y \z@ + \spx@boxes@radius@topright@x\z@ \spx@boxes@radius@topright@y\z@ + \spx@boxes@radius@topleft@x \z@ \spx@boxes@radius@topleft@y \z@ + \def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle}% +}% + +%%%%%%%%%%%%%%%% +% \sphinxbox (added at 6.2.0) +% +% For an inline box, possibly rounded. +\newcommand\sphinxbox[1][]{% #1 stands for the options, they are... optional! + % \leavevmode makes sure TeX switches to paragraph mode, which is necessary + % if this is first in a paragraph or a list element. The \sphinxAtStartPar + % mechanism also ensures this automatically, if not redefined, but not with + % lualatex as then it is by default doing nothing. + \leavevmode + \begingroup + \ifcsname spx@boxes@sphinxbox@isnested\endcsname + % nested boxes reset all box options to be as the \sphinxboxsetup + % defaults, before applying their specific options + \spx@boxes@sphinxbox@reset + \else + % top layer box, toggle the nested flag + \csname spx@boxes@sphinxbox@isnested\endcsname + \fi + % we do not use \sphinxboxsetup as it is a user command extending the + % "reset" storage + \setkeys{sphinxbox}{#1}% + \spx@boxes@fcolorbox@setup{box}% + \spx@boxes@shadowinbboxtrue% inline sphinx boxes include shadow in bbox + \ifspx@box@withtextcolor\color{sphinxboxTextColor}\fi + % + % MEMO: the fcolorbox@{rectangle,rounded} draw the contents (which here + % will be encapsulated as \box\z@) last, i.e. after shadow, background, + % and border and their color commands. The \reset@color from naked + % top-level \color commands in argument (which can not arise from Sphinx + % mark-up anyhow) would end up being placed via color.sty \aftergroup core + % mechanism in token stream after \spx@boxes@sphinxbox@a (which is the + % first \aftergroup) hence after the box contents with its unbalanced + % color pushes is shipped to PDF. So the missing color pop specials are + % inserted then in correct order at correct place (after the \endgroup at + % end of \spx@boxes@sphinxbox@a but this is not relevant) and do not end + % up causing havoc in push/pop pairs (and all this happens on same page). + % + % There is thus no reason here to go to the trouble to add an extra + % \color@begingroup/\color@endgroup or like pair to encapsulate the caught + % contents in order for the \box\z@ to contain as many color pop's as it + % has color pushes. But as this is subtle, this comment was added for + % future maintenance. Actually even if the contents were not drawn last, + % their (purely theoretical, as Sphinx mark-up can not create it) missing + % color pop's would not have caused trouble I guess as long as the color + % insertions for shadow, background, border are correctly balanced. + \setbox0\hbox\bgroup\aftergroup\spx@boxes@sphinxbox@a + \afterassignment\spx@box@TeXextras + \let\next=% +} +\def\spx@boxes@sphinxbox@a{\spx@boxes@fcolorbox{% + \ifspx@opt@box@addstrut\strut\fi\box\z@}\endgroup} + +\newcommand\newsphinxbox[2][]{% + \newcommand#2[1][]{\sphinxbox[#1,##1]}% +} +% Let's catch \renewsphinxbox[...]{\sphinxbox} which would cause \sphinxbox +% to fall into infinite looping on use. +\newcommand\renewsphinxbox[2][]{% + \in@{#2}{\sphinxbox}% + \ifin@ + \PackageWarning{sphinx}{Attempt to \string\renewsphinxbox\space + the \string\sphinxbox\space command\MessageBreak + itself. This is not allowed and will be ignored.\MessageBreak + Reported}% + \else + \renewcommand#2[1][]{\sphinxbox[#1,##1]}% + \fi +} + +%%%%%%%%%%%%%%%% +% MACROS +% +% \spx@boxes@fcolorbox expands either to \spx@boxes@fcolorbox@rectangle +% or \spx@boxes@fcolorbox@rounded depending on preliminary set-up. +% +% This is decided by the "setup" which must have been executed by the caller. +% Let's give it some (thus unneeded) default fall-back for clarity. +\def\spx@boxes@fcolorbox{\spx@boxes@fcolorbox@rectangle} +% +% A macro \spx@boxes@fcolorbox@setuphook used to be executed at start of the +% \hbox constructs (rectangle or rounded). This was used until 6.2.0 for the +% support of pre_box-decoration-break option, hence was really an internal +% non-public macro. As it is not needed anymore, with some hesitation it got +% entirely removed at 6.2.0 on the occasion of a refactoring of interactions of +% this file with sphinxlatexliterals.sty. Besides its name should have been +% rather something such as \spx@boxes@fcolorbox@atstartofhbox. +% +% After "setup", \spx@boxes@fcolorbox expands to one of: +% +% - \spx@boxes@fcolorbox@rectangle (4 padding parameters, 4 border widths, 2 shadow widths, +% and three colours: background, border and shadow; same as in CSS styling) +% +% It branches to one of: +% - \spx@boxes@fcolorbox@externalshadow +% - \spx@boxes@fcolorbox@insetshadow (same concept of "inset" as in CSS styling) +% +% - \spx@boxes@fcolorbox@rounded: rounded corners using the picture environment +% and pict2e package for its low-weight interface to PDF graphics operations + +% MEMO: we have also successfully tested usage of tcolorbox.sty (its \tcbox) but +% decided to use pict2e.sty for the following reasons: +% 1- PDF build was observed to be an order of magnitude faster, +% 2- the boxes we can do with pict2e appear to be fancy enough, +% almost matching what one can see in HTML renderings, +% 2- orders of magnitude smaller dependency (tcolorbox uses the pgf TeX +% framework), although on Ubuntu it seems texlive-pictures is +% needed which also contains the whole of pgf/TikZ... so this point +% is a bit moot... + +% For code-blocks, attachments of caption and continuation hints are done +% exactly as prior to extension of Sphinx via this package, whether the box +% has straight or rounded corners. The vertical space occupied is the same, +% if nothing else is changed (perhaps in future the title itself could be also +% rendered in a rounded box?) + +%%%%%%%% +%//// \spx@boxes@fcolorbox@rectangle +% +% This box will have the same baseline as its argument (which is typeset in +% horizontal mode). It takes into account four border widths parameters, four +% padding parameters, two shadow widths (each possibly negative), and three +% colors: background, border and shadow. Its boundary box takes into account +% border and padding. Width of shadow is taken into account if the boolean +% \ifspx@boxes@shadowinbbox is \iftrue. The "setup" sets it to \iffalse. +% Prior to 6.2.0, shadow size was included in bbox but the callers manually +% removed it by extra steps. The \sphinxbox command sets it to \iftrue after +% the "setup". +% +% It is up to the caller to take extra steps if the border and padding must go +% into margin as well (see sphinxlatexliterals.sty for how this is done in +% \spx@verb@FrameCommand). +% +% In usage as a "FrameCommand" with framed.sty, the argument will already be a +% collection of TeX boxes (and interline glues). +% +% This was designed so that the parameters configured by "setup" are +% interpreted as they would be as CSS properties in an HTML context. +\long\def\spx@boxes@fcolorbox@rectangle#1{% + \hbox\bgroup + \setbox\spx@tempboxa + \hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax + {#1}% + \kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}% + \ht\spx@tempboxa + \dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax + \dp\spx@tempboxa + \dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax + \ifspx@boxes@insetshadow + \expandafter\spx@boxes@fcolorbox@insetshadow + \else + \expandafter\spx@boxes@fcolorbox@externalshadow + \fi +} + +% external shadow +\def\spx@boxes@fcolorbox@externalshadow{% + % reserve space to external shadow if on left + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi + \fi + \fi + % BACKGROUND + % draw background and move back to reference point + {\color{spx@boxes@backgroundcolor}% + \vrule\@height\ht\spx@tempboxa + \@depth\dp\spx@tempboxa + \@width\wd\spx@tempboxa + \kern-\wd\spx@tempboxa + }% + % BOX SHADOW + % draw shadow and move back to reference point + \ifspx@boxes@withshadow + \vbox{% + \moveright\spx@boxes@shadow@xoffset + \hbox{\lower\spx@boxes@shadow@yoffset + \vbox{\ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: guard against a manually inserted \color command in + % contents which could leak at a page break to the shadow + \normalcolor + \fi + \ifdim\spx@boxes@shadow@yoffset<\z@ + \hrule\@height-\spx@boxes@shadow@yoffset + \kern\spx@boxes@shadow@yoffset + \fi + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{% + \ifdim\spx@boxes@shadow@xoffset<\z@\vrule\@width-\spx@boxes@shadow@xoffset\fi + \hss + \ifdim\spx@boxes@shadow@xoffset>\z@\vrule\@width\spx@boxes@shadow@xoffset\fi + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \ifdim\spx@boxes@shadow@yoffset>\z@ + \kern-\spx@boxes@shadow@yoffset + \hrule\@height\spx@boxes@shadow@yoffset + \fi + \kern-\dp\spx@tempboxa + }% end of \vbox, attention it will have zero depth if yoffset>0 + \kern-\wd\spx@tempboxa + \ifdim\spx@boxes@shadow@xoffset>\z@ + \kern-\spx@boxes@shadow@xoffset + \fi + }% end of \hbox, attention its depth is only yoffset if yoffset>0 + }% end of \vbox + \fi % end of shadow drawing, and we are back to horizontal reference point + % BOX BORDER + % 7.4.0 requires a set border color + \vbox{\color{spx@boxes@bordercolor}% + \hrule\@height\spx@boxes@border@top + \kern-\spx@boxes@border@top + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa + {\vrule\@width\spx@boxes@border@left + \hss\vrule\@width\spx@boxes@border@right + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \kern-\spx@boxes@border@bottom + \hrule\@height\spx@boxes@border@bottom + \kern-\dp\spx@tempboxa + }% attention this box has zero depth due to \hrule at bottom + % step back to horizontal reference point + \kern-\wd\spx@tempboxa + % end of border drawing + % CONTENTS + % adjust the total depth to include the bottom shadow + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset>\z@ + \dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax + \fi + \fi + \box\spx@tempboxa + % include lateral shadow in total width + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi + \fi + \fi + \egroup +} + +% inset shadow +% +% The parameters signs are interpreted as in CSS styling. +\def\spx@boxes@fcolorbox@insetshadow{% + % BACKGROUND + % draw background and move back to reference point + % 7.4.0 always assumes a background color + {\color{spx@boxes@backgroundcolor}% + \vrule\@height\ht\spx@tempboxa + \@depth\dp\spx@tempboxa + \@width\wd\spx@tempboxa + \kern-\wd\spx@tempboxa + }% + % BOX SHADOW + % draw shadow and move back to reference point + \ifspx@boxes@withshadow + \hbox{\vbox{\ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: guard against a manually inserted \color command in + % contents which could leak at a page break to the shadow + \normalcolor + \fi +% NOTA BENE +% We deliberately draw shadow partially under an area later covered by frame +% with the idea to avoid anti-aliasing problems but in fact this may be a bad +% idea with border is thin. +% This may need some extra testing with PDF viewers... reports welcome! + \ifdim\spx@boxes@shadow@yoffset>\z@ + \hrule\@height\dimexpr\spx@boxes@border@top+\spx@boxes@shadow@yoffset\relax + \kern-\spx@boxes@shadow@yoffset + \kern-\spx@boxes@border@top + \fi + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa{% + \ifdim\spx@boxes@shadow@xoffset>\z@ + \vrule\@width\dimexpr\spx@boxes@border@left+\spx@boxes@shadow@xoffset\relax\fi + \hss + \ifdim\spx@boxes@shadow@xoffset<\z@ + \vrule\@width\dimexpr-\spx@boxes@shadow@xoffset+\spx@boxes@border@right\relax\fi + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \ifdim\spx@boxes@shadow@yoffset<\z@ + \kern\spx@boxes@shadow@yoffset + \kern-\spx@boxes@border@bottom + \hrule\@height\dimexpr-\spx@boxes@shadow@yoffset+\spx@boxes@border@bottom\relax + \fi + \kern-\dp\spx@tempboxa + }% end of \vbox, attention it will have zero depth if yoffset<0 + \kern-\wd\spx@tempboxa + }% end of \hbox, attention its depth is only |yoffset| if yoffset<0 + \fi % end of inset shadow drawing, and we are back to horizontal reference point + % BOX BORDER + % 7.4.0 requires a set border color + \vbox{\color{spx@boxes@bordercolor}% + \hrule\@height\spx@boxes@border@top + \kern-\spx@boxes@border@top + \setbox\spx@tempboxb\hb@xt@\wd\spx@tempboxa + {\vrule\@width\spx@boxes@border@left + \hss\vrule\@width\spx@boxes@border@right + }% + \ht\spx@tempboxb\ht\spx@tempboxa + \dp\spx@tempboxb\dp\spx@tempboxa + \box\spx@tempboxb + \kern-\spx@boxes@border@bottom + \hrule\@height\spx@boxes@border@bottom + \kern-\dp\spx@tempboxa + }% attention this box has zero depth due to \hrule at bottom + % step back to horizontal reference point + \kern-\wd\spx@tempboxa + % end of border drawing + % CONTENTS + \box\spx@tempboxa + \egroup +} + +% let's abort input if pict2e package could not be loaded. +% To be extra safe we also alias @rounded to @rectangle but +% a priori the architecture is done so that @rounded will never +% be called in that case by other Sphinx LaTeX components. +\@ifpackageloaded{pict2e} + {} + {\def\spx@boxes@fcolorbox@rounded{\spx@boxes@fcolorbox@rectangle}% + \endinput + } + +% we proceed now in the context of pict2e being available and loaded +% (TeX being a macro-expansion based language it would have +% swallowed all the coming definitions even if pict2e +% had in fact not been loaded... but we aborted the input above) +%%%%%%%% +%//// \spx@boxes@fcolorbox@rounded +% +% Prior to 6.2.0, a constant border-width was applied as the border was +% obtained as a \strokepath. This allowed 4 distinct radii but not to vary the +% border widths. Now the border is drawn by two \fillpath operation, the first +% one filling up to external border, the second one actually filling for the +% background paradoxically on top of it, up to internal border path. +% +% This 6.2.0 abandonment of \strokepath allowed great simplification in +% supporting opentop, openbottom and openboth situations, and it can +% allow automatic support of openleft and openright analogs. +% +% And 6.2.0 also implements elliptical arcs thanks to ellipse package, +% which extends pict2e. + +% Currently, inset shadow is not supported. +% +% Prior to 6.2.0 an inset shadow triggered the rectangle variant, so we never +% ended here, but now it is simply ignored. This change does not appear to me +% to be breaking, as it changes output only for conf.py's specifying both +% rounded corners and an inset shadow and the documentation said it was +% incompatible. + +% wrappers for pict2e usage if old +% Better not to copy over 2020 pict2e definitions in case +% something internal changes +% However our wrappers will work ONLY with dimensional inputs +% No need to pre-expand the arguments +% Braces in case the expression uses parentheses +\def\spx@moveto(#1,#2){\moveto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})} +\def\spx@lineto(#1,#2){\lineto({\strip@pt\dimexpr#1\relax},{\strip@pt\dimexpr#2\relax})} +% attention here the [N] becomes mandatory +% \circlearc[]{}{}{}{}{} +\def\spx@circlearc[#1]#2#3#4%#5#6 + {\circlearc[#1]{\strip@pt\dimexpr#2\relax}% + {\strip@pt\dimexpr#3\relax}% + {\strip@pt\dimexpr#4\relax}% + } +% attention here too the [N] becomes mandatory +% the core path macro of ellipse.sty. Thanks to Daan Leijen, author of this +% package. +% \elliparc []{}{}{}{}{}{} +% maybe this wrapper is unneeded but I don't have real time to check +\def\spx@elliparc[#1]#2#3#4#5%#6#7 + {\elliparc[#1]{\strip@pt\dimexpr#2\relax}% + {\strip@pt\dimexpr#3\relax}% + {\strip@pt\dimexpr#4\relax}% + {\strip@pt\dimexpr#5\relax}% + } + +% Macro whose execution prepares a path to be either stroked or filled +% Only fill operation is used at 6.2.0. The radii are given by the set box +% parameters, but the width and height are in \spx@width and \spx@height. A +% \put command will be used for appropriate shifts. +% 6.2.0 adds elliptical corners! +% But I feel perhaps I need to think about how x-radius and y-radius should +% interact with border-width. So consider output WIP for time being. +\def\spx@boxes@border@defpath{% + \spx@moveto(\spx@boxes@radius@bottomleft@x,\z@)% our \spx@moveto is a bit rigid + % and we must use \z@ not 0 here + \spx@lineto(\spx@width-\spx@boxes@radius@bottomright@x,\z@)% + % x and y radii are either both positive or both zero + % probably not needed to actually guard against the latter case, + % let's do it nevertheless + \ifdim\spx@boxes@radius@bottomright@x>\z@ + \ifdim\spx@boxes@radius@bottomright@x=\spx@boxes@radius@bottomright@y + \spx@circlearc[2]{\spx@width-\spx@boxes@radius@bottomright@x}% + {\spx@boxes@radius@bottomright@y}% + {\spx@boxes@radius@bottomright@x}{-90}{0}% + \else + \spx@elliparc[2]{\spx@width-\spx@boxes@radius@bottomright@x}% + {\spx@boxes@radius@bottomright@y}% + {\spx@boxes@radius@bottomright@x} + {\spx@boxes@radius@bottomright@y}{-90}{0}% + \fi + \fi + \spx@lineto(\spx@width,% + \spx@height-\spx@boxes@radius@topright@y)% + \ifdim\spx@boxes@radius@topright@x>\z@ + \ifdim\spx@boxes@radius@topright@x=\spx@boxes@radius@topright@y + \spx@circlearc[2]{\spx@width-\spx@boxes@radius@topright@x} + {\spx@height-\spx@boxes@radius@topright@y}% + {\spx@boxes@radius@topright@x}{0}{90}% + \else + \spx@elliparc[2]{\spx@width-\spx@boxes@radius@topright@x} + {\spx@height-\spx@boxes@radius@topright@y}% + {\spx@boxes@radius@topright@x}% + {\spx@boxes@radius@topright@y}{0}{90}% + \fi + \fi + \spx@lineto(\spx@boxes@radius@topleft@x,\spx@height)% + \ifdim\spx@boxes@radius@topleft@x>\z@ + \ifdim\spx@boxes@radius@topleft@x=\spx@boxes@radius@topleft@y + \spx@circlearc[2]{\spx@boxes@radius@topleft@x}% + {\spx@height-\spx@boxes@radius@topleft@y}% + {\spx@boxes@radius@topleft@x}{90}{180}% + \else + \spx@elliparc[2]{\spx@boxes@radius@topleft@x}% + {\spx@height-\spx@boxes@radius@topleft@y}% + {\spx@boxes@radius@topleft@x}% + {\spx@boxes@radius@topleft@y}{90}{180}% + \fi + \fi + \spx@lineto(\z@,\spx@boxes@radius@bottomleft@y)% + \ifdim\spx@boxes@radius@bottomleft@x>\z@ + \ifdim\spx@boxes@radius@bottomleft@x=\spx@boxes@radius@bottomleft@y + \spx@circlearc[2]{\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}% + {\spx@boxes@radius@bottomleft@x}{180}{270}% + \else + \spx@elliparc[2]{\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}% + {\spx@boxes@radius@bottomleft@x}% + {\spx@boxes@radius@bottomleft@y}{180}{270}% + \fi + \fi +}% end of definition of \spx@boxes@border@defpath + +% The customization of the various parameters must have been done via an +% appropriate call to \spx@boxes@fcolorbox@setup, which will have set up +% \spx@boxes@fcolorbox to expand to \spx@boxes@fcolorbox@rounded, and will +% have set its various parameters. +% +\long\def\spx@boxes@fcolorbox@rounded #1{% + \hbox{% + \ifspx@boxes@withshadow + \ifspx@boxes@insetshadow + \spx@boxes@withshadowfalse % ignore inset shadow + \fi + \fi + % reserve space to external shadow if on left + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset<\z@\kern-\spx@boxes@shadow@xoffset\fi + \fi + \fi + \vbox{% + % adjust vertical bbox + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset<\z@ + \kern-\spx@boxes@shadow@yoffset + \fi + \fi + \setlength{\unitlength}{1pt}% + \setbox\spx@tempboxa + \hbox{\kern\dimexpr\spx@boxes@border@left+\spx@boxes@padding@left\relax + {#1}% + \kern\dimexpr\spx@boxes@padding@right+\spx@boxes@border@right\relax}% + \ht\spx@tempboxa + \dimexpr\ht\spx@tempboxa+\spx@boxes@border@top+\spx@boxes@padding@top\relax + \dp\spx@tempboxa + \dimexpr\dp\spx@tempboxa+\spx@boxes@padding@bottom+\spx@boxes@border@bottom\relax + \edef\spx@width{\number\wd\spx@tempboxa sp}% + \edef\spx@height{\number\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa sp}% + \hbox{% + \begin{picture}% + % \strip@pt\dimexpr to work around "old" LaTeX picture limitation + % (we could use the "picture" package, this would add another dependency) + (\strip@pt\dimexpr\spx@width\relax,\strip@pt\dimexpr\spx@height\relax)% + \spx@boxes@border@defpath + \ifspx@boxes@withshadow + \ifspx@boxes@withshadowcolor + \color{spx@boxes@shadowcolor}% + \else + % 6.2.0: here and elsewhere guard against a manually inserted + % \color command in contents which could leak to the shadow + % to the shadow + \normalcolor + \fi + \put(\strip@pt\spx@boxes@shadow@xoffset,% + \strip@pt\dimexpr-\spx@boxes@shadow@yoffset\relax) + {\fillpath}% + \fi + \spx@boxes@border@defpath% must be redone after each \fillpath! (even if + % was in a \put) + % 7.4.0 requires a set border color + \color{spx@boxes@bordercolor}% + \fillpath + % and backgroundcolor command + \color{spx@boxes@backgroundcolor}% + \edef\spx@width{\number\dimexpr\spx@width-\spx@boxes@border@left + -\spx@boxes@border@right sp}% + \edef\spx@height{\number\dimexpr\spx@height-\spx@boxes@border@top + -\spx@boxes@border@bottom sp}% + % redefine a path (in relative coordinates) matching the area delimited + % by the internal borders + \spx@boxes@border@defpath + % use \put to shift, and fill it with background color + \put(\strip@pt\spx@boxes@border@left,\strip@pt\spx@boxes@border@bottom) + {\fillpath}% + \end{picture}}% end of picture \hbox in \vbox + % back-up vertically for outputting the contents + \kern-\dimexpr\ht\spx@tempboxa+\dp\spx@tempboxa\relax + % adjust vertical bbox + \ifspx@boxes@withshadow + \ifdim\spx@boxes@shadow@yoffset>\z@ + \dp\spx@tempboxa\dimexpr\dp\spx@tempboxa+\spx@boxes@shadow@yoffset\relax + \fi + \fi + % inhibit TeX's "line skip" adjustment when piling up hboxes in a vbox + \nointerlineskip + \box\spx@tempboxa + }% end of \vbox + % include lateral shadow in total width + \ifspx@boxes@withshadow + \ifspx@boxes@shadowinbbox + \ifdim\spx@boxes@shadow@xoffset>\z@\kern\spx@boxes@shadow@xoffset\fi + \fi + \fi + }% end of \hbox +}% + + +\endinput diff --git a/docs/build/latex/sphinxpackagecyrillic.sty b/docs/build/latex/sphinxpackagecyrillic.sty new file mode 100644 index 0000000000000000000000000000000000000000..9aa62fc22baa68906867164da4d6819dfaf72907 --- /dev/null +++ b/docs/build/latex/sphinxpackagecyrillic.sty @@ -0,0 +1,55 @@ +%% CYRILLIC IN NON-CYRILLIC DOCUMENTS (pdflatex only) +% +% refs: https://tex.stackexchange.com/q/460271/ +\ProvidesPackage{sphinxpackagecyrillic}% + [2018/11/21 v2.0 support for Cyrillic in non-Cyrillic documents] +\RequirePackage{kvoptions} +\SetupKeyvalOptions{prefix=spx@cyropt@} % use \spx@cyropt@ prefix +\DeclareBoolOption[false]{Xtwo} +\DeclareBoolOption[false]{TtwoA} +\DeclareDefaultOption{\@unknownoptionerror} +\ProcessLocalKeyvalOptions* % ignore class options + +\ifspx@cyropt@Xtwo +% original code by tex.sx user egreg (updated 2019/10/28): +% https://tex.stackexchange.com/a/460325/ +% 159 Cyrillic glyphs as available in X2 TeX 8bit font encoding +% This assumes inputenc loaded with utf8 option, or LaTeX release +% as recent as 2018/04/01 which does it automatically. + \@tfor\next:=% + {Ё}{Ђ}{Є}{Ѕ}{І}{Ј}{Љ}{Њ}{Ћ}{Ў}{Џ}{А}{Б}{В}{Г}{Д}{Е}{Ж}{З}{И}{Й}% + {К}{Л}{М}{Н}{О}{П}{Р}{С}{Т}{У}{Ф}{Х}{Ц}{Ч}{Ш}{Щ}{Ъ}{Ы}{Ь}{Э}{Ю}% + {Я}{а}{б}{в}{г}{д}{е}{ж}{з}{и}{й}{к}{л}{м}{н}{о}{п}{р}{с}{т}{у}% + {ф}{х}{ц}{ч}{ш}{щ}{ъ}{ы}{ь}{э}{ю}{я}{ё}{ђ}{є}{ѕ}{і}{ј}{љ}{њ}{ћ}% + {ў}{џ}{Ѣ}{ѣ}{Ѫ}{ѫ}{Ѵ}{ѵ}{Ґ}{ґ}{Ғ}{ғ}{Ҕ}{ҕ}{Җ}{җ}{Ҙ}{ҙ}{Қ}{қ}{Ҝ}{ҝ}% + {Ҟ}{ҟ}{Ҡ}{ҡ}{Ң}{ң}{Ҥ}{ҥ}{Ҧ}{ҧ}{Ҩ}{ҩ}{Ҫ}{ҫ}{Ҭ}{ҭ}{Ү}{ү}{Ұ}{ұ}{Ҳ}{ҳ}% + {Ҵ}{ҵ}{Ҷ}{ҷ}{Ҹ}{ҹ}{Һ}{һ}{Ҽ}{ҽ}{Ҿ}{ҿ}{Ӏ}{Ӄ}{ӄ}{Ӆ}{ӆ}{Ӈ}{ӈ}{Ӌ}{ӌ}% + {Ӎ}{ӎ}{Ӕ}{ӕ}{Ә}{ә}{Ӡ}{ӡ}{Ө}{ө}\do + {% + \begingroup\def\IeC{\protect\DeclareTextSymbolDefault}% + \protected@edef\@temp{\endgroup + \@ifl@t@r{\fmtversion}{2019/10/01}{\csname u8:\next\endcsname}{\next}}% + \@temp{X2}% + }% +\else +\ifspx@cyropt@TtwoA +% original code by tex.sx user jfbu: +% https://tex.stackexchange.com/a/460305/ +% 63*2+1=127 Cyrillic glyphs as found in T2A 8bit TeX font-encoding + \@tfor\@tempa:=% + {ae}{a}{b}{chrdsc}{chvcrs}{ch}{c}{dje}{dze}{dzhe}{d}{erev}{ery}{e}% + {f}{ghcrs}{gup}{g}{hdsc}{hrdsn}{h}{ie}{ii}{ishrt}{i}{je}% + {kbeak}{kdsc}{kvcrs}{k}{lje}{l}{m}{ndsc}{ng}{nje}{n}{otld}{o}{p}{r}% + {schwa}{sdsc}{sftsn}{shch}{shha}{sh}{s}{tshe}{t}{ushrt}{u}{v}% + {ya}{yhcrs}{yi}{yo}{yu}{y}{zdsc}{zhdsc}{zh}{z}\do + {% + \expandafter\DeclareTextSymbolDefault\expandafter + {\csname cyr\@tempa\endcsname}{T2A}% + \expandafter\uppercase\expandafter{\expandafter + \def\expandafter\@tempa\expandafter{\@tempa}}% + \expandafter\DeclareTextSymbolDefault\expandafter + {\csname CYR\@tempa\endcsname}{T2A}% + }% + \DeclareTextSymbolDefault{\CYRpalochka}{T2A}% +\fi\fi +\endinput diff --git a/docs/build/latex/sphinxpackagefootnote.sty b/docs/build/latex/sphinxpackagefootnote.sty new file mode 100644 index 0000000000000000000000000000000000000000..7f2e29138743cea047bb177667dd848be4372be1 --- /dev/null +++ b/docs/build/latex/sphinxpackagefootnote.sty @@ -0,0 +1,434 @@ +\NeedsTeXFormat{LaTeX2e} +\ProvidesPackage{sphinxpackagefootnote}% + [2024/05/17 v7.3.x Sphinx custom footnotehyper package (Sphinx team)] +%% +%% Package: sphinxpackagefootnote +%% Version: based on footnotehyper.sty 2021/02/04 v1.1d +%% https://www.ctan.org/pkg/footnotehyper +%% License: the one applying to Sphinx +%% +% Provides support for footnote mark-up from Sphinx latex writer: +% - "footnote" and "footnotetext" environments allowing verbatim material +% - "savenotes" environment for wrapping environments, such as for tables +% which have problems with LaTeX footnotes +% - hyperlinks +% +% Sphinx uses exclusively this mark-up for footnotes: +% - \begin{footnote}[N] +% - \begin{footnotetext}[N] +% - \sphinxfootnotemark[N] +% where N is a number. +% +%% Some small differences from upstream footnotehyper.sty: +%% - a tabulary compatibility layer (partial but enough for Sphinx), +%% - usage of \spx@opt@BeforeFootnote +%% - usage of \sphinxunactivateextrasandspace from sphinx.sty, +%% - \sphinxlongtablepatch +%% +%% Starting with Sphinx v4.5.0, inherited footnotehyper macros for +%% footnote/footnotetext receive some Sphinx specific extras to +%% implement "intelligent" footnote marks checking page numbers. +%% +%% All footnotes output from Sphinx are hyperlinked. With "savenotes" +%% footnotes may appear on page distinct from footnote mark, the latter +%% will indicate page number of the footnote. +\newif\iffootnotehyperparse\footnotehyperparsetrue +\DeclareOption*{\PackageWarning{sphinxpackagefootnote}{Option `\CurrentOption' is unknown}}% +\ProcessOptions\relax +\newbox\FNH@notes +\newtoks\FNH@toks % 1.1c +\newdimen\FNH@width +\let\FNH@colwidth\columnwidth +\newif\ifFNH@savingnotes +\AtBeginDocument {% + \let\FNH@latex@footnote \footnote + \let\FNH@latex@footnotetext\footnotetext + \let\FNH@H@@footnotetext \@footnotetext + \let\FNH@H@@mpfootnotetext \@mpfootnotetext + \newenvironment{savenotes} + {\FNH@savenotes\ignorespaces}{\FNH@spewnotes\ignorespacesafterend}% + \let\spewnotes \FNH@spewnotes + \let\footnote \FNH@footnote + \let\footnotetext \FNH@footnotetext + \let\endfootnote \FNH@endfntext + \let\endfootnotetext\FNH@endfntext + % always True branch taken with Sphinx + \@ifpackageloaded{hyperref} + {\ifHy@hyperfootnotes + \let\FNH@H@@footnotetext\H@@footnotetext + \let\FNH@H@@mpfootnotetext\H@@mpfootnotetext + \else + \let\FNH@hyper@fntext\FNH@nohyp@fntext + \fi}% + {\let\FNH@hyper@fntext\FNH@nohyp@fntext}% +}% +\def\FNH@hyper@fntext{\FNH@fntext\FNH@hyper@fntext@i}% +\def\FNH@nohyp@fntext{\FNH@fntext\FNH@nohyp@fntext@i}% +\def\FNH@fntext #1{% + \ifx\ifmeasuring@\@undefined + \expandafter\@secondoftwo\else\expandafter\@firstofone\fi +% these two lines modified for Sphinx (tabulary compatibility): + {\ifmeasuring@\expandafter\@gobbletwo\else\expandafter\@firstofone\fi}% + {\ifx\equation$\expandafter\@gobbletwo\fi #1}%$ +}% +\long\def\FNH@hyper@fntext@i#1{% + \global\setbox\FNH@notes\vbox + {\unvbox\FNH@notes + \FNH@startnote + \@makefntext + {\rule\z@\footnotesep\ignorespaces + \ifHy@nesting\expandafter\ltx@firstoftwo + \else\expandafter\ltx@secondoftwo + \fi + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}{#1}}% + {\Hy@raisedlink + {\expandafter\hyper@@anchor\expandafter{\Hy@footnote@currentHref}% + {\relax}}% + \let\@currentHref\Hy@footnote@currentHref + \let\@currentlabelname\@empty + #1}% + \@finalstrut\strutbox + }% + \FNH@endnote + }% +}% +\long\def\FNH@nohyp@fntext@i#1{% + \global\setbox\FNH@notes\vbox + {\unvbox\FNH@notes + \FNH@startnote + \@makefntext{\rule\z@\footnotesep\ignorespaces#1\@finalstrut\strutbox}% + \FNH@endnote + }% +}% +\def\FNH@startnote{% + \hsize\FNH@colwidth + \interlinepenalty\interfootnotelinepenalty + \reset@font\footnotesize + \floatingpenalty\@MM + \@parboxrestore + \protected@edef\@currentlabel{\csname p@\@mpfn\endcsname\@thefnmark}% + \color@begingroup +}% +\def\FNH@endnote{\color@endgroup}% +\def\FNH@savenotes{% + \begingroup + \ifFNH@savingnotes\else + \FNH@savingnotestrue + \let\@footnotetext \FNH@hyper@fntext + \let\@mpfootnotetext \FNH@hyper@fntext + \let\H@@mpfootnotetext\FNH@nohyp@fntext + \FNH@width\columnwidth + \let\FNH@colwidth\FNH@width + \global\setbox\FNH@notes\box\voidb@x + \let\FNH@thempfn\thempfn + \let\FNH@mpfn\@mpfn + \ifx\@minipagerestore\relax\let\@minipagerestore\@empty\fi + \expandafter\def\expandafter\@minipagerestore\expandafter{% + \@minipagerestore + \let\thempfn\FNH@thempfn + \let\@mpfn\FNH@mpfn + }% + \fi +}% +\def\FNH@spewnotes {% + \if@endpe\ifx\par\@@par\FNH@toks{}\else + \FNH@toks\expandafter{\expandafter + \def\expandafter\par\expandafter{\par}\@endpetrue}% + \expandafter\expandafter\expandafter + \FNH@toks + \expandafter\expandafter\expandafter + {\expandafter\the\expandafter\FNH@toks + \expandafter\def\expandafter\@par\expandafter{\@par}}% + \expandafter\expandafter\expandafter + \FNH@toks + \expandafter\expandafter\expandafter + {\expandafter\the\expandafter\FNH@toks + \expandafter\everypar\expandafter{\the\everypar}}\fi + \else\FNH@toks{}\fi + \expandafter + \endgroup\the\FNH@toks + \ifFNH@savingnotes\else + \ifvoid\FNH@notes\else + \begingroup + \let\@makefntext\@empty + \let\@finalstrut\@gobble + \let\rule\@gobbletwo + \ifx\@footnotetext\@mpfootnotetext + \expandafter\FNH@H@@mpfootnotetext + \else + \expandafter\FNH@H@@footnotetext + \fi{\unvbox\FNH@notes}% + \endgroup + \fi + \fi +}% +\def\FNH@footnote@envname {footnote}% +\def\FNH@footnotetext@envname{footnotetext}% +\def\FNH@footnote{% +% this line added for Sphinx: + \spx@opt@BeforeFootnote + \ifx\@currenvir\FNH@footnote@envname + \expandafter\FNH@footnoteenv + \else + \expandafter\FNH@latex@footnote + \fi +}% +\def\FNH@footnoteenv{% +% this line added for Sphinx (footnotes in parsed literal blocks): + \catcode13=5 \sphinxunactivateextrasandspace + \@ifnextchar[% + \FNH@footnoteenv@i %] + {\stepcounter\@mpfn + \protected@xdef\@thefnmark{\thempfn}% + \@footnotemark + \def\FNH@endfntext@fntext{\@footnotetext}% + \FNH@startfntext}% +}% +\def\FNH@footnoteenv@i[#1]{% + \begingroup + % This legacy code from LaTeX core restricts #1 to be digits only + % This limitation could be lifted but legacy Sphinx anyhow obeys it + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup +% -- Sphinx specific: +% currently commented out due to +% https://github.com/sphinx-doc/sphinx/pull/10191#issuecomment-1038807448 +% Memo: memoir class detection of successive footnote marks (to separate them +% by commas) is broken by \refstepcounter and also by \label, and some +% mitigation such as in \sphinxfootref would be needed + % \global\let\spx@saved@thefnmark\@thefnmark + % % this is done to access robustly the page number where footnote mark is + % \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}% + % % if possible, compare page numbers of mark and footnote to define \@thefnmark + % \ltx@ifundefined{r@\thesphinxscope.footnote.#1}% + % {}% one more latex run is needed + % {\sphinx@xdef@thefnmark{#1}}% check of page numbers possible +% -- + \@footnotemark + \def\FNH@endfntext@fntext{\@footnotetext}% +% -- Sphinx specific: + % we need to reset \@thefnmark as it is used by \FNH@startfntext via + % \FNH@startnote to set \@currentlabel which will be used by \label +% currently commented out (see above) + % \global\let\@thefnmark\spx@saved@thefnmark +% -- + \FNH@startfntext +% -- again Sphinx specific + % \@currentlabel as needed by \label got set by \FNH@startnote + % insert this at start of footnote text then the label will allow + % to robustly know on which page the footnote text ends up +% currently only of use for extra footnote marks so in case footnote multiply referred + \phantomsection\label{\thesphinxscope.footnote.#1}% +}% +\def\FNH@footnotetext{% + \ifx\@currenvir\FNH@footnotetext@envname + \expandafter\FNH@footnotetextenv + \else + \expandafter\FNH@latex@footnotetext + \fi +}% +\def\FNH@footnotetextenv{% + \@ifnextchar[% + \FNH@footnotetextenv@i %] + {\protected@xdef\@thefnmark{\thempfn}% + \def\FNH@endfntext@fntext{\@footnotetext}% + \FNH@startfntext}% +}% +\def\FNH@footnotetextenv@i[#1]{% + \begingroup + \csname c@\@mpfn\endcsname #1\relax + \unrestored@protected@xdef\@thefnmark{\thempfn}% + \endgroup + \ifFNH@savingnotes + \def\FNH@endfntext@fntext{\FNH@nohyp@fntext}% + \else + \def\FNH@endfntext@fntext{\FNH@H@@footnotetext}% + \fi + \FNH@startfntext +% -- Sphinx specific addition + \phantomsection\label{\thesphinxscope.footnote.#1}% +}% +\def\FNH@startfntext{% + \setbox\z@\vbox\bgroup + \FNH@startnote + \FNH@prefntext + \rule\z@\footnotesep\ignorespaces +}% +\def\FNH@endfntext {% + \@finalstrut\strutbox + \FNH@postfntext + \FNH@endnote + \egroup + \begingroup + \let\@makefntext\@empty\let\@finalstrut\@gobble\let\rule\@gobbletwo + \FNH@endfntext@fntext {\unvbox\z@}% + \endgroup +}% +\let\FNH@prefntext\@empty +\let\FNH@postfntext\@empty +\AtBeginDocument{\iffootnotehyperparse\expandafter\FNH@check\fi}% +\def\FNH@safeif#1{% + \iftrue\csname if#1\endcsname\csname fi\endcsname\expandafter\@firstoftwo + \else\csname fi\endcsname\expandafter\@secondoftwo + \fi +}% +\def\FNH@check{% + \ifx\@makefntextFB\@undefined\expandafter\FNH@check@ + \else\expandafter\FNH@frenchb@ + \fi +}% +\def\FNH@frenchb@{% + \def\FNH@prefntext{% + \localleftbox{}% + \let\FBeverypar@save\FBeverypar@quote + \let\FBeverypar@quote\relax + \FNH@safeif{FB@koma}% + {\FNH@safeif{FBFrenchFootnotes}% + {\ifx\footnote\thanks + \let\@@makefnmark\@@makefnmarkTH + \@makefntextTH{} % space as in french.ldf + \else + \let\@@makefnmark\@@makefnmarkFB + \@makefntextFB{} % space as in french.ldf + \fi + }{\let\@@makefnmark\@@makefnmarkORI + \@makefntextORI{}% no space as in french.ldf + }% + }% + {\FNH@safeif{FBFrenchFootnotes}% + {\@makefntextFB{}}% + {\@makefntextORI{}}% + }% + }% + \def\FNH@postfntext{% + \let\FBeverypar@quote\FBeverypar@save + \localleftbox{\FBeveryline@quote}% + }% +}% +\def\FNH@check@{% + \expandafter\FNH@check@a\@makefntext{1.2!3?4,}% + \FNH@@@1.2!3?4,\FNH@@@\relax +}% +\long\def\FNH@check@a #11.2!3?4,#2\FNH@@@#3{% + \ifx\relax#3\expandafter\FNH@checkagain@ + \else + \def\FNH@prefntext{#1}\def\FNH@postfntext{#2}% + \expandafter\FNH@check@b + \fi +}% +\def\FNH@checkagain@{% + \expandafter\FNH@checkagain@a + \detokenize\expandafter{\@makefntext{1.2!3?4,}}\relax\FNH@@@ +}% +\edef\FNH@temp{\noexpand\FNH@checkagain@a ##1\string{1.2!3?4,\string}}% +\expandafter\def\FNH@temp#2#3\FNH@@@{% + \ifx\relax#2% + \def\FNH@prefntext{\@makefntext{}}% + \else\FNH@bad@makefntext@alert + \fi +}% +\def\FNH@check@b #1\relax{% + \expandafter\expandafter\expandafter\FNH@check@c + \expandafter\meaning\expandafter\FNH@prefntext + \meaning\FNH@postfntext1.2!3?4,\FNH@check@c\relax +}% +\def\FNH@check@c #11.2!3?4,#2#3\relax{% + \ifx\FNH@check@c#2\else\FNH@bad@makefntext@alert\fi +}% +% slight reformulation for Sphinx +\def\FNH@bad@makefntext@alert{% + \sphinxbuildwarning{badfootnotes}% + \PackageWarningNoLine{sphinxpackagefootnote}% + {Footnotes will be sub-optimal, sorry. This is due to the document class or^^J + some package modifying macro \string\@makefntext.^^J + You can try to report this incompatibility at^^J + https://github.com/sphinx-doc/sphinx with this info:}% + \typeout{\meaning\@makefntext}% + \let\FNH@prefntext\@empty\let\FNH@postfntext\@empty +}% +% this macro from original footnote.sty is not used anymore by Sphinx +% but for simplicity sake let's just keep it as is +\def\makesavenoteenv{\@ifnextchar[\FNH@msne@ii\FNH@msne@i}%] +\def\FNH@msne@i #1{% + \expandafter\let\csname FNH$#1\expandafter\endcsname %$ + \csname #1\endcsname + \expandafter\let\csname endFNH$#1\expandafter\endcsname %$ + \csname end#1\endcsname + \FNH@msne@ii[#1]{FNH$#1}%$ +}% +\def\FNH@msne@ii[#1]#2{% + \expandafter\edef\csname#1\endcsname{% + \noexpand\savenotes + \expandafter\noexpand\csname#2\endcsname + }% + \expandafter\edef\csname end#1\endcsname{% + \expandafter\noexpand\csname end#2\endcsname + \noexpand\expandafter + \noexpand\spewnotes + \noexpand\if@endpe\noexpand\@endpetrue\noexpand\fi + }% +}% +% +% some extras for Sphinx : +% \sphinxfootnotemark: +% - if in section titles will auto-remove itself from TOC +\def\sphinxfootnotemark [#1]% + {\ifx\thepage\relax\else\sphinxfootref{#1}\fi}% +\newcounter{sphinxfootnotemark} +\renewcommand\thesphinxfootnotemark{\number\value{sphinxfootnotemark}} +% - compares page number of footnote mark versus the one of footnote text +\def\sphinx@xdef@thefnmark#1{% + \expandafter\expandafter\expandafter\sphinx@footref@get + \csname r@\thesphinxscope.footnote.#1\endcsname\relax + \expandafter\expandafter\expandafter\sphinx@footmark@getpage + \csname r@footnotemark.\thesphinxfootnotemark\endcsname\thepage\relax + \protected@xdef\@thefnmark{% + \ifx\spx@footmarkpage\spx@footrefpage + \spx@footreflabel + \else + % the macro \sphinxthefootnotemark is in sphinx.sty + \sphinxthefootnotemark{\spx@footreflabel}{\spx@footrefpage}% + \fi + }% +}% +\def\sphinx@footref@get #1#2#3#4#5\relax{% + \def\spx@footreflabel{#1}% + \def\spx@footrefpage {#2}% + \def\spx@footrefHref {#4}% +}% +\def\sphinx@footmark@getpage #1#2#3\relax{% + \edef\spx@footmarkpage{#2}% +}% +\protected\def\sphinxfootref#1{% #1 always is explicit number in Sphinx + \spx@opt@BeforeFootnote + % each of \refstepcounter and \label interferes with memoir class detection + % of successive footnote marks, so we move them to inside \@makefnmark + \let\spx@saved@makefnmark\@makefnmark + \ltx@ifundefined{r@\thesphinxscope.footnote.#1}% + {\gdef\@thefnmark{?}% on first LaTeX run + \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}% + }% + {\def\@makefnmark{% will be used by \H@@footnotemark + \refstepcounter{sphinxfootnotemark}\label{footnotemark.\thesphinxfootnotemark}% + \sphinx@xdef@thefnmark{#1}% also defines \spx@footrefHref + % must be executed after \refstepcounter + \hyper@linkstart{link}{\spx@footrefHref}% + \spx@saved@makefnmark + \hyper@linkend + }% + }% + \H@@footnotemark + \let\@makefnmark\spx@saved@makefnmark +}% +\AtBeginDocument{% + % let hyperref less complain + \pdfstringdefDisableCommands{\def\sphinxfootnotemark [#1]{}}% + % to obtain hyperlinked footnotes in longtable environment we must replace + % hyperref's patch of longtable's patch of \@footnotetext by our own + \let\LT@p@ftntext\FNH@hyper@fntext + % this *requires* longtable to be used always wrapped in savenotes environment +}% +\endinput +%% +%% End of file `sphinxpackagefootnote.sty'. diff --git a/docs/build/latex/sphinxpackagesubstitutefont.sty b/docs/build/latex/sphinxpackagesubstitutefont.sty new file mode 100644 index 0000000000000000000000000000000000000000..536bf20ff4b8b31a416ab9892066cb130fa3bcf0 --- /dev/null +++ b/docs/build/latex/sphinxpackagesubstitutefont.sty @@ -0,0 +1,21 @@ +%% a stub for obsoleted LaTeX package substitutefont +% The package substitutefont stopped being distributed with TeXLive +% around August 2023 and was moved to "obsolete" section. +% cf https://ctan.org/pkg/substitutefont +% Trying to load it raises a LaTeX build error since. + +% The \substitutefont has a LaTeX kernel replacement +% \DeclareFontFamilySubstitution +% which was added to LaTeX 2020-02-02 +% The aim of this stub is to do that replacement silently. + +% change this info string if making any custom modification +\ProvidesPackage{sphinxpackagesubstitutefont}[2023/15/11 v7.3.0 substitutefont stub] + +\ifdefined\DeclareFontFamilySubstitution + \def\substitutefont{\DeclareFontFamilySubstitution} +\else + \usepackage{substitutefont} +\fi + +\endinput diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 0000000000000000000000000000000000000000..8f56bebd6272bc9c7883ae04b97824d95e0e1056 --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,35 @@ +@ECHO OFF + +pushd %~dp0 + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set SOURCEDIR=. +set BUILDDIR=build + +%SPHINXBUILD% >NUL 2>NUL +if errorlevel 9009 ( + echo. + echo.The 'sphinx-build' command was not found. Make sure you have Sphinx + echo.installed, then set the SPHINXBUILD environment variable to point + echo.to the full path of the 'sphinx-build' executable. Alternatively you + echo.may add the Sphinx directory to PATH. + echo. + echo.If you don't have Sphinx installed, grab it from + echo.https://www.sphinx-doc.org/ + exit /b 1 +) + +if "%1" == "" goto help + +%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% +goto end + +:help +%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O% + +:end +popd diff --git a/docs/source/conf.py b/docs/source/conf.py new file mode 100644 index 0000000000000000000000000000000000000000..aea49532eaf2cc8b6fe802011694cd1574c887c3 --- /dev/null +++ b/docs/source/conf.py @@ -0,0 +1,61 @@ +# Configuration file for the Sphinx documentation builder. +# +# For the full list of built-in configuration values, see the documentation: +# https://www.sphinx-doc.org/en/master/usage/configuration.html + +# -- Project information ----------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information + +import os +import sys +sys.path.insert(0, os.path.abspath('../../src/')) + +project = 'AIM-CU' +copyright = '2024, Smriti Prathapan, Berkman Sahiner, Dhaval Kadia, Ravi K. Samala' +author = 'Smriti Prathapan, Berkman Sahiner, Dhaval Kadia, Ravi K. Samala' +release = '1.0.0' +version = '1.0.0' + +# -- General configuration --------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration + +extensions = ['sphinx.ext.autodoc', + 'sphinx.ext.coverage', + 'sphinx.ext.napoleon', + 'sphinx.ext.autosummary', + 'sphinx.ext.duration', + 'sphinx_tabs.tabs', + 'sphinx_simplepdf', + # 'sphinxcontrib.inkscapeconverter', + # 'rinoh.frontend.sphinx', + # 'sphinx_pdf_generate' + ] + +templates_path = ['_templates'] +exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store'] + + + +# -- Options for HTML output ------------------------------------------------- +# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output + +html_theme = 'alabaster' +# html_static_path = ['_static'] + +html_show_copyright = False +html_theme_options = { + 'sidebar_width': '300px', + 'page_width': '1200px', + 'body_max_width': 'auto', + 'github_button': 'true', + 'github_user': 'DIDSR', + 'github_repo': 'AIM-CU', +} +# html_sidebars = {'**': ['searchbox.html', 'globaltoc.html', 'sourcelink.html']} + +latex_elements = { + 'preamble': r''' + \DeclareUnicodeCharacter{03BC}{\textmu} + \DeclareUnicodeCharacter{03C3}{\ensuremath{\sigma}} + ''', +} diff --git a/docs/source/index.rst b/docs/source/index.rst new file mode 100644 index 0000000000000000000000000000000000000000..bcea0f64f0b1a5804fda25694d2447acf2c2ee12 --- /dev/null +++ b/docs/source/index.rst @@ -0,0 +1,52 @@ +.. AIM-CU documentation master file, created by + sphinx-quickstart on Wed Nov 27 09:59:49 2024. + You can adapt this file completely to your liking, but it should at least + contain the root `toctree` directive. + +AIM-CU documentation +==================== + +A CUSUM-based tool for AI Monitoring + +AIM-CU is a statistical tool for AI monitoring using cumulative sum (AIM-CU). AIM-CU computes: + +* The parameter choices for change-point detection based on an acceptable false alarm rate +* Detection delay estimates for a given displacement of the performance metric from the target for those parameter choices. + +Code execution +------------------ +Clone AIM-CU repository. + +.. code-block:: shell + + git clone https://github.com/DIDSR/AIM-CU.git + +Run the following commands to install required dependencies (Python = 3.10 is used). + +.. code-block:: shell + + apt-get -y install python3 + apt-get -y install pip + cd AIM-CU + pip install -r requirements.txt + +Run AIM-CU. + +.. code-block:: shell + + python3 app.py + +Open the URL http://0.0.0.0:7860 that is running the AIM-CU locally. + +Demo +------------------ +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. + +.. toctree:: + :maxdepth: 2 + :caption: Contents: + + ref_method + ref_cusum + ref_theoretical + ref_utils \ No newline at end of file diff --git a/docs/source/ref_cusum.rst b/docs/source/ref_cusum.rst new file mode 100644 index 0000000000000000000000000000000000000000..1d643a3359ce74c9756d3b4a5ae1d51d59cc4c29 --- /dev/null +++ b/docs/source/ref_cusum.rst @@ -0,0 +1,5 @@ +CUSUM +===== + +.. automodule:: package.cusum + :members: \ No newline at end of file diff --git a/docs/source/ref_method.rst b/docs/source/ref_method.rst new file mode 100644 index 0000000000000000000000000000000000000000..dc977457222b6c074ef7bd843f8ac8a4f27d537e --- /dev/null +++ b/docs/source/ref_method.rst @@ -0,0 +1,32 @@ +Methods +======= + +CUSUM parameters +---------------- + +.. csv-table:: CUSUM parameters + :file: ../../assets/params.csv + :header-rows: 1 + +CUSUM chart +----------- + +A two-sided CUSUM control chart computes the cumulative differences or +deviations of individual observations from the target mean (or +in-control mean, :math:`\mu_{in}`). The positive and negative cumulative +sums are calculated: + +.. math:: + + \\ S_{hi}(d) = max(0, S_{hi}(d-1) + x_d - \hat{\mu}_{in} - K) + \\ S_{lo}(d) = max(0, S_{lo}(d-1) - x_d + \hat{\mu}_{in} - K) + +where *d* denotes a unit of time, :math:`x_d` is the value of quantity +being monitored at time :math:`d`, :math:`\hat{\mu}_{in}` is the +in-control mean of :math:`x_d`, and :math:`K` is a "reference value" +related to the magnitude of change that one is interested in detecting. +:math:`S_{hi}` and :math:`S_{lo}` are the cumulative sum of positive and +negative changes. To detect a change in the observed values from the +in-control mean, the CUSUM scheme accumulates deviations that are +:math:`K` units away from the in-control mean. Let :math:`\sigma_{in}` +denote the in-control standard deviation of :math:`x_d`. \ No newline at end of file diff --git a/docs/source/ref_theoretical.rst b/docs/source/ref_theoretical.rst new file mode 100644 index 0000000000000000000000000000000000000000..3fc8048e19a2ef49d4393e40b2b77d2f2d5d52f6 --- /dev/null +++ b/docs/source/ref_theoretical.rst @@ -0,0 +1,5 @@ +ARLTheoretical +============== + +.. automodule:: package.ARLTheoretical + :members: \ No newline at end of file diff --git a/docs/source/ref_utils.rst b/docs/source/ref_utils.rst new file mode 100644 index 0000000000000000000000000000000000000000..7eeb201a370e1cbdc0bb5200b5c761899a99cb54 --- /dev/null +++ b/docs/source/ref_utils.rst @@ -0,0 +1,5 @@ +Utils +===== + +.. automodule:: package.utils + :members: \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000000000000000000000000000000000000..79a5c6d93c3dd2d9cad9c03363e4c0ab507137a0 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,15 @@ +numpy==2.1.1 +pandas==2.2.2 +gradio==4.43.0 +datasets==2.21.0 +plotly==5.24.0 +nbformat>=4.2.0 +tomli +rpy2==3.5.1 +great_tables==0.11.0 +kaleido +selenium +sphinx +sphinxcontrib-napoleon +sphinx-simplepdf +jupyter \ No newline at end of file diff --git a/src/package/.ipynb_checkpoints/app-checkpoint.py b/src/package/.ipynb_checkpoints/app-checkpoint.py new file mode 100644 index 0000000000000000000000000000000000000000..2969d0c0177b8811cdbc7190f9a291e008b1eef3 --- /dev/null +++ b/src/package/.ipynb_checkpoints/app-checkpoint.py @@ -0,0 +1,333 @@ +""" +Gradio user interface for AIM-CU +""" + +import os +import sys +import pandas as pd +import gradio as gr +import tomli +from cusum import CUSUM +from ARLTheoretical import get_ref_value, get_ref_value_k, get_ARL_1, get_ARL_1_h_mu1_k +from utils import ( + populate_summary_table_ARL0_k, + populate_summary_table_ARL1_k, +) +import great_tables as gt +import plotly.graph_objects as go + + +def populate_table(h: str) -> tuple[gt.GT, gt.GT]: + """ + Populate tables for ARL0 and ARL1 given the value of h + + Args: + h (str): Normalized threshold. + + Returns: + tuple[gt.GT, gt.GT]: Table for ARL0 and k in HTML format; table for ARL1 and k in HTML format. + """ + h = float(h) + + summary_table_df_ARL0_k, dict_ARL0_k = get_ref_value( + h=h, + list_ARL_0=config["params_cusum"]["list_ARL_0"], + ) + summary_table_df_ARL0_k = summary_table_df_ARL0_k.applymap(lambda x: '{:.2f}'.format(x) if isinstance(x, (float)) else x) + + summary_table_df_ARL1_k = get_ARL_1( + h=h, + shift_in_mean=config["params_cusum"]["shift_in_mean"], + dict_ARL0_k=dict_ARL0_k, + ) + summary_table_df_ARL1_k = summary_table_df_ARL1_k.applymap(lambda x: '{:.2f}'.format(x) if isinstance(x, (float)) else x) + + return populate_summary_table_ARL0_k( + summary_table_df_ARL0_k, h + ), populate_summary_table_ARL1_k(summary_table_df_ARL1_k, dict_ARL0_k, h) + + +def calculate_reference_value_k(h: str, arl_0: str) -> float: + """ + Gets the reference value for given h and ARL_0. + + Args: + h (str): Normalized threshold. + arl_0 (str): ARL0 value. + + Returns: + float: Normalized reference value k. + """ + h = float(h) + arl_0 = float(arl_0) + + k = get_ref_value_k(h=h, ARL_0=arl_0) + k = '{:.2f}'.format(k) + + return k + + +def calculate_arl1_h_k_mu1(h: str, k: str, mu1: str) -> float: + """ + Get the ARL_1 with given Shift in Mean (mu1) and k. + + Args: + h (str): Normalized threshold. + k (str): Normalized reference value. + mu1 (str): Intended shift in mean. + + Returns: + float: Detection delay (ARL1). + """ + h = float(h) + k = float(k) + mu1 = float(mu1) + + arl_1 = get_ARL_1_h_mu1_k(h=h, k=k, mu1=mu1) + arl_1 = '{:.2f}'.format(arl_1) + + return arl_1 + + +def populate_cusum_plots( + file_csv_metric: gr.File, + ref_value: str, + normalized_threshold: str, + pre_change_days: str, +) -> tuple[go.Figure, go.Figure]: + """ + Populate CUSUM plots + + Args: + file_csv_metric (gr.File): CSV file with metric data + ref_value (str): Normalized reference value for detecting a unit standard deviation change in mean of the process. + normalized_threshold (str): Normalized threshold. + pre_change_days (str): Number of days for in-control phase. + + Returns: + tuple[go.Figure, go.Figure]: Scatter plot as Plotly graph object; CUSUM plot using Plotly graph object. + """ + ref_value = float(ref_value) + normalized_threshold = float(normalized_threshold) + pre_change_days = int(pre_change_days) + + if file_csv_metric is not None: + # upload CSV file + data_csv_metric = pd.read_csv(file_csv_metric.name) + obj_cusum.set_df_metric_csv(data_csv_metric) + else: + # use the example CSV data + obj_cusum.set_df_metric_default() + + obj_cusum.change_detection( + pre_change_days=pre_change_days, + normalized_ref_value=ref_value, + normalized_threshold=normalized_threshold, + ) + + return (obj_cusum.plot_input_metric_plotly(), obj_cusum.plot_cusum_plotly()) + + +with gr.Blocks( + theme=gr.themes.Base( + neutral_hue=gr.themes.Color( + c50="#e5f1f8", + c100="#e5f1f8", + c200="#cce4f1", + c300="#b2d7ea", + c400="#7fbddc", + c500="#4ca3ce", + c600="#007cba", + c700="#006394", + c800="#004a6f", + c900="#00314a", + c950="#001825", + ), + ) +) as demo: + gr.Markdown(f""" + # AIM-CU + ## AIM-CU: A statistical tool for AI monitoring using cumulative sum (AIM-CU). + """) # noqa: F541 + + gr.Markdown(f""" + ### AIM-CU Input: + AI output (e.g. metrics such as Accuracy, F1-score, Sensitivity etc.) + """) # noqa: F541 + + with gr.Row(): + with gr.Column(): + gr.Markdown(f""" + ### Phase I: + Parameter choices for detecting change and detection delay estimates (theoretical calculations). + """) # noqa: F541 + + gr.Markdown(f""" + ### Enter h value: + """) # noqa: F541 + + h_phase1 = gr.Textbox( + label="h value =", + placeholder="h = normalized threshold, default = 4", + value="4", + autofocus=True, + ) + + dataframe_gt_ref_value = gr.HTML( + label="Reference Values for an intended ARL0 with normalized threshold h", + show_label=True, + visible=False, + ) + + gr.Markdown(f""" + ### Calculate reference value k for a specific value for ARL0: + """) # noqa: F541 + + with gr.Row(): + arl_0 = gr.Textbox( + label="ARL_0 value =", placeholder="ARL_0", value="100" + ) + + button_calculate_k = gr.Button("Calculate k") + + output_k = gr.Textbox(label="Calculated k =", visible=False) + + dataframe_gt_ARL0 = gr.HTML( + label="Estimate of steady state ARL (ARL_1 based on the computed reference values and intended zero-state ARL (ARL_0) with normalized threshold h)", + show_label=True, + visible=False, + ) + + gr.Markdown(f""" + ### Calculate ARL1 for reference value h, value k and shift in mean: + """) # noqa: F541 + + with gr.Row(): + k_phase1 = gr.Textbox( + label="k value =", placeholder="k", value="0.2996" + ) + mu1 = gr.Textbox( + label="Shift in mean value =", + placeholder="Shift in mean value", + value="1.2", + ) + + button_calculate_ARL_1 = gr.Button("Calculate ARL_1") + + output_ARL_1 = gr.Textbox(label="Calculated ARL_1 =", visible=False) + + button_populate_table = gr.Button( + "Populate Reference Values and ARL_1 tables for the given h value" + ) + + gr.Markdown(f""" + ### Upload the CSV file with metric. Or use the default example CSV file by directly clicking the button below. + """) # noqa: F541 + + # load the CSV file with specifities across days + csv_file_metric = gr.File( + file_types=["csv"], + label="Upload CSV file with metric across days", + ) + with gr.Column(): + gr.Markdown(f""" + ### Phase II: + Performance drift detection plots, pre- and post-change distribution with respect to the performance drift detected. + """) # noqa: F541 + + gr.Markdown(f""" + ### Enter required values: + """) # noqa: F541 + + with gr.Row(): + h_phase2 = gr.Textbox( + label="h value =", + placeholder="normalized threshold, default = 4", + value="4", + ) + + k_phase2 = gr.Textbox( + label="k value =", + placeholder="normalized reference value, default = 0.5", + value="0.5", + ) + + pre_change_days = gr.Textbox( + label="In-control days =", + placeholder="Number of days for in-control phase, default = 60", + value="60", + ) + + button_csv_metric = gr.Button("Show CUSUM plots") + + plot_avg_metric = gr.Plot( + label="Average metric for the pre-change and post-change regime", + visible=False, + ) + plot_cusum_chart = gr.Plot(label="CUSUM Chart", visible=False) + + # Get the CSV file and populate tables + button_populate_table.click( + fn=populate_table, + inputs=[h_phase1], + outputs=[dataframe_gt_ref_value, dataframe_gt_ARL0], + ) + button_populate_table.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=dataframe_gt_ref_value + ) + button_populate_table.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=dataframe_gt_ARL0 + ) + + # Calculate specific k for ARL_0 + button_calculate_k.click( + fn=calculate_reference_value_k, inputs=[h_phase1, arl_0], outputs=[output_k] + ) + button_calculate_k.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=output_k + ) + + # Calculate specific ARL_1 for value h, value k and shift in mean + button_calculate_ARL_1.click( + fn=calculate_arl1_h_k_mu1, inputs=[h_phase1, k_phase1, mu1], outputs=[output_ARL_1] + ) + button_calculate_ARL_1.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=output_ARL_1 + ) + + # Get the CSV file and populate plots + button_csv_metric.click( + fn=populate_cusum_plots, + inputs=[csv_file_metric, k_phase2, h_phase2, pre_change_days], + outputs=[plot_avg_metric, plot_cusum_chart], + ) + + button_csv_metric.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=plot_avg_metric + ) + button_csv_metric.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=plot_cusum_chart + ) + +try: + path_file_config = os.path.abspath("../../config/config.toml") + + with open(path_file_config, "rb") as file_config: + config = tomli.load(file_config) +except FileNotFoundError: + print("Error: config.toml not found at", path_file_config) + sys.exit(1) + + +if config["control"]["save_figure"] == "true": + path_check = os.path.abspath( + os.path.join("../../", config["path_output"]["path_figure"]) + ) + if not os.path.exists(path_check): + os.mkdir(path_check) + print("Created", path_check) + +obj_cusum = CUSUM() +obj_cusum.initialize() + +demo.launch(server_name="0.0.0.0", server_port=7860) diff --git a/src/package/.ipynb_checkpoints/example_AIM_CU-checkpoint.ipynb b/src/package/.ipynb_checkpoints/example_AIM_CU-checkpoint.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..82534ee1b589ca2462ece75884eb868ba674f953 --- /dev/null +++ b/src/package/.ipynb_checkpoints/example_AIM_CU-checkpoint.ipynb @@ -0,0 +1,2997 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 29, + "id": "9296d4be-eb69-47a7-a3b4-d6111231e018", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nExample on Cumulative Sum (CUSUM)\\n\\n@author: smriti.prathapan\\n'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Example on Cumulative Sum (CUSUM)\n", + "\n", + "@author: smriti.prathapan\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "2a3c98bd", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import pandas as pd\n", + "from cusum import CUSUM" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "bd11f2ea", + "metadata": {}, + "outputs": [], + "source": [ + "# Absolute path to the metric file in CSV format\n", + "file_csv_metric = None # Use your own file here, else it will use /config/spec-60-60.csv\n", + "\n", + "# Normalized reference value for detecting a unit standard deviation change in mean of the process\n", + "ref_value = 0.5\n", + "# Normalized threshold value\n", + "normalized_threshold = 4\n", + "# Number of days for in-control phase\n", + "pre_change_days = 60 # An integer value" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "bd01cab4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Change-point with respect to S_lo is: 60\n" + ] + } + ], + "source": [ + "obj_cusum = CUSUM()\n", + "obj_cusum.initialize()\n", + "\n", + "if file_csv_metric is not None:\n", + " # upload CSV file\n", + " data_csv_metric = pd.read_csv(file_csv_metric.name)\n", + " obj_cusum.set_df_metric_csv(data_csv_metric)\n", + "else:\n", + " # use the example CSV data\n", + " obj_cusum.set_df_metric_default()\n", + "\n", + "# Set initial days and get in-control mean and standard deviation\n", + "obj_cusum.set_init_stats(init_days=30)\n", + "\n", + "# Detects a change in the process\n", + "obj_cusum.change_detection(\n", + " normalized_ref_value=ref_value,\n", + " normalized_threshold=normalized_threshold,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "4ebf2fd5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "darkturquoise", + "size": 10 + }, + "mode": "markers", + "name": "In-control Sp", + "opacity": 0.4, + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59 + ], + "xaxis": "x", + "y": [ + 0.8426395939086294, + 0.8913043478260869, + 0.8826530612244898, + 0.8308457711442786, + 0.7679558011049724, + 0.8444444444444444, + 0.8306878306878307, + 0.8308457711442786, + 0.8936170212765957, + 0.8138297872340425, + 0.7747252747252747, + 0.8052631578947368, + 0.8090452261306532, + 0.8317757009345794, + 0.8958333333333334, + 0.8306878306878307, + 0.8556701030927835, + 0.8387096774193549, + 0.7894736842105263, + 0.8563829787234043, + 0.8186813186813187, + 0.8306878306878307, + 0.7918781725888325, + 0.8823529411764706, + 0.8737373737373737, + 0.8666666666666667, + 0.8518518518518519, + 0.8659217877094972, + 0.8232044198895028, + 0.8764044943820225, + 0.8167539267015707, + 0.8478260869565217, + 0.8363636363636363, + 0.797752808988764, + 0.8309859154929577, + 0.875, + 0.8, + 0.8608247422680413, + 0.8288770053475936, + 0.8556149732620321, + 0.8153846153846154, + 0.859375, + 0.8324607329842932, + 0.9043062200956936, + 0.8279569892473119, + 0.8197674418604651, + 0.7795698924731183, + 0.8135593220338984, + 0.8481675392670157, + 0.8134715025906736, + 0.7864583333333334, + 0.8548387096774194, + 0.8370786516853933, + 0.7157360406091371, + 0.8324607329842932, + 0.8296703296703297, + 0.8844221105527639, + 0.7884615384615384, + 0.935, + 0.8840579710144928 + ], + "yaxis": "y" + }, + { + "marker": { + "color": "coral", + "size": 10 + }, + "mode": "markers", + "name": "Out-of-control Sp", + "opacity": 0.4, + "type": "scatter", + "x": [ + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "xaxis": "x", + "y": [ + 0.75, + 0.8324607329842932, + 0.7939698492462312, + 0.7272727272727273, + 0.8284313725490197, + 0.7692307692307693, + 0.8010204081632653, + 0.8235294117647058, + 0.7277486910994765, + 0.775, + 0.8361581920903954, + 0.7959183673469388, + 0.8489583333333334, + 0.8465346534653465, + 0.812807881773399, + 0.7475247524752475, + 0.8491620111731844, + 0.6989247311827957, + 0.7967914438502673, + 0.7236180904522613, + 0.746031746031746, + 0.7371428571428571, + 0.7839195979899497, + 0.7921348314606742, + 0.8258706467661692, + 0.8121827411167513, + 0.8258426966292135, + 0.7675675675675676, + 0.6666666666666666, + 0.7872340425531915, + 0.8325123152709359, + 0.8247422680412371, + 0.7619047619047619, + 0.7967032967032966, + 0.867816091954023, + 0.8010471204188482, + 0.625, + 0.7684210526315789, + 0.7409326424870466, + 0.7593582887700535, + 0.8041237113402062, + 0.8160919540229885, + 0.803030303030303, + 0.6898395721925134, + 0.7037037037037037, + 0.8219895287958116, + 0.8153846153846154, + 0.712707182320442, + 0.7548076923076923, + 0.8258426966292135, + 0.8, + 0.7444444444444445, + 0.7604166666666666, + 0.7446808510638298, + 0.7845303867403315, + 0.7616279069767442, + 0.7525773195876289, + 0.7213930348258707, + 0.8222222222222222, + 0.817258883248731 + ], + "yaxis": "y" + }, + { + "line": { + "color": "darkturquoise", + "dash": "dash" + }, + "mode": "lines", + "name": "In-control mean", + "type": "scatter", + "x": [ + 0, + 59 + ], + "xaxis": "x", + "y": [ + 0.8368330003971066, + 0.8368330003971066 + ], + "yaxis": "y" + }, + { + "line": { + "color": "coral", + "dash": "dash" + }, + "mode": "lines", + "name": "Out-of-control mean", + "type": "scatter", + "x": [ + 60, + 119 + ], + "xaxis": "x", + "y": [ + 0.7794127721177365, + 0.7794127721177365 + ], + "yaxis": "y" + }, + { + "line": { + "color": "grey", + "dash": "dash" + }, + "mode": "lines", + "name": "Change-point", + "type": "scatter", + "x": [ + 60, + 60 + ], + "xaxis": "x", + "y": [ + 0.625, + 0.935 + ], + "yaxis": "y" + }, + { + "marker": { + "color": "mediumturquoise" + }, + "nbinsy": 15, + "opacity": 0.4, + "orientation": "h", + "showlegend": false, + "type": "histogram", + "xaxis": "x2", + "y": [ + 0.8426395939086294, + 0.8913043478260869, + 0.8826530612244898, + 0.8308457711442786, + 0.7679558011049724, + 0.8444444444444444, + 0.8306878306878307, + 0.8308457711442786, + 0.8936170212765957, + 0.8138297872340425, + 0.7747252747252747, + 0.8052631578947368, + 0.8090452261306532, + 0.8317757009345794, + 0.8958333333333334, + 0.8306878306878307, + 0.8556701030927835, + 0.8387096774193549, + 0.7894736842105263, + 0.8563829787234043, + 0.8186813186813187, + 0.8306878306878307, + 0.7918781725888325, + 0.8823529411764706, + 0.8737373737373737, + 0.8666666666666667, + 0.8518518518518519, + 0.8659217877094972, + 0.8232044198895028, + 0.8764044943820225, + 0.8167539267015707, + 0.8478260869565217, + 0.8363636363636363, + 0.797752808988764, + 0.8309859154929577, + 0.875, + 0.8, + 0.8608247422680413, + 0.8288770053475936, + 0.8556149732620321, + 0.8153846153846154, + 0.859375, + 0.8324607329842932, + 0.9043062200956936, + 0.8279569892473119, + 0.8197674418604651, + 0.7795698924731183, + 0.8135593220338984, + 0.8481675392670157, + 0.8134715025906736, + 0.7864583333333334, + 0.8548387096774194, + 0.8370786516853933, + 0.7157360406091371, + 0.8324607329842932, + 0.8296703296703297, + 0.8844221105527639, + 0.7884615384615384, + 0.935, + 0.8840579710144928 + ], + "yaxis": "y2" + }, + { + "marker": { + "color": "coral" + }, + "nbinsy": 15, + "opacity": 0.4, + "orientation": "h", + "showlegend": false, + "type": "histogram", + "xaxis": "x2", + "y": [ + 0.75, + 0.8324607329842932, + 0.7939698492462312, + 0.7272727272727273, + 0.8284313725490197, + 0.7692307692307693, + 0.8010204081632653, + 0.8235294117647058, + 0.7277486910994765, + 0.775, + 0.8361581920903954, + 0.7959183673469388, + 0.8489583333333334, + 0.8465346534653465, + 0.812807881773399, + 0.7475247524752475, + 0.8491620111731844, + 0.6989247311827957, + 0.7967914438502673, + 0.7236180904522613, + 0.746031746031746, + 0.7371428571428571, + 0.7839195979899497, + 0.7921348314606742, + 0.8258706467661692, + 0.8121827411167513, + 0.8258426966292135, + 0.7675675675675676, + 0.6666666666666666, + 0.7872340425531915, + 0.8325123152709359, + 0.8247422680412371, + 0.7619047619047619, + 0.7967032967032966, + 0.867816091954023, + 0.8010471204188482, + 0.625, + 0.7684210526315789, + 0.7409326424870466, + 0.7593582887700535, + 0.8041237113402062, + 0.8160919540229885, + 0.803030303030303, + 0.6898395721925134, + 0.7037037037037037, + 0.8219895287958116, + 0.8153846153846154, + 0.712707182320442, + 0.7548076923076923, + 0.8258426966292135, + 0.8, + 0.7444444444444445, + 0.7604166666666666, + 0.7446808510638298, + 0.7845303867403315, + 0.7616279069767442, + 0.7525773195876289, + 0.7213930348258707, + 0.8222222222222222, + 0.817258883248731 + ], + "yaxis": "y2" + }, + { + "line": { + "color": "mediumturquoise", + "dash": "dash" + }, + "mode": "lines", + "showlegend": false, + "type": "scatter", + "x": [ + 0, + 20 + ], + "xaxis": "x2", + "y": [ + 0.8368330003971066, + 0.8368330003971066 + ], + "yaxis": "y2" + } + ], + "layout": { + "barmode": "overlay", + "legend": { + "orientation": "h", + "x": 1, + "xanchor": "right", + "y": 1.02, + "yanchor": "bottom" + }, + "plot_bgcolor": "#F3F9FC", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "font": { + "size": 20, + "weight": "bold" + }, + "text": "Pre- and post-change observations and their respective histograms" + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 0.6859999999999999 + ], + "dtick": 20, + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Length of Simulation (days)" + } + }, + "xaxis2": { + "anchor": "y2", + "domain": [ + 0.706, + 1 + ], + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Count" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "AI model metric" + } + }, + "yaxis2": { + "anchor": "x2", + "domain": [ + 0, + 1 + ], + "matches": "y", + "showticklabels": false + } + } + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAABF4AAAFoCAYAAABuXz/oAAAgAElEQVR4XuydCbxNVRvGX+695lnRQGWqJJGSJiVKRaUSGdIkFUUJyVSGMitKSlIaNFAZkogKldJIIVOUIVLmmXuv733Wte+373H2OXufc/Y95/Ks79eHe9dee+3/WnvttZ71vu/KdViTMJEACZAACZAACZAACZAACZAACZAACZAACcScQC4KLzFnygJJgARIgARIgARIgARIgARIgARIgARIwBCg8MKOQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAI+EaDw4hNYFksCJEACJEACJEACJEACJEACJEACJEACFF7YB0iABEiABEiABEiABEiABEiABEiABEjAJwIUXnwCy2JJgARIgARIgARIgARIgARIgARIgARIgMIL+wAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ+ESAwotPYFksCZAACZAACZAACZAACZAACZAACZAACVB4YR8gARIgARIgARIgARIgARIgARIgARIgAZ8IUHjxCSyLJQESIAESIAESIAESIAESIAESIAESIAEKL+wDJEACJEACJEACJEACJEACJEACJEACJOATAQovPoFlsSRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA4YV9gARIgARIgARIgARIgARIgARIgARIgAR8IkDhxSewLJYESIAESIAESIAESIAESIAESIAESIAEKLywD5AACZAACZAACZAACZAACZAACZAACZCATwQovPgElsWSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAIUX9gESIAESIAESIAESIAESIAESIAESIAES8IkAhRefwLJYEiABEiABEiABEiABEiABEiABEiABEqDwwj5AAiRAAiRAAiRAAiRAAiRAAiRAAiRAAj4RoPDiE1gWSwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIUXtgHSIAESIAESIAESIAESIAESIAESIAESMAnAhRefALLYkmABEiABEiABEiABEiABEiABEiABEiAwgv7AAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn4RIDCi09gWSwJkAAJkAAJkAAJkAAJkAAJkAAJkAAJUHhhHyABEiABEiABEiABEiABEiABEiABEiABnwhQePEJLIslARIgARIgARIgARIgARIgARIgARIgAQov7AMkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4BMBCi8+gWWxJEACJEACJEACJEACJEACJEACJEACJEDhhX2ABEiABEiABEiABEiABEiABEiABEiABHwiQOHFJ7AslgRIgARIgARIgARIgARIgARIgARIgAQovLAPkAAJkAAJkAAJkAAJkAAJkAAJkAAJkIBPBCi8+ASWxZIACZAACZAACZAACZAACZAACZAACZAAhRf2ARIgARIgARIgARIgARIgARIgARIgARLwiQCFF5/AslgSIAESIAESIAESIAESIAESIAESIAESoPDCPkACJEACJEACJEACJEACJEACJEACJEACPhGg8OIT2JxY7Mo16+Xme3qaqje/uZ70fLRVTnwMX+q86d+tUq/JY6bsG66+RAb1fMCX+xxLhfYa/Jp8NH2eeaRPxw+S004tfSw9XlTP8vFn8+WJ/q+YMvp0vkduu+HKqMo7Hi5+9MmRMmvej+ZRv57yghQvWjiix76uxeOy7u/NUuqEYvLlB8MjKsPpIvb5mOJ0LCwROHt9h/kNyZ6+wbuQAAmQAAmQQKISOC6El059RsmML78P2gZFCxeUsyqWlcYNrzQL6uM55XThZcEvv8uPC5dJQ23HM8qeFNOm5KTZO85EWBx5r3Vsr0hLS5dXxn8sJYsXlaY31sks3OuiLba1ypmleRVenMYDCi85p/3Xb/xXpsz4WqqfW0kuq3luZsUTYWzx+g7H6hvixCTntCprSgIkQAIkQALHJ4HjXnixN/st19eWp7u2Pj57gj51ThdeWj70tCxcskpe7P+o1Lm0ekzbMVaT5phWKsELS4TFUbwRzf9xsbTpPFTOOfMMmfhK78zqHEpNk337D5h/58+bR1JSkuNd1YS/v1fhxWk88FN42X/goBw8lGpYFiqQX3LnzpXwXBO5gsPHfCBjxk+Tu5teJ13aNcusaiJw9iq8HD58WHbt2WeeISU5WfLnyxMReicmERXGi0iABEiABEiABLKNwHEnvHR9qLmUO+0UA3j/gQPy2++r5a0PZ8nBg4fMz14d2kUuubCKYwMc0kn1sbpIysnCy8bNW+XqphmuQBResm38CHmjRBdesuNdthgECi+J0UI5qxZehJdQ44GfwosXopH0P1hQISUl5fZyqxyb12qrQOElER7Iq/ASqzonGpNI+nGsWLAcEiABEiABEshJBI474eWd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S8o3P5gps+f9ZITfvfsPGNGwcqXTpJWO3bDaCfYMsOpCX8WYYb23cPeDtZM9efkWuh1zUT4CrkPQRFDrIjq2YAxod1ejkMILrru1dS/DBglujHCLCpbc8gt2bayEF5Tt5TvnxATleBmfkd/LNyTcnMjLuLBs5dqYCC9e2YUcMPhLEiABEiABEvCZwHEhvPjM8Lgs3u1i9riEk40PDUsWu2BiPxK3dq2qJtArEwmQAAm4JRBKzHNbBvPlHAL8huSctmJNSYAESIAEcjYBCi85u/3iVnsKL3FDb24MN5t3Jn0u/2msiaefuM9Y/2ACPUwtYBC3BQnWGrDaYCIBEiABtwQovLgllbPz8RuSs9uPtScBEiABEsh5BCi85Lw2S4gaU3iJbzOsWrPBxG2Abz0S3Ab2qfuAFf8GJ8u8MaKbcW9hIgESIAG3BCi8uCWVs/PxG5Kz24+1JwESIAESyHkEKLzkvDZLiBpTeIl/MyDGCuKmLPj5dz0pabvk1mC3iH+DwK6IM0TRJf5txBqQQE4jQOElp7VY5PXlNyRydrySBEiABEiABLwSoPDilRjzkwAJkAAJkAAJkAAJkAAJkAAJkAAJkIBLAhReXIJiNhIgARIgARIgARIgARIgARIgARIgARLwSoDCi1dizE8CJEACJEACJEACJEACJEACJEACJEACLglQeHEJitlIgARIgARIgARIgARIgARIgARIgARIwCsBCi9eiTE/CZAACZAACZAACZAACZAACZAACZAACbgkQOHFJShmIwESIAESIAESIAESIAESIAESIAESIAGvBCi8eCXG/CRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgkgCFF5egmI0ESIAESIAESIAESIAESIAESIAESIAEvBKg8OKVGPOTAAmQAAmQAAmQAAmQAAmQAAmQAAmQgEsCFF5cgmI2EiABEiABEiABEiABEiABEiABEiABEvBKgMKLV2LMTwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIuCVB4cQmK2UiABEiABEiABEiABEiABEiABEiABEjAKwEKL16JMT8JkAAJkAAJkAAJkAAJkAAJkAAJkAAJuCRA4cUlKGYjARIgARIgARIgARIgARIgARIgARIgAa8EKLx4Jcb8JEACJEACJEACJEACJEACJEACJEACJOCSAIUXl6CYjQRIgARIgARIgARI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", + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Average metric for the pre-change and post-change regime\n", + "obj_cusum.plot_input_metric_plotly()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "a59e8b44", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "greenyellow", + "size": 10 + }, + "mode": "lines", + "name": "Positive changes (Shi)", + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "y": [ + 0, + 0.8762097534279534, + 1.7524195068559068, + 0.8762097534279534, + 0, + 0, + 0, + 0, + 1.1682796712372712, + 0, + 0, + 0, + 0, + 0, + 1.1682796712372712, + 0.2920699178093178, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 0, + 0.8762097534279534, + 1.1682796712372712, + 1.4603495890465892, + 1.4603495890465892, + 1.7524195068559068, + 0.5841398356186356, + 1.1682796712372712, + 0, + 0, + 0, + 0, + 0, + 0.5841398356186356, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1.4603495890465892, + 0.5841398356186356, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 2.3365593424745423, + 2.9206991780931784, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "marker": { + "color": "darkcyan", + "size": 10 + }, + "mode": "lines", + "name": "Negative changes (Slo)", + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "y": [ + 0, + 0, + 0, + 0, + 1.4603495890465892, + 0.8762097534279534, + 0.8762097534279534, + 0.5841398356186356, + 0, + 0.2920699178093178, + 1.7524195068559068, + 2.0444894246652248, + 2.62862926028386, + 2.3365593424745423, + 0.2920699178093178, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0.8762097534279534, + 0.5841398356186356, + 0, + 0.5841398356186356, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 1.4603495890465892, + 1.7524195068559068, + 0.8762097534279534, + 1.1682796712372712, + 2.3365593424745423, + 1.1682796712372712, + 0.8762097534279534, + 4.0889788493304495, + 3.7969089315211315, + 3.5048390137118135, + 1.7524195068559068, + 2.62862926028386, + 0, + 0, + 2.0444894246652248, + 1.7524195068559068, + 2.62862926028386, + 5.549328438377038, + 5.25725852056772, + 7.009678027423627, + 7.593817863042263, + 7.593817863042263, + 10.222447123326122, + 11.682796712372713, + 11.390726794563394, + 11.97486663018203, + 11.390726794563394, + 10.51451704113544, + 10.806586958944758, + 13.143146301419302, + 12.266936547991348, + 16.06384547951248, + 16.647985315131113, + 19.568684493224293, + 21.905243835698833, + 24.241803178173377, + 25.41008284941065, + 26.286292602838603, + 26.286292602838603, + 26.57836252064792, + 26.57836252064792, + 28.038712109694508, + 32.711830794643596, + 33.58804054807155, + 33.295970630262225, + 33.295970630262225, + 35.04839013711813, + 35.92459989054609, + 34.4642503014995, + 35.340460054927455, + 40.889788493304486, + 42.642208000160394, + 44.97876734263494, + 46.731186849490854, + 47.31532668510949, + 47.6073966029188, + 48.19153643853743, + 51.98844537005857, + 55.49328438377038, + 55.49328438377038, + 55.785354301579694, + 58.998123397482196, + 61.04261282214742, + 60.750542904338104, + 61.626752657766055, + 63.9633120002406, + 65.7157315070965, + 68.05229084957105, + 68.928500602999, + 70.97299002766422, + 73.01747945232945, + 75.93817863042263, + 75.93817863042263, + 75.93817863042263 + ] + }, + { + "line": { + "color": "skyblue", + "dash": "dash" + }, + "mode": "lines", + "name": "Threshold (H)", + "type": "scatter", + "x": [ + 0, + 120 + ], + "y": [ + 4, + 4 + ] + }, + { + "line": { + "color": "grey", + "dash": "dash" + }, + "mode": "lines", + "name": "Change-point", + "type": "scatter", + "x": [ + 60, + 60 + ], + "y": [ + 0, + 75.93817863042263 + ] + } + ], + "layout": { + "legend": { + "orientation": "h", + "x": 1, + "xanchor": "right", + "y": 1.02, + "yanchor": "bottom" + }, + "plot_bgcolor": "#F3F9FC", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "font": { + "size": 20, + "weight": "bold" + }, + "text": "CUSUM Chart" + }, + "xaxis": { + "dtick": 20, + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Length of Simulation (Days)" + } + }, + "yaxis": { + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "CUSUM value" + } + } + } + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAABF4AAAFoCAYAAABuXz/oAAAgAElEQVR4XuydBZyU1ffGH2pZGukOSWmQDkFQQUEQFUQMQEQREH8ISEungCDSLaCgtHRJd4eUgpR0N0v877kw819i1933zuz7zsxz/fBxmZ0b53su773zzLnnRnugClhIgARIgARIgARIgARIgARIgARIgARIgAQ8TiAahRePM2WDJEACJEACJEACJEACJEACJEACJEACJKAJUHjhRCABEiABEiABEiABEiABEiABEiABEiABLxGg8OIlsGyWBEiABEiABEiABEiABEiABEiABEiABCi8cA6QAAmQAAmQAAmQAAmQAAmQAAmQAAmQgJcIUHjxElg2SwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIUXjgHSIAESIAESIAESIAESIAESIAESIAESMBLBCi8eAksmyUBEiABEiABEiABEiABEiABEiABEiABCi+cAyRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgJQIUXrwEls2SAAmQAAmQAAmQAAmQAAmQAAmQAAmQAIUXzgESIAESIAESIAESIAESIAESIAESIAES8BIBCi9eAstmSYAESIAESIAESIAESIAESIAESIAESIDCC+cACZAACZAACZAACZAACZAACZAACZAACXiJAIUXL4FlsyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA4YVzgARIgARIgARIgARIgARIgARIgARIgAS8RIDCi5fAslkSIAESIAESIAESIAESIAESIAESIAESoPDCOUACJEACJEACJEACJEACJEACJEACJEACXiJA4cVLYNksCZAACZAACZAACZAACZAACZAACZAACVB44RwgARIgARIgARIgARIgARIgARIgARIgAS8RoPDiJbBslgRIgARIgARIgARIgARIgARIgARIgAQovHAOkAAJkAAJkAAJkAAJkAAJkAAJkAAJkICXCFB48RJYNksCJEACJEACJEACJEACJEACJEACJEACFF44B0iABEiABEiABEiABEiABEiABEiABEjASwQovHgJLJslARIgARIgARIgARIgARIgARIgARIgAQovnAMkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4CUCFF68BJbNkgAJkAAJkAAJkAAJkAAJkAAJkAAJkACFF84BEiABEiABEiABEiAB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QAIkQAIk4DQCFF6c5hGOhwRIgARIgARIgARIgARIgARIgARIwG8IUHjxG1fSEBIgARIgARIgARIgARIgARIgARIgAacRoPDiNI9wPCRAAiRAAiRAAiRAAiRAAiRAAiRAAn5DgMKL37iShpAACZAACZAACZAACZAACZAACZAACTiNAIUXp3mE4yEBEiABEiABEiABEiABEiABEiABEvAbAhRe/MaVNIQESIAESIAESIAESIAESIAESIAESMBpBCi8OM0jHA8JkAAJkAAJkAAJkAAJkAAJkAAJkIDfEKDw4jeupCEkQAIkQAIkQAIkQAIkQAIkQAIkQAJOI0DhxWke4XhIgARIgARIgARIgARIgARIgARIgAT8hgCFF79xJQ0hARIgARIgARIgARIgARIgARIgARJwGgEKL07zCMdDAiRAAiRAAiRAAiRAAiRAAiRAAiTgNwQovPiNK2kICZAACZAACZAACZAACZAACZAACZCA0whQeHGaRzgeEiABEiABEiABEiABEiABEiABEiABvyFA4cVvXElDSIAESIAESIAESIAESIAESIAESIAEnEaAwovTPMLxkAAJkAAJkAAJkAAJkAAJkAAJkAAJ+A0BCi9+40oaQgIkQAIkQAIkQAIkQAIkQAIkQAIk4DQCFF6c5hGOhwRIgARIgARIgARIgARIgARIgARIwG8IUHjxG1fSEBIgARIgARIgARIgARIgARIgARIgAacRoPDiNI9wPCRAAiRAAiRAAiRAAiRAAiRAAiRAAn5DgMKL37iShpAACZAACZAACZAACZAACZAACZAACTiNAIUXp3mE4yEBEiABEiABEiABEiABEiABEiABEvAbAhRe/MaVNIQESIAESIAESIAESIAESIAESIAESMBpBCi8OM0jHA8JkAAJkAAJkAAJkAAJkAAJkAAJkIDfEKDw4jeupCEkQAIkQAKBTODuvXvIX6E+YsWKqTFEjxYNmdKnQvOG76FUkTyW0IydPB+Hjp5E128+wbrNe5A5Y2qkSp4EoV+31HAEKpWs2hiTh36LDGlTRuDd9r9lzOR5OHXmIto2/QAHDx9Hn8GTsf/vo7h3/z7SpkqG/zV4FyULh+2HE6fO4YvW32PCoLZIlCCe/QYZjmDgqGn46beFmDuxl54zrvJ2/Q7o0aYBcmbNYNjD09VDz1Fh+Ub5YnjztZIe78fV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PRlIgARIgARIwN0IUHhxtx5le0iABEiABFyagGz1eG/AFF1HObVHnLoykIAtBF54e6i2nmqqRKNpoxL81KRXMIl0pqPWbS333X6TsHHbP6hWsTQWTh9kazZMRwIkQAIkQAIuTYDCi0t3DytHAiRAAiSQUQnIEctDx8/T23r6v/8qWjSuqZvSSzkjla0wYlGzaek0fcoLAwnYQkD8pYjfFNket+6HiciXN9CWbKxOs3jlRnz86VydTny7mFuwWJPZpSvX0fzFnvpo60/6d8Ezj9e3JjnjkgAJkAAJkECGIUDhJcN0FStKAiRAAiSQkQiIDxKxSBA/KHJksfgeET8XJse6H/d4TTulZSABWwncVqdSPf3GQO2LqF3rJhja6w1bs7Io3dQ5i/GjOjVKTiCSINvmpo3sblHa5CKJeCMiTvEi+bFs3ii9bYmBBEiABEiABNyRAIUXd+xVtokESIAESMAlCIjvDDl95nflv0Xu7mfNkgXlSxdVp/20QPNGCRYwDCRghIDJp4v46lk0c4j2o+Ko8NncpZj7/Sr4Kn86ssWoT9eXkSO7j03FyRapF98Zpv3rzBzXEw2SOXXMpoyZiARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQj8DxKUYWqdtDZoAAAAAElFTkSuQmCC", + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# CUSUM Chart\n", + "obj_cusum.plot_cusum_plotly()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/package/ARLTheoretical.py b/src/package/ARLTheoretical.py new file mode 100644 index 0000000000000000000000000000000000000000..f93c9aa8b6b0860a3b84311c6422277c0ea556bc --- /dev/null +++ b/src/package/ARLTheoretical.py @@ -0,0 +1,140 @@ +""" +ARLTheoretical + +@author: smriti.prathapan +""" + +import pandas as pd +import numpy as np +from collections import OrderedDict + +# import rpy2's package module +import rpy2.robjects.packages as rpackages + +# R vector of strings +from rpy2.robjects.vectors import StrVector + +import rpy2.robjects as ro + +# Suppress all R warnings globally +ro.r["options"](warn=-1) + + +def get_ref_value_k(h: float, ARL_0: float) -> float: + """ + Calculation for the reference value for given h and ARL_0. + + Args: + h (float): Normalized threshold. + ARL_0 (float): ARL0 value. + + Returns: + float: Normalized reference value k. + """ + + k = np.round(spc.xcusum_crit_L0h(ARL_0, h), decimals=4).tolist()[0] + + return k + + +def get_ref_value( + h: float, list_ARL_0: list[float] +) -> tuple[pd.DataFrame, OrderedDict]: + """ + provides normalized reference values k for provided list of ARL0, given the value of normalized threshold h. + + Args: + h (float): Normalized threshold. + list_ARL_0 (list): List of ARL0 values. + + Returns: + tuple[pd.Dataframe, OrderedDict]: Dataframe of ARL0 and k, Data dictionary of ARL0 and k; where k is normalized reference value. + """ + + # data in Ordered dictionary to use it other functions instead of using DataFrame + dict_ARL0_k = OrderedDict() + + summary_table_df_ARL0_k = pd.DataFrame(columns=["ARL_0", "k"]) + for n, ARL_0 in enumerate(list_ARL_0): + k = np.round(spc.xcusum_crit_L0h(ARL_0, h), decimals=4).tolist()[0] + summary_table_df_ARL0_k.loc[n] = [ + ARL_0, + k, + ] + dict_ARL0_k[ARL_0] = k + + return summary_table_df_ARL0_k, dict_ARL0_k + + +def get_ARL_1_h_mu1_k(h: float, k: float, mu1: float) -> float: + """ + Calculate ARL_1 with given Shift in Mean (mu1) and k. + + Args: + h (float): Normalized threshold. + k (float): Normalized reference value. + mu1 (float): Intended shift in mean. + + Returns: + float: Detection delay (ARL1). + """ + + ARL_1 = np.round( + spc.xcusum_ad_(k=k, h=h, mu1=mu1, mu0=0, sided="two", r=20), decimals=2 + ).tolist()[0] # Changing decimals to 2 digits to match the results from paper + + return ARL_1 + + +def get_ARL_1( + h: float, shift_in_mean: list[float], dict_ARL0_k: OrderedDict +) -> pd.DataFrame: + """ + Get the ARL1 along with k values. + + Args: + h (float): Normalized threshold. + shift_in_mean (list[float]): List of the values of shift in mean. + dict_ARL0_k (OrderedDict): Data dictionary of ARL0 and k + + Returns: + pd.DataFrame: Table for ARL1 and k values. + """ + + list_ARL_0 = [ARL_0 for ARL_0 in dict_ARL0_k.keys()] + + dict_data_ARL1_k = OrderedDict() + dict_data_ARL1_k["Shift in mean"] = shift_in_mean + + for ARL_0 in list_ARL_0: + k = dict_ARL0_k[ARL_0] + list_ARL_1 = [] + + for mu1 in shift_in_mean: + ARL_1 = np.round( + spc.xcusum_ad_(k=k, h=h, mu1=mu1, mu0=0, sided="two", r=20), decimals=2 + ).tolist()[ + 0 + ] # Changing decimals to 2 digits to match the results from paper + list_ARL_1.append(ARL_1) + + dict_data_ARL1_k[ARL_0] = list_ARL_1 + + summary_table_df_ARL1_k = pd.DataFrame(dict_data_ARL1_k) + + return summary_table_df_ARL1_k + + +# import R's utility package +utils = rpackages.importr("utils") +spc = rpackages.importr("spc") +# select a mirror for R packages +utils.chooseCRANmirror(ind=1) # select the first mirror in the list + +# R package names +packnames = ("ggplot2", "hexbin", "lazyeval", "cusumcharter", "RcppCNPy", "spc") + +# Selectively install what needs to be install +names_to_install = [x for x in packnames if not rpackages.isinstalled(x)] +if len(names_to_install) > 0: + utils.install_packages(StrVector(names_to_install)) diff --git a/src/package/__pycache__/ARLTheoretical.cpython-310.pyc b/src/package/__pycache__/ARLTheoretical.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..98e24c05d88e92ce2ceb96733f327561218e52a3 Binary files /dev/null and b/src/package/__pycache__/ARLTheoretical.cpython-310.pyc differ diff --git a/src/package/__pycache__/ARLTheoretical.cpython-39.pyc b/src/package/__pycache__/ARLTheoretical.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..257e646d4548c749a885bd1441901eb6c710cdea Binary files /dev/null and b/src/package/__pycache__/ARLTheoretical.cpython-39.pyc differ diff --git a/src/package/__pycache__/__init__.cpython-310.pyc b/src/package/__pycache__/__init__.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..e564e84c6abc79b19600970d977836c42bea0d6d Binary files /dev/null and b/src/package/__pycache__/__init__.cpython-310.pyc differ diff --git a/src/package/__pycache__/app.cpython-310.pyc b/src/package/__pycache__/app.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2aecfbd8226016b4302fe889187daa173e165171 Binary files /dev/null and b/src/package/__pycache__/app.cpython-310.pyc differ diff --git a/src/package/__pycache__/cusum.cpython-310.pyc b/src/package/__pycache__/cusum.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..dff2277e56dfc72c20aa4c3fa01533000680d182 Binary files /dev/null and b/src/package/__pycache__/cusum.cpython-310.pyc differ diff --git a/src/package/__pycache__/cusum.cpython-39.pyc b/src/package/__pycache__/cusum.cpython-39.pyc new file mode 100644 index 0000000000000000000000000000000000000000..7c0e59404979e898335ff2f70703fad1f2037964 Binary files /dev/null and b/src/package/__pycache__/cusum.cpython-39.pyc differ diff --git a/src/package/__pycache__/utils.cpython-310.pyc b/src/package/__pycache__/utils.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..a6d568d1e4bd99c8d88786c758531e6aa0c0a151 Binary files /dev/null and b/src/package/__pycache__/utils.cpython-310.pyc differ diff --git a/src/package/app.py b/src/package/app.py new file mode 100644 index 0000000000000000000000000000000000000000..1dfc32f44e40eebef3977ef21453646570741ad3 --- /dev/null +++ b/src/package/app.py @@ -0,0 +1,395 @@ +""" +Gradio user interface for AIM-CU +""" + +import os +import sys +import pandas as pd +import gradio as gr +import tomli +from cusum import CUSUM +from ARLTheoretical import get_ref_value, get_ref_value_k, get_ARL_1, get_ARL_1_h_mu1_k +from utils import ( + populate_summary_table_ARL0_k, + populate_summary_table_ARL1_k, +) +import great_tables as gt +import plotly.graph_objects as go + + +def set_init_days( + file_csv_metric: gr.File, init_days: str +) -> tuple[float, float, go.Figure]: + """ + Set initial days and get in-control mean and standard deviation. + + Args: + file_csv_metric (gr.File): CSV file with metric data + init_days (str): initial days to calculate in-control mean and standard deviation + + Returns: + tuple[float, float, go.Figure]: In-control mean and standard deviation, and observation data plot. + """ + init_days = int(init_days) + + data_csv_metric = pd.read_csv(file_csv_metric.name) + obj_cusum.set_df_metric_csv(data_csv_metric) + + obj_cusum.set_init_stats(init_days=init_days) + + return ( + "{:.2f}".format(obj_cusum.in_mu), + "{:.2f}".format(obj_cusum.in_std), + obj_cusum.plot_input_metric_plotly_raw(), + ) + + +def populate_table(h: str) -> tuple[gt.GT, gt.GT]: + """ + Populate tables for ARL0 and ARL1 given the value of h + + Args: + h (str): Normalized threshold. + + Returns: + tuple[gt.GT, gt.GT]: Table for ARL0 and k in HTML format; table for ARL1 and k in HTML format. + """ + h = float(h) + + summary_table_df_ARL0_k, dict_ARL0_k = get_ref_value( + h=h, + list_ARL_0=config["params_cusum"]["list_ARL_0"], + ) + summary_table_df_ARL0_k = summary_table_df_ARL0_k.applymap( + lambda x: "{:.2f}".format(x) if isinstance(x, (float)) else x + ) + + summary_table_df_ARL1_k = get_ARL_1( + h=h, + shift_in_mean=config["params_cusum"]["shift_in_mean"], + dict_ARL0_k=dict_ARL0_k, + ) + summary_table_df_ARL1_k = summary_table_df_ARL1_k.applymap( + lambda x: "{:.2f}".format(x) if isinstance(x, (float)) else x + ) + + return populate_summary_table_ARL0_k( + summary_table_df_ARL0_k, h + ), populate_summary_table_ARL1_k(summary_table_df_ARL1_k, dict_ARL0_k, h) + + +def calculate_reference_value_k(h: str, arl_0: str) -> float: + """ + Gets the reference value for given h and ARL_0. + + Args: + h (str): Normalized threshold. + arl_0 (str): ARL0 value. + + Returns: + float: Normalized reference value k. + """ + h = float(h) + arl_0 = float(arl_0) + + k = get_ref_value_k(h=h, ARL_0=arl_0) + k = "{:.2f}".format(k) + + return k + + +def calculate_arl1_h_k_mu1(h: str, k: str, mu1: str) -> float: + """ + Get the ARL_1 with given Shift in Mean (mu1) and k. + + Args: + h (str): Normalized threshold. + k (str): Normalized reference value. + mu1 (str): Intended shift in mean. + + Returns: + float: Detection delay (ARL1). + """ + h = float(h) + k = float(k) + mu1 = float(mu1) + + arl_1 = get_ARL_1_h_mu1_k(h=h, k=k, mu1=mu1) + arl_1 = "{:.2f}".format(arl_1) + + return arl_1 + + +def populate_cusum_plots( + ref_value: str, normalized_threshold: str +) -> tuple[go.Figure, go.Figure]: + """ + Populate CUSUM plots + + Args: + ref_value (str): Normalized reference value for detecting a unit standard deviation change in mean of the process. + normalized_threshold (str): Normalized threshold. + + Returns: + tuple[go.Figure, go.Figure]: Scatter plot as Plotly graph object; CUSUM plot using Plotly graph object. + """ + ref_value = float(ref_value) + normalized_threshold = float(normalized_threshold) + + obj_cusum.change_detection( + normalized_ref_value=ref_value, + normalized_threshold=normalized_threshold, + ) + + return (obj_cusum.plot_input_metric_plotly(), obj_cusum.plot_cusum_plotly()) + + +with gr.Blocks( + theme=gr.themes.Base( + neutral_hue=gr.themes.Color( + c50="#e5f1f8", + c100="#e5f1f8", + c200="#cce4f1", + c300="#b2d7ea", + c400="#7fbddc", + c500="#4ca3ce", + c600="#007cba", + c700="#006394", + c800="#004a6f", + c900="#00314a", + c950="#001825", + ), + ) +) as demo: + gr.Markdown(f""" + # AIM-CU + ## AIM-CU: A statistical tool for AI monitoring using cumulative sum (AIM-CU). + """) # noqa: F541 + + gr.Markdown(f""" + ### AIM-CU Input: + AI output (e.g. metrics such as Accuracy, F1-score, Sensitivity etc.) + """) # noqa: F541 + + with gr.Row(): + with gr.Column(): + gr.Markdown(f""" + ### Phase I: + """) # noqa: F541 + + gr.Markdown(f""" + ### Upload the AI output. + """) # noqa: F541 + + # load the CSV file with specifities across days + csv_file_metric = gr.File( + label="Upload the AI output", + ) + + with gr.Row(): + with gr.Column(): + init_days = gr.Textbox(label="Initial days", placeholder="30") + with gr.Column(): + button_calculate_incontrol_params = gr.Button( + "Calculate parameters" + ) + + with gr.Row(): + with gr.Column(): + in_control_mean = gr.Textbox( + label="In-control mean", interactive=False + ) + with gr.Column(): + in_control_std = gr.Textbox( + label="In-control standard deviation", interactive=False + ) + + plot_observation_data = gr.Plot(label="AI output", visible=False) + + gr.Markdown(f""" + Parameter choices for detecting change and detection delay estimates (theoretical calculations). + """) # noqa: F541 + + gr.Markdown(f""" + ### Enter h value: + """) # noqa: F541 + + h_phase1 = gr.Textbox( + label="h value =", + placeholder="h = normalized threshold, default = 4. Range: between 4 and 5 ([4, 5])", + value="4", + autofocus=True, + ) + + dataframe_gt_ref_value = gr.HTML( + label="Reference Values for an intended ARL0 with normalized threshold h", + show_label=True, + visible=False, + ) + + gr.Markdown(f""" + ### Calculate reference value k for a specific value for ARL0: + """) # noqa: F541 + + with gr.Row(): + arl_0 = gr.Textbox( + label="ARL_0 value =", placeholder="ARL_0", value="100" + ) + + button_calculate_k = gr.Button("Calculate k") + + output_k = gr.Textbox(label="Calculated k =", visible=False) + + dataframe_gt_ARL0 = gr.HTML( + label="Estimate of steady state ARL (ARL_1 based on the computed reference values and intended zero-state ARL (ARL_0) with normalized threshold h)", + show_label=True, + visible=False, + ) + + gr.Markdown(f""" + ### Calculate ARL1 for reference value h, value k and shift in mean: + """) # noqa: F541 + + with gr.Row(): + k_phase1 = gr.Textbox( + label="k value =", placeholder="k", value="0.2996" + ) + mu1 = gr.Textbox( + label="Shift in mean value =", + placeholder="Shift in mean value", + value="1.2", + ) + + button_calculate_ARL_1 = gr.Button("Calculate ARL_1") + + output_ARL_1 = gr.Textbox(label="Calculated ARL_1 =", visible=False) + + button_populate_table = gr.Button( + "Populate Reference Values and ARL_1 tables for the given h value" + ) + + gr.Markdown(f""" + ### Workflow: + Phase I: + - Upload the AI output. + - Enter initial days. + - Calculate parameters. + - Check parameter choices in Phase 1, for Phase 2. (optional) + + Phase II: + - Enter h and k values. + - Get CUSUM plots. + """) # noqa: F541 + + table_param_description = gr.Dataframe( + value=pd.read_csv("../../assets/params.csv") + ) + with gr.Column(): + gr.Markdown(f""" + ### Phase II: + Performance drift detection plots, pre- and post-change distribution with respect to the performance drift detected. + """) # noqa: F541 + + gr.Markdown(f""" + ### Enter required values: + """) # noqa: F541 + + with gr.Row(): + h_phase2 = gr.Textbox( + label="h value =", + placeholder="normalized threshold, default = 4. Range: between 4 and 5 ([4, 5])", + value="4", + ) + + k_phase2 = gr.Textbox( + label="k value =", + placeholder="normalized reference value, default = 0.5", + value="0.5", + ) + + button_csv_metric = gr.Button("Show CUSUM plots") + + plot_avg_metric = gr.Plot( + label="Average metric for the pre-change and post-change regime", + visible=False, + ) + plot_cusum_chart = gr.Plot(label="CUSUM Chart", visible=False) + + button_calculate_incontrol_params.click( + fn=set_init_days, + inputs=[csv_file_metric, init_days], + outputs=[in_control_mean, in_control_std, plot_observation_data], + ) + + button_calculate_incontrol_params.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=plot_observation_data + ) + + # Get the CSV file and populate tables + button_populate_table.click( + fn=populate_table, + inputs=[h_phase1], + outputs=[dataframe_gt_ref_value, dataframe_gt_ARL0], + ) + button_populate_table.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=dataframe_gt_ref_value + ) + button_populate_table.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=dataframe_gt_ARL0 + ) + + # Calculate specific k for ARL_0 + button_calculate_k.click( + fn=calculate_reference_value_k, inputs=[h_phase1, arl_0], outputs=[output_k] + ) + button_calculate_k.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=output_k + ) + + # Calculate specific ARL_1 for value h, value k and shift in mean + button_calculate_ARL_1.click( + fn=calculate_arl1_h_k_mu1, + inputs=[h_phase1, k_phase1, mu1], + outputs=[output_ARL_1], + ) + button_calculate_ARL_1.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=output_ARL_1 + ) + + # Get the CSV file and populate plots + button_csv_metric.click( + fn=populate_cusum_plots, + inputs=[k_phase2, h_phase2], + outputs=[plot_avg_metric, plot_cusum_chart], + ) + + button_csv_metric.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=plot_avg_metric + ) + button_csv_metric.click( + fn=lambda: gr.update(visible=True), inputs=[], outputs=plot_cusum_chart + ) + + +try: + path_file_config = os.path.abspath("../../config/config.toml") + + with open(path_file_config, "rb") as file_config: + config = tomli.load(file_config) +except FileNotFoundError: + print("Error: config.toml not found at", path_file_config) + sys.exit(1) + + +if config["control"]["save_figure"] == "true": + path_check = os.path.abspath( + os.path.join("../../", config["path_output"]["path_figure"]) + ) + if not os.path.exists(path_check): + os.mkdir(path_check) + print("Created", path_check) + +obj_cusum = CUSUM() +obj_cusum.initialize() + +demo.launch(server_name="0.0.0.0", server_port=7860) diff --git a/src/package/cusum.py b/src/package/cusum.py new file mode 100644 index 0000000000000000000000000000000000000000..91ee08b51202e240bcbf06a56a4d0b848c27c454 --- /dev/null +++ b/src/package/cusum.py @@ -0,0 +1,649 @@ +""" +Cumulative Sum (CUSUM) + +@author: smriti.prathapan +""" + +import os +import sys +import numpy as np +import random +import pandas as pd +import warnings + +import plotly.graph_objects as go +from plotly.subplots import make_subplots +import tomli + +warnings.filterwarnings("ignore") +random.seed(58) + + +class CUSUM: + """ + CUSUM class and its functionalities. + """ + + def __init__(self): + self.df_metric = None + self.metric_type = None + + self.AvgDD = None + self.data = None + + self.H = None + self.in_std = None + self.in_mu = None + self.S_hi = None + self.S_lo = None + + self.config = None + + self.total_days = None + self.pre_change_days = None + self.post_change_days = None + + self.init_days = None + + def initialize(self) -> None: + """ + Initialize with the configuration file. + """ + try: + path_file_config = os.path.abspath("../../config/config.toml") + + with open(path_file_config, "rb") as file_config: + self.config = tomli.load(file_config) + except FileNotFoundError: + print("Error: config.toml not found at", path_file_config) + sys.exit(1) + + def set_init_stats(self, init_days: int) -> None: + """ + Use initial days to calculate in-control mean and standard deviation. + + Args: + init_days (int, optional): Initial days when observations are considered stable. Defaults to 30. + """ + self.init_days = init_days + + in_control_data = self.data[ + : self.init_days + ] # Assume the input data has more than 30 observations + self.in_std = np.std(in_control_data) + self.in_mu = np.mean(in_control_data) # In-control mean + + def set_timeline(self, data: np.ndarray) -> None: + """ + Set the timeline of observations. + + Args: + data (np.ndarray): Data of the metric values across the observations. + """ + self.total_days = np.shape(data)[0] + + def set_df_metric_default(self) -> None: + """ + Read the provided performance metric data to be used for CUSUM for an example. + """ + try: + path_csv = os.path.abspath( + os.path.join("../../", self.config["path_input"]["path_df_metric"]) + ) + self.df_metric = pd.read_csv(path_csv) + except FileNotFoundError: + print("Error: CSV file not found at", path_csv) + sys.exit(1) + self.data = self.df_metric[self.df_metric.columns[1]].to_numpy() + + self.set_timeline(self.data) + + def set_df_metric_csv(self, data_csv: pd.DataFrame) -> None: + """ + Assign the performance metric data to be used for CUSUM. + + Args: + data_csv (DataFrame or TextFileReader): A comma-separated values (csv) file is returned as two-dimensional data structure with labeled axes. + """ + self.df_metric = data_csv + self.data = self.df_metric[self.df_metric.columns[1]].to_numpy() + + self.set_timeline(self.data) + + def compute_cusum( + self, x: list[float], mu_0: float, k: float + ) -> tuple[list[float], list[float], list[float]]: + """ + Compute CUSUM for the observations in x + + Args: + x (list[float]): Performance metric to be monitored + mu_0 (float) : In-control mean of the observations/performance metric + k (float) : Reference value related to the magnitude of change that one is interested in detecting + + Returns: + tuple[list[float], list[float], list[float]]: Positive cumulative sum, negative cumulative sum, and CUSUM + """ + num_rows = np.shape(x)[0] + + x_mean = np.zeros(num_rows, dtype=float) + # S_hi : sum of positive changes -------------------------- + self.S_hi = np.zeros(num_rows, dtype=float) + self.S_hi[0] = 0.0 # starts with 0 + # Increase in mean = x-mu-k ---------------------------- + mean_hi = np.zeros(num_rows, dtype=float) + + # Decrease in mean = mu-k-x---------------------------- + mean_lo = np.zeros(num_rows, dtype=float) + # S_lo : sum of negative changes -------------------------- + self.S_lo = np.zeros(num_rows, dtype=float) + self.S_lo[0] = 0.0 # starts with 0 + # CUSUM: Cumulative sum of x minus mu ------------------ + cusum = np.zeros(num_rows, dtype=float) + cusum[0] = 0.0 # initialize with 0 + + for i in range(0, num_rows): + x_mean[i] = x[i] - mu_0 # x - mean + mean_hi[i] = x[i] - mu_0 - k + self.S_hi[i] = max(0, self.S_hi[i - 1] + mean_hi[i]) + mean_lo[i] = mu_0 - k - x[i] + self.S_lo[i] = max(0, self.S_lo[i - 1] + mean_lo[i]) + cusum[i] = cusum[i - 1] + x_mean[i] + + x_mean = np.round(x_mean, decimals=2) + self.S_hi = np.round(self.S_hi, decimals=2) + mean_lo = np.round(mean_lo, decimals=2) + self.S_lo = np.round(self.S_lo, decimals=2) + cusum = np.round(cusum, decimals=2) + + return self.S_hi, self.S_lo, cusum + + def change_detection( + self, + normalized_ref_value: float = 0.5, + normalized_threshold: float = 4, + ) -> None: + """ + Detects a change in the process. + + Args: + pre_change_days (int) : Number of days for in-control phase. + normalized_ref_value (float, optional): Normalized reference value for detecting a unit standard deviation change in mean of the process. Defaults to 0.5. + normalized_threshold (float, optional): Normalized threshold. Defaults to 4. + """ + self.pre_change_days = self.init_days # This is the #initial days that we assume to be in-control - user enters or default = 30 + + ref_val = normalized_ref_value + control_limit = normalized_threshold + + DetectionTimes = np.array([], dtype=int) + Dj = np.array( + [], dtype=int + ) # save the Dj which are binary values indicating detection MTBFA + Zj = np.array([], dtype=int) # save the Zj = min(Tj,pre-change-days)-MTBFA + zj = np.array([], dtype=int) # ADD - Maximum likelihood estimate of delays + cj = np.array( + [], dtype=int + ) # ADD - binary - whether there is a change-detection (1) or not (0) + self.AvgDD = np.array([]) # Average Detection Delay + + self.H = control_limit * self.in_std # Threhold + k = ref_val * self.in_std # Reference value + + x = np.array(self.data) + + # Call compute CUSUM function with x (observatoins), in-control mean (mu) and k (drift or reference value) + self.S_hi, self.S_lo, cusum = self.compute_cusum(x, self.in_mu, k) + + # Check the variations in self.S_hi and self.S_lo to determine whether there was a change in the data + S_hi_last_known_zero = np.where(self.S_hi == 0)[ + 0 + ] # Find all the indices where self.S_hi was 0 + S_hi_start_of_change = ( + S_hi_last_known_zero[-1] + 1 + ) # Fetch the last entry where self.S_hi was 0 + + S_lo_last_known_zero = np.where(self.S_lo == 0)[ + 0 + ] # Find all the indices where self.S_lo was 0 + S_lo_start_of_change = ( + S_lo_last_known_zero[-1] + 1 + ) # Fetch the last entry where self.S_lo was 0 + + # Display the print messages in the UI + if (S_lo_start_of_change < S_hi_start_of_change) and ( + self.S_lo[S_lo_start_of_change + 10] > self.H + ): # check if the changes in the next 10 observations exceed the threshold + print( + f"Change-point with respect to S_lo is: {S_lo_start_of_change}" + ) # Use this change-point to generate histograms + self.pre_change_days = S_lo_start_of_change + + elif (S_hi_start_of_change < S_lo_start_of_change) and ( + self.S_hi[S_hi_start_of_change + 10] > self.H + ): + print(f"Change-point with respect to S_hi is: {S_hi_start_of_change}") + self.pre_change_days = S_hi_start_of_change + else: + print(f"No change") + + # False positives and Total alarms + falsePos = 0 + alarms = 0 + avddd = 0 # this is the delay from the paper: td-ts (z_k-v) where v is the changepoint and z_k is the time of detection + + for i in range(0, self.pre_change_days): + if (self.S_hi[i] > self.H) or (self.S_lo[i] > self.H): + falsePos += 1 # False Positives + DetectionTimes = np.append( + DetectionTimes, i + 1 + ) # time at which a false positive is detected + Dj = np.append(Dj, 1) + Zj = np.append(Zj, min(i, self.pre_change_days)) + break + + # If there is no false positive, Zj = pre_change_days, Dj = 0 + if falsePos == 0: + Dj = np.append(Dj, 0) + Zj = np.append(Zj, self.pre_change_days) + + # Delay to detect the first changepoint + # delay = 0 + for i in range(self.pre_change_days, self.total_days): + if (self.S_hi[i] > self.H) or (self.S_lo[i] > self.H): + alarms += 1 # True Positive: break after detecting one TP + cj = np.append(cj, 1) + zj = np.append(zj, min(i, self.total_days) - self.pre_change_days) + break + + # If there is no true detection, zj = total simulation days, cj = 0 + if alarms == 0: + cj = np.append(cj, 0) + zj = np.append(zj, self.total_days) + + self.AvgDD = np.append(self.AvgDD, avddd) # ADD estimate from the paper + + def plot_input_metric_plotly_raw(self) -> go.Figure: + """ + Plot AI output using Plotly. + + Returns: + go.Figure: Scatter plot as Plotly graph object. + """ + x1 = np.arange(self.init_days) + y1 = self.data[: self.init_days] + + x2 = np.arange(self.init_days, self.total_days, 1) + y2 = self.data[self.init_days : self.total_days] + + fig = make_subplots( + rows=1, + cols=1, + shared_yaxes=True, + horizontal_spacing=0.02, + ) + + font_size_title = 20 + font_size_legend = 18 + + # separate in sublots + fig.add_trace( + go.Scatter( + x=x1, + y=y1, + mode="markers", + marker=dict(color="lime", size=10), + opacity=0.4, + ), + row=1, + col=1, + ) + fig.add_trace( + go.Scatter( + x=x2, + y=y2, + mode="markers", + marker=dict(color="lime", size=10), + opacity=0.2, + ), + row=1, + col=1, + ) + + fig.add_vrect( + x0=0, + x1=self.init_days, + annotation_text="Initial days", + annotation_position="top right", + fillcolor="palegreen", + opacity=0.25, + line_width=0, + ) + + fig.update_layout( + title={ + "text": "AI output", + "font": {"size": font_size_title, "weight": "bold"}, + }, + xaxis_title={ + "text": "Length of observations", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + yaxis_title={ + "text": "AI model metric", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + xaxis=dict(dtick=20), + ) + + fig.update_layout(plot_bgcolor=self.config["color"]["blue_005"]) + + fig.update_layout( + legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1) + ) + + fig.update_layout(showlegend=False) + + return fig + + def plot_input_metric_plotly(self) -> go.Figure: + """ + Plot the input metric using Plotly. + + Returns: + go.Figure: Scatter plot as Plotly graph object. + """ + x1 = np.arange(self.pre_change_days) + y1 = self.data[: self.pre_change_days] + mean_y1 = np.mean(y1) + + x2 = np.arange(self.pre_change_days, self.total_days, 1) + y2 = self.data[self.pre_change_days : self.total_days] + mean_y2 = np.mean(y2) + + fig = make_subplots( + rows=1, + cols=2, + column_widths=[0.7, 0.3], + shared_yaxes=True, + horizontal_spacing=0.02, + ) + + font_size_title = 20 + font_size_legend = 18 + + # add subplots + fig.add_trace( + go.Scatter( + x=x1, + y=y1, + mode="markers", + name=f"""In-control data""", + marker=dict(color="darkturquoise", size=10), + opacity=0.4, + ), + row=1, + col=1, + ) + fig.add_trace( + go.Scatter( + x=x2, + y=y2, + mode="markers", + name=f"""Out-of-control data""", + marker=dict(color="coral", size=10), + opacity=0.4, + ), + row=1, + col=1, + ) + + # add horizontal lines + fig.add_trace( + go.Scatter( + x=[min(x1), max(x1)], + y=[mean_y1, mean_y1], + mode="lines", + name="In-control mean", + line=dict(color="darkturquoise", dash="dash"), + ), + row=1, + col=1, + ) + fig.add_trace( + go.Scatter( + x=[min(x2), max(x2)], + y=[mean_y2, mean_y2], + mode="lines", + name="Out-of-control mean", + line=dict(color="coral", dash="dash"), + ), + row=1, + col=1, + ) + + # add vertical line + fig.add_trace( + go.Scatter( + x=[self.pre_change_days, self.pre_change_days], + y=[np.min(self.data), np.max(self.data)], + mode="lines", + name="Change-point", + line=dict(color="grey", dash="dash"), + # textfont=dict(size=18) + ), + row=1, + col=1, + ) + + fig.update_layout( + title={ + "text": "Pre- and post-change observations and their respective histograms", + "font": {"size": font_size_title, "weight": "bold"}, + }, + xaxis_title={ + "text": "Length of observations", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + yaxis_title={ + "text": "AI model metric", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + xaxis=dict(dtick=20), + ) + + fig.update_layout(plot_bgcolor=self.config["color"]["blue_005"]) + + fig.update_layout( + legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1) + ) + + # add histogram (like marginal histogram) + nbinsx = 15 # 6 + + # add subplots + fig.add_trace( + go.Histogram( + y=self.data[: self.pre_change_days], + nbinsy=nbinsx, + # name=f"""Pre-change Sp""", + showlegend=False, + marker=dict(color="mediumturquoise"), + opacity=0.4, + orientation="h", + ), + row=1, + col=2, + ) + + fig.add_trace( + go.Histogram( + y=self.data[self.pre_change_days : self.total_days], + nbinsy=nbinsx, + # name=f"""Post-change Sp""", + showlegend=False, + marker=dict(color="coral"), + opacity=0.4, + orientation="h", + ), + row=1, + col=2, + ) + + fig.add_trace( + go.Scatter( + x=[0, 20], # [! y_max can should be used] + y=[ + np.mean(self.data[: self.pre_change_days]), + np.mean(self.data[: self.pre_change_days]), + ], + mode="lines", + # name="Reference mean", + showlegend=False, + line=dict(color="mediumturquoise", dash="dash"), + ), + row=1, + col=2, + ) + + fig.update_xaxes( + title_text="Count", + title_font_size=font_size_legend, + title_font_weight="bold", + row=1, + col=2, + ) + + # update layout + fig.update_layout(barmode="overlay") + + if self.config["control"]["save_figure"] == "true": + fig.write_image( + os.path.join( + os.path.abspath( + os.path.join( + "../../", self.config["path_output"]["path_figure"] + ) + ), + "fig_plot_1.png", + ), + scale=3, + ) + print( + "Created", + os.path.join( + os.path.abspath( + os.path.join( + "../../", self.config["path_output"]["path_figure"] + ) + ), + "fig_plot_1.png", + ), + ) + + return fig + + def plot_cusum_plotly(self) -> go.Figure: + """ + Plot CUSUM value using Plotly + + Returns: + go.Figure: CUSUM plot using Plotly graph object. + """ + fig = go.Figure() + + font_size_title = 20 + font_size_legend = 18 + + # add subplots + fig.add_trace( + go.Scatter( + x=list(range(len(self.S_hi))), + y=self.S_hi / self.in_std, + mode="lines", + name=f"""Positive changes (Shi)""", + marker=dict(color="greenyellow", size=10), + ) + ) + fig.add_trace( + go.Scatter( + x=list(range(len(self.S_lo))), + y=self.S_lo / self.in_std, + mode="lines", + name=f"""Negative changes (Slo)""", + marker=dict(color="darkcyan", size=10), + ) + ) + + # add horizontal lines + fig.add_trace( + go.Scatter( + x=[0, len(self.S_lo)], + y=[self.H / self.in_std, self.H / self.in_std], + mode="lines", + name="Threshold (h)", + line=dict(color="skyblue", dash="dash"), + ) + ) + + # add vertical line + fig.add_trace( + go.Scatter( + x=[self.pre_change_days, self.pre_change_days], + y=[ + 0, + np.max(self.S_lo / self.in_std), + ], + mode="lines", + name="Change-point", + line=dict(color="grey", dash="dash"), + ) + ) + + fig.update_layout( + title={ + "text": "CUSUM Chart", + "font": {"size": font_size_title, "weight": "bold"}, + }, + xaxis_title={ + "text": "Length of observations", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + yaxis_title={ + "text": "CUSUM value", + "font": {"size": font_size_legend, "weight": "bold"}, + }, + xaxis=dict(dtick=20), + ) + + fig.update_layout(plot_bgcolor=self.config["color"]["blue_005"]) + + fig.update_layout( + legend=dict(orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1) + ) + + if self.config["control"]["save_figure"] == "true": + fig.write_image( + os.path.join( + os.path.abspath( + os.path.join( + "../../", self.config["path_output"]["path_figure"] + ) + ), + "fig_plot_2.png", + ), + scale=3, + ) + print( + "Created", + os.path.join( + os.path.abspath( + os.path.join( + "../../", self.config["path_output"]["path_figure"] + ) + ), + "fig_plot_2.png", + ), + ) + + return fig diff --git a/src/package/example_AIM_CU.ipynb b/src/package/example_AIM_CU.ipynb new file mode 100644 index 0000000000000000000000000000000000000000..82534ee1b589ca2462ece75884eb868ba674f953 --- /dev/null +++ b/src/package/example_AIM_CU.ipynb @@ -0,0 +1,2997 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 29, + "id": "9296d4be-eb69-47a7-a3b4-d6111231e018", + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "'\\nExample on Cumulative Sum (CUSUM)\\n\\n@author: smriti.prathapan\\n'" + ] + }, + "execution_count": 29, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "\"\"\"\n", + "Example on Cumulative Sum (CUSUM)\n", + "\n", + "@author: smriti.prathapan\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "2a3c98bd", + "metadata": {}, + "outputs": [], + "source": [ + "import os\n", + "import sys\n", + "import pandas as pd\n", + "from cusum import CUSUM" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "bd11f2ea", + "metadata": {}, + "outputs": [], + "source": [ + "# Absolute path to the metric file in CSV format\n", + "file_csv_metric = None # Use your own file here, else it will use /config/spec-60-60.csv\n", + "\n", + "# Normalized reference value for detecting a unit standard deviation change in mean of the process\n", + "ref_value = 0.5\n", + "# Normalized threshold value\n", + "normalized_threshold = 4\n", + "# Number of days for in-control phase\n", + "pre_change_days = 60 # An integer value" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "bd01cab4", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Change-point with respect to S_lo is: 60\n" + ] + } + ], + "source": [ + "obj_cusum = CUSUM()\n", + "obj_cusum.initialize()\n", + "\n", + "if file_csv_metric is not None:\n", + " # upload CSV file\n", + " data_csv_metric = pd.read_csv(file_csv_metric.name)\n", + " obj_cusum.set_df_metric_csv(data_csv_metric)\n", + "else:\n", + " # use the example CSV data\n", + " obj_cusum.set_df_metric_default()\n", + "\n", + "# Set initial days and get in-control mean and standard deviation\n", + "obj_cusum.set_init_stats(init_days=30)\n", + "\n", + "# Detects a change in the process\n", + "obj_cusum.change_detection(\n", + " normalized_ref_value=ref_value,\n", + " normalized_threshold=normalized_threshold,\n", + " )" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "4ebf2fd5", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "darkturquoise", + "size": 10 + }, + "mode": "markers", + "name": "In-control Sp", + "opacity": 0.4, + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59 + ], + "xaxis": "x", + "y": [ + 0.8426395939086294, + 0.8913043478260869, + 0.8826530612244898, + 0.8308457711442786, + 0.7679558011049724, + 0.8444444444444444, + 0.8306878306878307, + 0.8308457711442786, + 0.8936170212765957, + 0.8138297872340425, + 0.7747252747252747, + 0.8052631578947368, + 0.8090452261306532, + 0.8317757009345794, + 0.8958333333333334, + 0.8306878306878307, + 0.8556701030927835, + 0.8387096774193549, + 0.7894736842105263, + 0.8563829787234043, + 0.8186813186813187, + 0.8306878306878307, + 0.7918781725888325, + 0.8823529411764706, + 0.8737373737373737, + 0.8666666666666667, + 0.8518518518518519, + 0.8659217877094972, + 0.8232044198895028, + 0.8764044943820225, + 0.8167539267015707, + 0.8478260869565217, + 0.8363636363636363, + 0.797752808988764, + 0.8309859154929577, + 0.875, + 0.8, + 0.8608247422680413, + 0.8288770053475936, + 0.8556149732620321, + 0.8153846153846154, + 0.859375, + 0.8324607329842932, + 0.9043062200956936, + 0.8279569892473119, + 0.8197674418604651, + 0.7795698924731183, + 0.8135593220338984, + 0.8481675392670157, + 0.8134715025906736, + 0.7864583333333334, + 0.8548387096774194, + 0.8370786516853933, + 0.7157360406091371, + 0.8324607329842932, + 0.8296703296703297, + 0.8844221105527639, + 0.7884615384615384, + 0.935, + 0.8840579710144928 + ], + "yaxis": "y" + }, + { + "marker": { + "color": "coral", + "size": 10 + }, + "mode": "markers", + "name": "Out-of-control Sp", + "opacity": 0.4, + "type": "scatter", + "x": [ + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "xaxis": "x", + "y": [ + 0.75, + 0.8324607329842932, + 0.7939698492462312, + 0.7272727272727273, + 0.8284313725490197, + 0.7692307692307693, + 0.8010204081632653, + 0.8235294117647058, + 0.7277486910994765, + 0.775, + 0.8361581920903954, + 0.7959183673469388, + 0.8489583333333334, + 0.8465346534653465, + 0.812807881773399, + 0.7475247524752475, + 0.8491620111731844, + 0.6989247311827957, + 0.7967914438502673, + 0.7236180904522613, + 0.746031746031746, + 0.7371428571428571, + 0.7839195979899497, + 0.7921348314606742, + 0.8258706467661692, + 0.8121827411167513, + 0.8258426966292135, + 0.7675675675675676, + 0.6666666666666666, + 0.7872340425531915, + 0.8325123152709359, + 0.8247422680412371, + 0.7619047619047619, + 0.7967032967032966, + 0.867816091954023, + 0.8010471204188482, + 0.625, + 0.7684210526315789, + 0.7409326424870466, + 0.7593582887700535, + 0.8041237113402062, + 0.8160919540229885, + 0.803030303030303, + 0.6898395721925134, + 0.7037037037037037, + 0.8219895287958116, + 0.8153846153846154, + 0.712707182320442, + 0.7548076923076923, + 0.8258426966292135, + 0.8, + 0.7444444444444445, + 0.7604166666666666, + 0.7446808510638298, + 0.7845303867403315, + 0.7616279069767442, + 0.7525773195876289, + 0.7213930348258707, + 0.8222222222222222, + 0.817258883248731 + ], + "yaxis": "y" + }, + { + "line": { + "color": "darkturquoise", + "dash": "dash" + }, + "mode": "lines", + "name": "In-control mean", + "type": "scatter", + "x": [ + 0, + 59 + ], + "xaxis": "x", + "y": [ + 0.8368330003971066, + 0.8368330003971066 + ], + "yaxis": "y" + }, + { + "line": { + "color": "coral", + "dash": "dash" + }, + "mode": "lines", + "name": "Out-of-control mean", + "type": "scatter", + "x": [ + 60, + 119 + ], + "xaxis": "x", + "y": [ + 0.7794127721177365, + 0.7794127721177365 + ], + "yaxis": "y" + }, + { + "line": { + "color": "grey", + "dash": "dash" + }, + "mode": "lines", + "name": "Change-point", + "type": "scatter", + "x": [ + 60, + 60 + ], + "xaxis": "x", + "y": [ + 0.625, + 0.935 + ], + "yaxis": "y" + }, + { + "marker": { + "color": "mediumturquoise" + }, + "nbinsy": 15, + "opacity": 0.4, + "orientation": "h", + "showlegend": false, + "type": "histogram", + "xaxis": "x2", + "y": [ + 0.8426395939086294, + 0.8913043478260869, + 0.8826530612244898, + 0.8308457711442786, + 0.7679558011049724, + 0.8444444444444444, + 0.8306878306878307, + 0.8308457711442786, + 0.8936170212765957, + 0.8138297872340425, + 0.7747252747252747, + 0.8052631578947368, + 0.8090452261306532, + 0.8317757009345794, + 0.8958333333333334, + 0.8306878306878307, + 0.8556701030927835, + 0.8387096774193549, + 0.7894736842105263, + 0.8563829787234043, + 0.8186813186813187, + 0.8306878306878307, + 0.7918781725888325, + 0.8823529411764706, + 0.8737373737373737, + 0.8666666666666667, + 0.8518518518518519, + 0.8659217877094972, + 0.8232044198895028, + 0.8764044943820225, + 0.8167539267015707, + 0.8478260869565217, + 0.8363636363636363, + 0.797752808988764, + 0.8309859154929577, + 0.875, + 0.8, + 0.8608247422680413, + 0.8288770053475936, + 0.8556149732620321, + 0.8153846153846154, + 0.859375, + 0.8324607329842932, + 0.9043062200956936, + 0.8279569892473119, + 0.8197674418604651, + 0.7795698924731183, + 0.8135593220338984, + 0.8481675392670157, + 0.8134715025906736, + 0.7864583333333334, + 0.8548387096774194, + 0.8370786516853933, + 0.7157360406091371, + 0.8324607329842932, + 0.8296703296703297, + 0.8844221105527639, + 0.7884615384615384, + 0.935, + 0.8840579710144928 + ], + "yaxis": "y2" + }, + { + "marker": { + "color": "coral" + }, + "nbinsy": 15, + "opacity": 0.4, + "orientation": "h", + "showlegend": false, + "type": "histogram", + "xaxis": "x2", + "y": [ + 0.75, + 0.8324607329842932, + 0.7939698492462312, + 0.7272727272727273, + 0.8284313725490197, + 0.7692307692307693, + 0.8010204081632653, + 0.8235294117647058, + 0.7277486910994765, + 0.775, + 0.8361581920903954, + 0.7959183673469388, + 0.8489583333333334, + 0.8465346534653465, + 0.812807881773399, + 0.7475247524752475, + 0.8491620111731844, + 0.6989247311827957, + 0.7967914438502673, + 0.7236180904522613, + 0.746031746031746, + 0.7371428571428571, + 0.7839195979899497, + 0.7921348314606742, + 0.8258706467661692, + 0.8121827411167513, + 0.8258426966292135, + 0.7675675675675676, + 0.6666666666666666, + 0.7872340425531915, + 0.8325123152709359, + 0.8247422680412371, + 0.7619047619047619, + 0.7967032967032966, + 0.867816091954023, + 0.8010471204188482, + 0.625, + 0.7684210526315789, + 0.7409326424870466, + 0.7593582887700535, + 0.8041237113402062, + 0.8160919540229885, + 0.803030303030303, + 0.6898395721925134, + 0.7037037037037037, + 0.8219895287958116, + 0.8153846153846154, + 0.712707182320442, + 0.7548076923076923, + 0.8258426966292135, + 0.8, + 0.7444444444444445, + 0.7604166666666666, + 0.7446808510638298, + 0.7845303867403315, + 0.7616279069767442, + 0.7525773195876289, + 0.7213930348258707, + 0.8222222222222222, + 0.817258883248731 + ], + "yaxis": "y2" + }, + { + "line": { + "color": "mediumturquoise", + "dash": "dash" + }, + "mode": "lines", + "showlegend": false, + "type": "scatter", + "x": [ + 0, + 20 + ], + "xaxis": "x2", + "y": [ + 0.8368330003971066, + 0.8368330003971066 + ], + "yaxis": "y2" + } + ], + "layout": { + "barmode": "overlay", + "legend": { + "orientation": "h", + "x": 1, + "xanchor": "right", + "y": 1.02, + "yanchor": "bottom" + }, + "plot_bgcolor": "#F3F9FC", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "font": { + "size": 20, + "weight": "bold" + }, + "text": "Pre- and post-change observations and their respective histograms" + }, + "xaxis": { + "anchor": "y", + "domain": [ + 0, + 0.6859999999999999 + ], + "dtick": 20, + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Length of Simulation (days)" + } + }, + "xaxis2": { + "anchor": "y2", + "domain": [ + 0.706, + 1 + ], + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Count" + } + }, + "yaxis": { + "anchor": "x", + "domain": [ + 0, + 1 + ], + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "AI model metric" + } + }, + "yaxis2": { + "anchor": "x2", + "domain": [ + 0, + 1 + ], + "matches": "y", + "showticklabels": false + } + } + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAABF4AAAFoCAYAAABuXz/oAAAgAElEQVR4XuydCbxNVRvGX+695lnRQGWqJJGSJiVKRaUSGdIkFUUJyVSGMitKSlIaNFAZkogKldJIIVOUIVLmmXuv733Wte+373H2OXufc/Y95/Ks79eHe9dee+3/WnvttZ71vu/KdViTMJEACZAACZAACZAACZAACZAACZAACZAACcScQC4KLzFnygJJgARIgARIgARIgARIgARIgARIgARIwBCg8MKOQAIkQAIkQAIkQAIkQAIkQAIkQAIkQAI+EaDw4hNYFksCJEACJEACJEACJEACJEACJEACJEACFF7YB0iABEiABEiABEiABEiABEiABEiABEjAJwIUXnwCy2JJgARIgARIgARIgARIgARIgARIgARIgMIL+wAJkAAJkAAJkAAJkAAJkAAJkAAJkAAJ+ESAwotPYFksCZAACZAACZAACZAACZAACZAACZAACVB4YR8gARIgARIgARIgARIgARIgARIgARIgAZ8IUHjxCSyLJQESIAESIAESIAESIAESIAESIAESIAEKL+wDJEACJEACJEACJEACJEACJEACJEACJOATAQovPoFlsSRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA4YV9gARIgARIgARIgARIgARIgARIgARIgAR8IkDhxSewLJYESIAESIAESIAESIAESIAESIAESIAEKLywD5AACZAACZAACZAACZAACZAACZAACZCATwQovPgElsWSAAmQAAmQAAmQAAmQAAmQAAmQAAmQAIUX9gESIAESIAESIAESIAESIAESIAESIAES8IkAhRefwLJYEiABEiABEiABEiABEiABEiABEiABEqDwwj5AAiRAAiRAAiRAAiRAAiRAAiRAAiRAAj4RoPDiE1gWSwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIUXtgHSIAESIAESIAESIAESIAESIAESIAESMAnAhRefALLYkmABEiABEiABEiABEiABEiABEiABEiAwgv7AAmQAAmQAAmQAAmQAAmQAAmQAAmQAAn4RIDCi09gWSwJkAAJkAAJkAAJkAAJkAAJkAAJkAAJUHhhHyABEiABEiABEiABEiABEiABEiABEiABnwhQePEJLIslARIgARIgARIgARIgARIgARIgARIgAQov7AMkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4BMBCi8+gWWxJEACJEACJEACJEACJEACJEACJEACJEDhhX2ABEiABEiABEiABEiABEiABEiABEiABHwiQOHFJ7AslgRIgARIgARIgARIgARIgARIgARIgAQovLAPkAAJkAAJkAAJkAAJkAAJkAAJkAAJkIBPBCi8+ASWxZIACZAACZAACZAACZAACZAACZAACZAAhRf2ARIgARIgARIgARIgARIgARIgARIgARLwiQCFF5/AslgSIAESIAESIAESIAESIAESIAESIAESoPDCPkACJEACJEACJEACJEACJEACJEACJEACPhGg8OIT2JxY7Mo16+Xme3qaqje/uZ70fLRVTnwMX+q86d+tUq/JY6bsG66+RAb1fMCX+xxLhfYa/Jp8NH2eeaRPxw+S004tfSw9XlTP8vFn8+WJ/q+YMvp0vkduu+HKqMo7Hi5+9MmRMmvej+ZRv57yghQvWjiix76uxeOy7u/NUuqEYvLlB8MjKsPpIvb5mOJ0LCwROHt9h/kNyZ6+wbuQAAmQAAmQQKISOC6El059RsmML78P2gZFCxeUsyqWlcYNrzQL6uM55XThZcEvv8uPC5dJQ23HM8qeFNOm5KTZO85EWBx5r3Vsr0hLS5dXxn8sJYsXlaY31sks3OuiLba1ypmleRVenMYDCi85p/3Xb/xXpsz4WqqfW0kuq3luZsUTYWzx+g7H6hvixCTntCprSgIkQAIkQALHJ4HjXnixN/st19eWp7u2Pj57gj51ThdeWj70tCxcskpe7P+o1Lm0ekzbMVaT5phWKsELS4TFUbwRzf9xsbTpPFTOOfMMmfhK78zqHEpNk337D5h/58+bR1JSkuNd1YS/v1fhxWk88FN42X/goBw8lGpYFiqQX3LnzpXwXBO5gsPHfCBjxk+Tu5teJ13aNcusaiJw9iq8HD58WHbt2WeeISU5WfLnyxMReicmERXGi0iABEiABEiABLKNwHEnvHR9qLmUO+0UA3j/gQPy2++r5a0PZ8nBg4fMz14d2kUuubCKYwMc0kn1sbpIysnCy8bNW+XqphmuQBResm38CHmjRBdesuNdthgECi+J0UI5qxZehJdQ44GfwosXopH0P1hQISUl5fZyqxyb12qrQOElER7Iq/ASqzonGpNI+nGsWLAcEiABEiABEshJBI474eWd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S8o3P5gps+f9ZITfvfsPGNGwcqXTpJWO3bDaCfYMsOpCX8WYYb23cPeDtZM9efkWuh1zUT4CrkPQRFDrIjq2YAxod1ejkMILrru1dS/DBglujHCLCpbc8gt2bayEF5Tt5TvnxATleBmfkd/LNyTcnMjLuLBs5dqYCC9e2YUcMPhLEiABEiABEvCZwHEhvPjM8Lgs3u1i9riEk40PDUsWu2BiPxK3dq2qJtArEwmQAAm4JRBKzHNbBvPlHAL8huSctmJNSYAESIAEcjYBCi85u/3iVnsKL3FDb24MN5t3Jn0u/2msiaefuM9Y/2ACPUwtYBC3BQnWGrDaYCIBEiABtwQovLgllbPz8RuSs9uPtScBEiABEsh5BCi85Lw2S4gaU3iJbzOsWrPBxG2Abz0S3Ab2qfuAFf8GJ8u8MaKbcW9hIgESIAG3BCi8uCWVs/PxG5Kz24+1JwESIAESyHkEKLzkvDZLiBpTeIl/MyDGCuKmLPj5dz0pabvk1mC3iH+DwK6IM0TRJf5txBqQQE4jQOElp7VY5PXlNyRydrySBEiABEiABLwSoPDilRjzkwAJkAAJkAAJkAAJkAAJkAAJkAAJkIBLAhReXIJiNhIgARIgARIgARIgARIgARIgARIgARLwSoDCi1dizE8CJEACJEACJEACJEACJEACJEACJEACLglQeHEJitlIgARIgARIgARIgARIgARIgARIgARIwCsBCi9eiTE/CZAACZAACZAACZAACZAACZAACZAACbgkQOHFJShmIwESIAESIAESIAESIAESIAESIAESIAGvBCi8eCXG/CRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgkgCFF5egmI0ESIAESIAESIAESIAESIAESIAESIAEvBKg8OKVGPOTAAmQAAmQAAmQAAmQAAmQAAmQAAmQgEsCFF5cgmI2EiABEiABEiABEiABEiABEiABEiABEvBKgMKLV2LMTwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIuCVB4cQmK2UiABEiABEiABEiABEiABEiABEiABEjAKwEKL16JMT8JkAAJkAAJkAAJkAAJkAAJkAAJkAAJuCRA4cUlKGYjARIgARIgARIgARIgARIgARIgARIgAa8EKLx4Jcb8JEACJEACJEACJEACJEACJEACJEACJOCSAIUXl6CYjQRIgARIgARIgARI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", + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# Average metric for the pre-change and post-change regime\n", + "obj_cusum.plot_input_metric_plotly()" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "a59e8b44", + "metadata": {}, + "outputs": [ + { + "data": { + "application/vnd.plotly.v1+json": { + "config": { + "plotlyServerURL": "https://plot.ly" + }, + "data": [ + { + "marker": { + "color": "greenyellow", + "size": 10 + }, + "mode": "lines", + "name": "Positive changes (Shi)", + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "y": [ + 0, + 0.8762097534279534, + 1.7524195068559068, + 0.8762097534279534, + 0, + 0, + 0, + 0, + 1.1682796712372712, + 0, + 0, + 0, + 0, + 0, + 1.1682796712372712, + 0.2920699178093178, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 0, + 0.8762097534279534, + 1.1682796712372712, + 1.4603495890465892, + 1.4603495890465892, + 1.7524195068559068, + 0.5841398356186356, + 1.1682796712372712, + 0, + 0, + 0, + 0, + 0, + 0.5841398356186356, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 1.4603495890465892, + 0.5841398356186356, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 2.3365593424745423, + 2.9206991780931784, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + ] + }, + { + "marker": { + "color": "darkcyan", + "size": 10 + }, + "mode": "lines", + "name": "Negative changes (Slo)", + "type": "scatter", + "x": [ + 0, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + 11, + 12, + 13, + 14, + 15, + 16, + 17, + 18, + 19, + 20, + 21, + 22, + 23, + 24, + 25, + 26, + 27, + 28, + 29, + 30, + 31, + 32, + 33, + 34, + 35, + 36, + 37, + 38, + 39, + 40, + 41, + 42, + 43, + 44, + 45, + 46, + 47, + 48, + 49, + 50, + 51, + 52, + 53, + 54, + 55, + 56, + 57, + 58, + 59, + 60, + 61, + 62, + 63, + 64, + 65, + 66, + 67, + 68, + 69, + 70, + 71, + 72, + 73, + 74, + 75, + 76, + 77, + 78, + 79, + 80, + 81, + 82, + 83, + 84, + 85, + 86, + 87, + 88, + 89, + 90, + 91, + 92, + 93, + 94, + 95, + 96, + 97, + 98, + 99, + 100, + 101, + 102, + 103, + 104, + 105, + 106, + 107, + 108, + 109, + 110, + 111, + 112, + 113, + 114, + 115, + 116, + 117, + 118, + 119 + ], + "y": [ + 0, + 0, + 0, + 0, + 1.4603495890465892, + 0.8762097534279534, + 0.8762097534279534, + 0.5841398356186356, + 0, + 0.2920699178093178, + 1.7524195068559068, + 2.0444894246652248, + 2.62862926028386, + 2.3365593424745423, + 0.2920699178093178, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 0, + 0, + 0.8762097534279534, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0.8762097534279534, + 0.5841398356186356, + 0, + 0.5841398356186356, + 0, + 0, + 0, + 0.2920699178093178, + 0, + 0, + 0, + 0, + 0, + 1.4603495890465892, + 1.7524195068559068, + 0.8762097534279534, + 1.1682796712372712, + 2.3365593424745423, + 1.1682796712372712, + 0.8762097534279534, + 4.0889788493304495, + 3.7969089315211315, + 3.5048390137118135, + 1.7524195068559068, + 2.62862926028386, + 0, + 0, + 2.0444894246652248, + 1.7524195068559068, + 2.62862926028386, + 5.549328438377038, + 5.25725852056772, + 7.009678027423627, + 7.593817863042263, + 7.593817863042263, + 10.222447123326122, + 11.682796712372713, + 11.390726794563394, + 11.97486663018203, + 11.390726794563394, + 10.51451704113544, + 10.806586958944758, + 13.143146301419302, + 12.266936547991348, + 16.06384547951248, + 16.647985315131113, + 19.568684493224293, + 21.905243835698833, + 24.241803178173377, + 25.41008284941065, + 26.286292602838603, + 26.286292602838603, + 26.57836252064792, + 26.57836252064792, + 28.038712109694508, + 32.711830794643596, + 33.58804054807155, + 33.295970630262225, + 33.295970630262225, + 35.04839013711813, + 35.92459989054609, + 34.4642503014995, + 35.340460054927455, + 40.889788493304486, + 42.642208000160394, + 44.97876734263494, + 46.731186849490854, + 47.31532668510949, + 47.6073966029188, + 48.19153643853743, + 51.98844537005857, + 55.49328438377038, + 55.49328438377038, + 55.785354301579694, + 58.998123397482196, + 61.04261282214742, + 60.750542904338104, + 61.626752657766055, + 63.9633120002406, + 65.7157315070965, + 68.05229084957105, + 68.928500602999, + 70.97299002766422, + 73.01747945232945, + 75.93817863042263, + 75.93817863042263, + 75.93817863042263 + ] + }, + { + "line": { + "color": "skyblue", + "dash": "dash" + }, + "mode": "lines", + "name": "Threshold (H)", + "type": "scatter", + "x": [ + 0, + 120 + ], + "y": [ + 4, + 4 + ] + }, + { + "line": { + "color": "grey", + "dash": "dash" + }, + "mode": "lines", + "name": "Change-point", + "type": "scatter", + "x": [ + 60, + 60 + ], + "y": [ + 0, + 75.93817863042263 + ] + } + ], + "layout": { + "legend": { + "orientation": "h", + "x": 1, + "xanchor": "right", + "y": 1.02, + "yanchor": "bottom" + }, + "plot_bgcolor": "#F3F9FC", + "template": { + "data": { + "bar": [ + { + "error_x": { + "color": "#2a3f5f" + }, + "error_y": { + "color": "#2a3f5f" + }, + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "bar" + } + ], + "barpolar": [ + { + "marker": { + "line": { + "color": "#E5ECF6", + "width": 0.5 + }, + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "barpolar" + } + ], + "carpet": [ + { + "aaxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "baxis": { + "endlinecolor": "#2a3f5f", + "gridcolor": "white", + "linecolor": "white", + "minorgridcolor": "white", + "startlinecolor": "#2a3f5f" + }, + "type": "carpet" + } + ], + "choropleth": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "choropleth" + } + ], + "contour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "contour" + } + ], + "contourcarpet": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "contourcarpet" + } + ], + "heatmap": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmap" + } + ], + "heatmapgl": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "heatmapgl" + } + ], + "histogram": [ + { + "marker": { + "pattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + } + }, + "type": "histogram" + } + ], + "histogram2d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2d" + } + ], + "histogram2dcontour": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "histogram2dcontour" + } + ], + "mesh3d": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "type": "mesh3d" + } + ], + "parcoords": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "parcoords" + } + ], + "pie": [ + { + "automargin": true, + "type": "pie" + } + ], + "scatter": [ + { + "fillpattern": { + "fillmode": "overlay", + "size": 10, + "solidity": 0.2 + }, + "type": "scatter" + } + ], + "scatter3d": [ + { + "line": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatter3d" + } + ], + "scattercarpet": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattercarpet" + } + ], + "scattergeo": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergeo" + } + ], + "scattergl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattergl" + } + ], + "scattermapbox": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scattermapbox" + } + ], + "scatterpolar": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolar" + } + ], + "scatterpolargl": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterpolargl" + } + ], + "scatterternary": [ + { + "marker": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "type": "scatterternary" + } + ], + "surface": [ + { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + }, + "colorscale": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "type": "surface" + } + ], + "table": [ + { + "cells": { + "fill": { + "color": "#EBF0F8" + }, + "line": { + "color": "white" + } + }, + "header": { + "fill": { + "color": "#C8D4E3" + }, + "line": { + "color": "white" + } + }, + "type": "table" + } + ] + }, + "layout": { + "annotationdefaults": { + "arrowcolor": "#2a3f5f", + "arrowhead": 0, + "arrowwidth": 1 + }, + "autotypenumbers": "strict", + "coloraxis": { + "colorbar": { + "outlinewidth": 0, + "ticks": "" + } + }, + "colorscale": { + "diverging": [ + [ + 0, + "#8e0152" + ], + [ + 0.1, + "#c51b7d" + ], + [ + 0.2, + "#de77ae" + ], + [ + 0.3, + "#f1b6da" + ], + [ + 0.4, + "#fde0ef" + ], + [ + 0.5, + "#f7f7f7" + ], + [ + 0.6, + "#e6f5d0" + ], + [ + 0.7, + "#b8e186" + ], + [ + 0.8, + "#7fbc41" + ], + [ + 0.9, + "#4d9221" + ], + [ + 1, + "#276419" + ] + ], + "sequential": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ], + "sequentialminus": [ + [ + 0, + "#0d0887" + ], + [ + 0.1111111111111111, + "#46039f" + ], + [ + 0.2222222222222222, + "#7201a8" + ], + [ + 0.3333333333333333, + "#9c179e" + ], + [ + 0.4444444444444444, + "#bd3786" + ], + [ + 0.5555555555555556, + "#d8576b" + ], + [ + 0.6666666666666666, + "#ed7953" + ], + [ + 0.7777777777777778, + "#fb9f3a" + ], + [ + 0.8888888888888888, + "#fdca26" + ], + [ + 1, + "#f0f921" + ] + ] + }, + "colorway": [ + "#636efa", + "#EF553B", + "#00cc96", + "#ab63fa", + "#FFA15A", + "#19d3f3", + "#FF6692", + "#B6E880", + "#FF97FF", + "#FECB52" + ], + "font": { + "color": "#2a3f5f" + }, + "geo": { + "bgcolor": "white", + "lakecolor": "white", + "landcolor": "#E5ECF6", + "showlakes": true, + "showland": true, + "subunitcolor": "white" + }, + "hoverlabel": { + "align": "left" + }, + "hovermode": "closest", + "mapbox": { + "style": "light" + }, + "paper_bgcolor": "white", + "plot_bgcolor": "#E5ECF6", + "polar": { + "angularaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "radialaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "scene": { + "xaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "yaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + }, + "zaxis": { + "backgroundcolor": "#E5ECF6", + "gridcolor": "white", + "gridwidth": 2, + "linecolor": "white", + "showbackground": true, + "ticks": "", + "zerolinecolor": "white" + } + }, + "shapedefaults": { + "line": { + "color": "#2a3f5f" + } + }, + "ternary": { + "aaxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "baxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + }, + "bgcolor": "#E5ECF6", + "caxis": { + "gridcolor": "white", + "linecolor": "white", + "ticks": "" + } + }, + "title": { + "x": 0.05 + }, + "xaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + }, + "yaxis": { + "automargin": true, + "gridcolor": "white", + "linecolor": "white", + "ticks": "", + "title": { + "standoff": 15 + }, + "zerolinecolor": "white", + "zerolinewidth": 2 + } + } + }, + "title": { + "font": { + "size": 20, + "weight": "bold" + }, + "text": "CUSUM Chart" + }, + "xaxis": { + "dtick": 20, + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "Length of Simulation (Days)" + } + }, + "yaxis": { + "title": { + "font": { + "size": 18, + "weight": "bold" + }, + "text": "CUSUM value" + } + } + } + }, + "image/png": "iVBORw0KGgoAAAANSUhEUgAABF4AAAFoCAYAAABuXz/oAAAgAElEQVR4XuydBZyU1ffGH2pZGukOSWmQDkFQQUEQFUQMQEQREH8ISEungCDSLaCgtHRJd4eUgpR0N0v877kw819i1933zuz7zsxz/fBxmZ0b53su773zzLnnRnugClhIgARIgARIgARIgARIgARIgARIgARIgAQ8TiAahRePM2WDJEACJEACJEACJEACJEACJEACJEACJKAJUHjhRCABEiABEiABEiABEiABEiABEiABEiABLxGg8OIlsGyWBEiABEiABEiABEiABEiABEiABEiABCi8cA6QAAmQAAmQAAmQAAmQAAmQAAmQAAmQgJcIUHjxElg2SwIkQAIkQAIkQAIkQAIkQAIkQAIkQAIUXjgHSIAESIAESIAESIAESIAESIAESIAESMBLBCi8eAksmyUBEiABEiABEiABEiABEiABEiABEiABCi+cAyRAAiRAAiRAAiRAAiRAAiRAAiRAAiTgJQIUXrwEls2SAAmQAAmQAAmQAAmQAAmQAAmQAAmQAIUXzgESIAESIAESIAESIAESIAESIAESIAES8BIBCi9eAstmSYAESIAESIAESIAESIAESIAESIAESIDCC+cACZAACZAACZAACZAACZAACZAACZAACXiJAIUXL4FlsyRAAiRAAiRAAiRAAiRAAiRAAiRAAiRA4YVzgARIgARIgARIgARIgARIgARIgARIgAS8RIDCi5fAslkSIAESIAESIAESIAESIAESIAESIAESoPDCOUACJEACJEACJEACJEACJEACJEACJEACXiJA4cVLYNksCZAACZAACZAACZAACZAACZAACZAACVB44RwgARIgARIgARIgARIgARIgARIgARIgAS8RoPDiJbBslgRIgARIgARIgARIgARIgARIgARIgAQovHAOkAAJkAAJkAAJkAAJkAAJkAAJkAAJkICXCFB48RJYNksCJEACJEACJEACJEACJEACJEACJEACFF44B0iABEiABEiABEiABEiABEiABEiABEjASwQovHgJLJslARIgARIgARIgARIgARIgARIgARIgAQovnAMkQAIkQAIkQAIkQAIkQAIkQAIkQAIk4CUCFF68BJbNkgAJkAAJkAAJkAAJkAAJkAAJkAAJkACFF84BEiABEiABEiABEiAB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QAIkQAIk4DQCFF6c5hGOhwRIgARIgARIgARIgARIgARIgARIwG8IUHjxG1fSEBIgARIgARIgARIgARIgARIgARIgAacRoPDiNI9wPCRAAiRAAiRAAiRAAiRAAiRAAiRAAn5DgMKL37iShpAACZAACZAACZAACZAACZAACZAACTiNAIUXp3mE4yEBEiABEiABEiABEiABEiABEiABEvAbAhRe/MaVNIQESIAESIAESIAESIAESIAESIAESMBpBCi8OM0jHA8JkAAJkAAJkAAJkAAJkAAJkAAJkIDfEKDw4jeupCEkQAIkQAIkQAIkQAIkQAIkQAIkQAJOI0DhxWke4XhIgARIgARIgARIgARIgARIgARIgAT8hgCFF79xJQ0hARIgARIgARIgARIgARIgARIgARJwGgEKL07zCMdDAiRAAiRAAiRAAiRAAiRAAiRAAiTgNwQovPiNK2kICZAACZAACZAACZAACZAACZAACZCA0whQeHGaRzgeEiABEiABEiABEiABEiABEiABEiABvyFA4cVvXElDSIAESIAESIAESIAESIAESIAESIAEnEaAwovTPMLxkAAJkAAJkAAJkAAJkAAJkAAJkAAJ+A0BCi9+40oaQgIkQAIkQAIkQAIkQAIkQAIkQAIk4DQCFF6c5hGOhwRIgARIgARIgARIgARIgARIgARIwG8IUHjxG1fSEBIgARIgARIgARIgARIgARIgARIgAacRoPDiNI9wPCRAAiRAAiRAAiRAAiRAAiRAAiRAAn5DgMKL37iShpAACZAACZAACZAACZAACZAACZAACTiNAIUXp3mE4yEBEiABEiABEiABEiABEiABEiABEvAbAhRe/MaVNIQESIAESIAESIAESIAESIAESIAESMBpBCi8OM0jHA8JkAAJkAAJkAAJkAAJkAAJkAAJkIDfEKDw4jeupCEkQAIkQAKBTODuvXvIX6E+YsWKqTFEjxYNmdKnQvOG76FUkTyW0IydPB+Hjp5E128+wbrNe5A5Y2qkSp4EoV+31HAEKpWs2hiTh36LDGlTRuDd9r9lzOR5OHXmIto2/QAHDx9Hn8GTsf/vo7h3/z7SpkqG/zV4FyULh+2HE6fO4YvW32PCoLZIlCCe/QYZjmDgqGn46beFmDuxl54zrvJ2/Q7o0aYBcmbNYNjD09VDz1Fh+Ub5YnjztZIe78fVIOeo19BGScMNWvTF+q17dF/37z9A9OjR3P2unT0YFWu39Noz6H/f/ojSRfPi3SplI2zrvr+OQuot+LnPU3W+bDcQr5Ut8sz5fvnqdXz0ZQ8M7dUMU+eswLkLl/UzPXQpVvkLjB/YBkdPnMHMBaswpGezCI/LF9744MEDjP91IX79/Q/8q561zyVOgFdfKqKfy3HjxMak6Uuw88+/0bv9575gTrhjjMizT/YLC5ZtRJVXS/i8vb5kAIUXX/IWx0oCJEACJEACYRBwCS9Lf+uvP+jK35eu2oL2vcdg/qTeSJYkUaTZ3bx1B/dUO/HjxUGTtgPR4MMqyJ8rC0K/HulGI1jBlz7UHj1xGp+17IdZ47ojdlAsvP5BK9R7r5L6UFUOSv/CohWb0K7XKCz99XskShi2qCKb/z8P/IPurT+NICXnvk2El98XrUHBvNnwXYcv3AP1pvASeo5euXZD+0L+eKtwjnqLbNS3+/K7/8OALl/q55urRMS/9+7dR4wY0SM94KgUXtr3Ho1c2TOhdvUKkH+X4QkvIojK2MqVLIC3KpWOtF1OrdB32BQsXrEZnVvUQ75cz+PU2YtKHP8ZIXfvYXS/b/xKeInIs2/vwSP4fsRvGPFdC6e6zC/HReHFL91Ko0iABEiABAKNwJPCi8t++aDb5JO3Ub5UQSxcvhGDx83C3bt3tRDTSW1Cn8+QGhJt0br7CLUhv6SElvuo8WY5NPigijuyJWO6lPhx7AykTPYcWnzxHo7/e1ZHwiRMEBchIXdVlMeHurtLl6+hQs2vsXzaAJy/eAUd+47Vm/y4cYJ1JEjBPNmecstfh0+gw3djVLTIeaRLnQI92zZQ/08O+dDzpRr3LzOX4dz5S6irhIzPPnxT15+1cA2GT5it7LiH1CmTole7z5E6RRJMmLpIRZkcw507ITj67xlty8AuTZBGRZys2bQb3QZMQEz1Ialm1Zcx+pd5mDS4vY5GWbFuh96Ehigu6dMkV98G10fypInD5PKkEZ36jkOmDKlQt2YlvZEv+Oqn+GPq97oNVzly/LS2K7wPabdu30HF9x9+yy52+XKRD3ixYsZQ356v1v4ppAQYKaGFl3+OnQpzjoycNAeTle+TPJdQz8cRE3/Hkin99Bxr3WMEDqv5d199i12nRkV8+M6rGPXz3Mfm6PR5q3TEyz4VdeSkOfpl+x+QW30I3r7nLzXnLyB92hQY0LmJnhdW5qjU6TPkFz3nY8WMqf99vlQ8/1NTh3M0/H9NYQkvz3oGiTgqYka2zOlw+txFjBvQOsxnSFj+EXEja6a0WLt5N44o4bZQ3uzueXDg0HF07jcOFy5d1cLhVw3ewcslCyJ0xIs8s1t0GYoL6jmbO0cm3Lh5C5UrlHgq4uXk6fN4v1FXLPzlO91WRISXXXsP6X9jcyf08uVHkHvsshZVqNEME9XzPk+OzO7Xr9+4hTmL1+LtymXx6+w/sG33QRX5dB9bdh7Q6+Ogbk312hHWM0f80bbnSJQtUUDV2Y+z5y+j3Vcf6kim2+rfYwc1R7aqNjOkSYEX82XX64lE+0m/XQf8hB17/tbPyA/efgXvVSv/FOs9+/9BG+WHEoVzQ34WQaX9Vx+haMGcOkJr0Jjpek2Xkjfn8+jQ7GP9JYkr4iXb8+meOT5Zh6vWaavau458L2TB6P7f+IWffcEICi++4CWOkQRIgARIwJEEpqOALeN6G9uf6jcs4aVavXZooY4bySa/uhJhfh3eUR/f+fX35Zg+dwUmD+uoBQnZaDb8uCquqs1dhz5jdCi6hKW7jhpVrdtOvybfCLuOGtVQYfJfdx6iPxBLmTF/FZaoKJvBPf6Hdz79FrXeKo8aKupj177DkFD4xZP7uo9Cyfsl/Lv6JyIMVccrZV7UYsiGrX/qb+FEeHmjfHG9kZUP6G/Va4/1c4fqD5jl1LfTs1V0SXq1oZUPlBJV0rF5Xf2t5eBxM9Tvemh75MNLooTxtYDzyntfa0FFNsWDlYg0XH2QX6TGEzNGDFT5uI0+4iMfpMZNWaA2ywfwQ9emYXJJED+um7/Y8FL1pvh5SAc9Hiliq3wg+/jdiihW6IXHBJj/mjAtuw7VH8Lef6vCf731sd+P2LEDny9eHKk6nnjzZ/nyYfhrrz3VlHzAC44dpI+7iSgi8y6aclRo4SWsOSKi2UdNumP2+B762JWIFTIH5IhFn8G/6A8g3VrV1x9kxHcLf/4OKZIlRug56vrwIaKhk+aofOC+ePkqRqlv2eU4YPVP2qP1l7VRrGAuS3NUbO7UvI6eM/JB8OcZS9Cl5ePHSJwyR2/efYCBu86HO+3ixIyGr/KGLzp6qp3QAwlLeHnWM+iYmp+1G3XRz5PXlbgn4nJYz5Cw/CPzQJ4RI9WzLqb68F1N+bGj8mPxQrnVz23RsE41JaQUhwjTtRs/FE5OqygN11GjrzsN0SJxs89qQISamp93Qlfl9yeP1v08Yyl27v0bvdp+ps2NiPAi7yv3zv9UJEhLZFHrhpUyYMAAXL58OdyqzZo1Q8KECcN9jyfaWbZmG3oOmqTXn7CKXjvUujDhx3bIkjEN5DmcNlVyfRQprGfO5avX9PNsSM+vUaZYXsxbukGtQYu1oD9l1jLMWbIeYwe0UuLYVT1fSqijprKG9vrxZ/0MEJ9cvnIdNZTvROR58vil/HuWZ+TIvmo9VHWXrd6K74ZO0RGs0tfoX+aqdasd4gQHoVW34UipIl2bN6zpFl5yZssQ5vgWLt+EaWr9Z8SLldltvQ6FF+vsWJMESIAESCDACThZeJHIC/k2rMfAiZivPrAuWblFiyJyzl+KfCNX6LUGWD9niPqwtlR/8yoCTW71jaAr10HoXC7PEl5kE/mKinD5UQktsmls3HYAKpUrisL5c+DNOm2wcd5wd1vywaDlF7VQpEBO96yRs/YiBm1QgooUGXNISIiOkBHhZVTfljpEXkqJKo3w28jOOmpEvjGMFzdYvz536Xot+Mh7ZfMseT5+7PGV/t3EaYv1N4WfqSNStdW3vuuUrVLkg1LZt7+CHMvasHWv2sSux/A+zfXv5Jvj4qqvbYtGacHgWVxCT/vjJ8+iRoOO7rZddsg3qMJ/p/r2WKKKPv+oKiqWK6LHKKKQ/Owq/Yb9isb13tJCheRFkQ23fDMameJE4UW+YRcxr85XPVGtYim8/cZLbuFFBJWw5ohEs6zetEuLX1LkQ8YPo6dp4UUERol0ElZS3viwlT6apb/FDSUOhs5z4KQ5Kh+c5fiVROpIadrhBx3NUCB3Vktz9LNv+iJTulSoo6KtMqjomWeVyM5RmYPyobNCmULPbM/qHPWUYOKpdkIbF5bw8qxn0M1bt/He552xecEI/XyTCLywniFh+UfmQYE8WXWUXOh58GK+HOrDdgf17BymhUopErHSoHZlHX3hEl5E7JVn1gvZMrrfU1uJtU8KL216jNQRMRIVJkWEl/G/LtCREaGLRIVMG9XF/eFfxOPypQuh+utlIvMYcr/XE4KJNOaJdsQ/v8xcqiMJwyryXJZnvXxpIMW1dkgEZljPHGH4QeNu2ldSJNqycZvvseTX/joaSf5Nu7jLlwB3VQSmrJmv1WqBvt9+oY48PTzW9t3QyYin1rxGdd96bHiyDsiz07U+ur5cWT1rkBZvcmbJgHq1Xtd1Vm/cpaM2xYeuZ58IL2GNj8KLpWltXInCizFCNkACJEACJEAC9hN4MrlujOjR1beVadCqcW0d5ixHNw4dOamP8rjKixU/w4wxXfWGXkSWueobuguXrqC+2uTLBzRdV4QAACAASURBVMOICC+yAZS8JXVqVNLh3LLpPHzsJN7/oov+Bs5V5MPKt83qPCY4SCRMs28H6TpPlifzK7j+LseRJKpljdpoSrl89QbSqGM5Ei79ZIJE198l8kY+gIROSlnglfpYoL5Fnq8+1Et7iRMlcA/h2vWbmPNTT/Va/GdyCT1WCctv1X045k3s/cxJIMeHRPTq1G8sxvRvpaN/nhReQlecs2SdDn8f1vuhEOSrRT7guYQX+QDRsFV/zfTjpj20qCTzNaw5cuT4KRxTx9lcCUDlCIDLfyKkSYj9RXUMI5r60HtAfdgZpb6Zl4iPsIQXJ83RJ3N7uP4u/1atzFH5cD7sp1laVE0QL66OnnkyiXNk56gcgwpPePGXORr631ZEcry4nkEiWktiXjlSKUWek2E9Q8LyT1jzIGvmtGghUYShnonyb0ciAvPkzOwWXiSR+jwV+SBHJaXIeyRC5knhpWGrfuq1Uvp3UuTf5QklFn/T+P3HHi0iYP70Q1u38CLHRCUysv77b/jqI8g97pXrd+gjjX9MfeivZ5Ww1g5JthvWM0ciHz9r2dfdriRVd/390xbfoZri7vKHHJV0PdMKV/oMUjeGiraUIkchK71cVEdMDhk/U7/WqM5b+guMJkoAc0WUyuuyZk8f3VVHY75RoZhbGJN1pWn7gXosoYWXsMZH4cWeaU3hxR7u7JUESIAESIAEPEogrKNGrk6mzV2JxSs3uT/QS4Jc2QDKt3Wu6BF5r+Qiqfu/nvqbP4kGCe+okXww3rrroPr2bRI+rV0FvyvBQEKmT529oEPnXd/UhWWoRLzIUagNc4fpb45lA3pMfSiQCJGwhBfZYMomVkKsE6rN6++L1uo8IuEJL5Kvpo6yac2sH/VQQke8bNq2Tye/HdT9YZRMWCU0F1cUjrxXbsKQfAgu4eWkytvxl9qAlymW77GmZAMsH54kqmfXvkP6iJOIXMK5qTpKIxt8ifSRCB5JSutPwouAkCNh8eIFY6PiLfNGRK2w5ohEYG3avhffq9wnUuYv26A/MIpwJh8Q679fGe9Ufkn/rlLtb5SQ82m4wouT5mhYH7jl23HTObpqw05803UY1qgbeULf0BPZOSpioQgv4qNxKjpCcseUKJxLHxuU4i9zNPQ/0MgKL6E/0MozKCLPkND++brT4MduNXLNi6IFX9ARL65nooyxVsPO+FxFjqVOkdQtvJR560t1BKWlWyip8VkndbTxtaeEl8+/6YeqKtostPDyX8l1Xf9eJf+QPwgvcjSxTLWHvCQ/iquIgNZLHUFq2eh9HTUZ+laj0EJMWM+c8ISXZh1/VNGdL+iExlI69x+vI/Xk2SfPrAEq99iTR4tu3LytIy6lyFogSdvlNqqN84bq6Cc5ZltQRanKjVs9Bk1E9ufTu/0jc0uekVNVVCiFl/BWcnt/R+HFXv7snQRIgARIgAQ8QuC/hBeXGPLbiE76m0w5i77gj006t4mERVerWFqfU5fN6LvqXHnPdp9BRAmX8CJnzf/XoIZ+T+hIGMkf8UrNhyHvr6tv4Fwb/HfV8RsJg5a/S5LInmqjKDdKyIbSVaRuNZW7RW4AkpB2SY4rG0hXjpfQ10m7hJhVG3apJKS79HWnck3q1x0H47rarMp7w/rWUja7crRIxBX5FnHAyKmQ659dOV4kf4ycy5d8ICLsiPAhCYPD4hI6QaPke6ipPvS4jjHJMZma6hiCRBaVL1VI55+RZI0iroz5vpX+WTbQwkbyCEhEkoShu4QXYfDngSOPRSZ5ZIJEcSOhI16ka5kDktBRomAG93x4NC2sOfK3isz64lGETDwVzi/f2p84eU4LLzIPRn7XUh+fkA+8kqSyX8fGel6GnqOhjxo5aY6GJbxUVddeR3aONvusJuo166U/xMlNZnKkSBis+33IY8JLZOfoxm17tfAyZfYyfdOPXLdbS0WwuY5q+Msc9ZTwIkLGs54h4fknLOFFBEURJD/76E1UeaWEPnb4SbPe+rioJMp1HTWSo0DPq1wkkuNFBAOJJJOcM09GvIgoLM+r0EeNIiK8SF4lSchu9ahRFD9u/rM7iZKTnGWyBslx17MqYbt8YRA7KAgDu34Z5tohz+WwnjmpUjwXZsSLrC+SWFmeVdLXe0o8EzFe1qLeKk/VLYkA/bqOPn7Uf/iv2tfyTAtdxPc1PuuojiU10pGi8rwbqY6/Sn6zBX9s1FGsE39sr5+pzTsP1vNB8plFRHiRfDHS1s9q3XMdaftPiHyDMQEKL8YI2QAJkAAJkAAJ2E/gv4QXGaGEFw8eN1NHlsjxnE4t6urwZhEbuqhv5C5duaYTfsqHwMb1qj8msAwZP0slnp2Prz59RwkHd92CjLTb44eJelMrZ89dwookQ+2kBAW5uUU2dnVrVnzmzQ2SGPLbPqPxr/pQkVHlqgh9q9GzhJf46jhFI3WOXpISysa3mRKD5EOCfECQW4TC+tZS8oT0Hz5Fh3hL4tp+arMrSXhTJn/OfSOJfNMv0T+S0FeOroTFJbS35UN9qWpNMEUlKXYl19W5AsbO1DfvQAkv6dXxKLmRSXJmhM7xIkmMJQeKfOvqEl4kYiG/in6Qmy58uTwpvIgtEj3x3ZDJ7lwS4c0ReZ9EVsjtTjIfJa/I/El9dK4G+cAh80A+pMqNIzMXrFIfIDpghop8cs3R1Rt361uNXB9EnTJHxWZJ8PyuSkwtJbQQY2WOyjf1IybO0de+BwfHRtP6KpG0iqwymaOuHC/iLxFmpcjRmoFdm+h/3/4yR0MzMol4kXZcN6M9+QwJyz9hCXAyL1y3GkkCVsllJDdVyfGx0LcayTxqqZ4V8qFeEp7LM7ZsifxPCSUiku1RtzBFNrmu8BABXBKO+0uRSLrJ6vkhUZVJ1NFSeTY0VnlVYsWKGa7wEtYzR3JLtes16plHjSRJvfjnoFrfsj2fFjlUPhbxpyS+lhxlclRIjlDKul1O3YrUqkltfcNR6CL+bqa+WHhZXe29fN127WMR1+SGuNC3GqklSH+h0ObLD7RIGhHhRcQ3iaS6p25xCu8Ilr/43il2UHhxiic4DhIgARIgARIgAa8REIFEimxe5ZrpAq/W18l/5UYI0yKbb7m605UoM7z2whNe5My/JF6UG5JcuRtMx+ar9eWDheu4jBxP6jdsCqaom5H8uThljrqEl4cRLw/FFlfEi0TEcY76ziyUaKcP1Q1hcqNPkIqMiEjZvf8wWqooSBE6WawTCP0MkxuTbiphXxLYR7Q8FF5+pB8iCswH3kfhxQecxCGSAAmQAAmQAAmYEZAcCDXeLIea6o/khJGbPWaM6WbW6KPaEtki3zLOUiHgEvZtVXiZMX+1SuR4ONI3GnnECAc1IseSKr7fEr8oAUqSjbbvPVp/+G/b9AMHjdLzQ3HKHHUJLzrHi4pyk4iAl4rnx1uVSuvIAM5Rz/vemy3KcSPJIVSrWvkIdSPROM+KnolQZb5JE5ArrCVqTxLhPnhwX91Y1g1NPqn+VDRaeLhCRzgRq38QoPDiH36kFSRAAiRAAiRAAuEQkLDuzv3G49r1G0jyXEJ91t91FasnwI3+ZR5On71oWRw4oRINi3gzQd0sIrdEBXr59ffl+kjRfRWdlCt7Rh1iL0KAPxfOUX/2rn22ybHMj1QOmKG9mv1nJN3ilZsxfd4q/V4W6wQkqrK7OoK7fO02FbkXXedokWiXyORTofBinb9Ta1J4capnOC4SIAESIAESIAESIAESIAESIAESIAGfJ0DhxeddSANIgARIgARIgARIgARIgARIgARIgAScSoDCi1M9w3GRAAmQAAmQAAmQAAmQAAmQAAmQAAn4PAEKLz7vQhpAAiRAAiRAAiRAAiRAAiRAAiRAAiTgVAIUXpzqGY6LBEiABEiABEiABEiABEiABEiABEjA5wlQePF5F9IAEiABEiABEiABEiABEiABEiABEiABpxKg8BLKM9+P+A0Ll2/SrxTIkxUdv66LOMFBOHriDNr2HIm9B4/oa9i6fPMJCuTO6lSfclwkQAIkQAIkQAIkQAIkQAIkQAIkQAIOIUDh5ZEjRHAZOWkOJgxqh6BYMdGiyxBkzZQWjetVx0dfdkepInlRv3ZlrFi3HT3UvewLf+mLWDFjOMSNHAYJkAAJkAAJkAAJkAAJkAAJkAAJkIATCVB4eeSVIeNn4cLFK2j/v4/0K5OmL8GWnQfQ7qsPUal2S6ybMwQxYzwUWt5t0BGtGr+PIgVyOtGnHBMJkAAJkAAJkAAJkAAJkAAJkAAJkIBDCFB4eeSIzTv2o0v/8TriJW6c2GjaYRDKly6ILBnT6tdnju3mdlmLLkNRrNALqFGlnEPcyGGQAAmQAAmQAAmQAAmQAAmQAAmQAAk4kQCFl1Be6dh3LGYtXKOOEMXEC9kyYFTflti8cz8GjpyGKcM7ut/ZrtcoZM+SHnVqVNSvXbtzz4m+5Zj8nEDcWDFw6+493H/g54bSPMcRiB4NCFZHLW+E8NnnOOcEwICCYqgJiGi4c+9+AFhLE51GgGuv0zwSOOPh2hs4vnaqpfGDmGbDxDcUXh7R+2XmUixbvQ0DuzZBUFAs9Bk8GTdu3sI7lV9C+96jMXdCLzfnph1+QJli+dwRLxReTKYg61olwM2fVXKsZ0qAmz9TgqxvQoDCiwk91jUlwLXXlCDrWyXAtdcqOdbzFAEKL2YkKbw84tek7UC8VCI/ar5ZTr+ybfdBtO4+ApOHfYtXajbHmtk/Ijh2kP5d5Y9ao6u62ahQ3uz67xRezCYha1sjwM2fNW6sZU6Amz9zhmzBOgEKL9bZsaY5Aa695gzZgjUCXHutcWMtzxGg8GLGksLLI34DRk7F30f+Rf9OjfVtRQNHTcNfh49jUPevUL95H7yYLwcafFBFXTe9Uf9u/qTe7mS7FF7MJiFrWyPAzZ81bqxlToCbP3OGbME6AQov1tmxpjkBrr3mDNmCNQJce61xYy3PEaDwYsaSwssjfjdu3ka3AT9BkuxGjx4dmdKnQsfmdZE6RRKcPH0erboPx579/yB9mhTo3vpT5M6RyU2ewovZJGRtawS4+bPGjbXMCXDzZ86QLVgnQOHFOjvWNCfAtdecIVuwRoBrrzVurOU5AhRezFhSeDHjp2tTePEARDYRaQLc/EUaGSt4iAA3fx4CyWYsEaDwYgkbK3mIANdeD4FkM5EmwLU30shYwcMEKLyYAaXwYsaPwosH+LEJawS4+bPGjbXMCXDzZ86QLVgnQOHFOjvWNCfAtdecIVuwRoBrrzVurOU5AhRezFhSeDHjR+HFA/zYhDUC3PxZ48Za5gS4+TNnyBasE6DwYp0da5oT4NprzpAtWCPAtdcaN9byHAEKL2YsKbyY8aPw4gF+bMIaAW7+rHFjLXMC3PyZM2QL1glQeLHOjjXNCXDtNWfIFqwR4NprjVsg1Dp65QremzMLu8+dMzL3QpOvEEvlOg2rUHgxwgsKL2b8KLx4gB+bsEaAmz9r3FjLnAA3f+YM2YJ1AhRerLNjTXMCXHvNGbIFawS49lrj5u+1/jh2FB/Pm4NLt28bm3q1abNw26DwYoaYwosZPwovHuDHJqwR4ObPGjfWMifAzZ85Q7ZgnQCFF+vsWNOcANdec4ZswRoBrr3WuPlzrb6bNqLrujW4r4ysljUbRr5WCXFixvSayRRezNBSeDHjR+HFA/zYhDUC3PxZ48Za5gS4+TNnyBasE6DwYp0da5oT4NprzpAtWCPAtdcaN3+sdUVFt9RfOB8L/jmsjwb1KFMWDfMX8LqpFF7MEFN4MeNH4cUD/NiENQLc/FnjxlrmBLj5M2fIFqwToPBinR1rmhPg2mvOkC1YI8C11xo3f6t14OIFvDt7Jg5fvowUceNiSpVqKJwqVZSYSeHFDDOFFzN+FF48wI9NWCPAzZ81bqxlToCbP3OGbME6AQov1tmxpjkBrr3mDNmCNQJce61x86das/86iAaLFuDG3bsolio1JlepimRKfImqQuHFjDSFFzN+FF48wI9NWCPAzZ81bqxlToCbP3OGbME6AQov1tmxpjkBrr3mDNmCNQJce61x84daf126hI5rVmH2339pc5q9WBhdSpWJctMovJghp/Bixo/Ciwf4sQlrBLj5s8aNtcwJcPNnzpAtWCdA4cU6O9Y0J8C115whW7BGgGuvNW6+XOvirVvoppLnjti1U5sRL1YsjFIJdKtkyWqLWRRezLBTeDHjR+HFA/zYhDUC3PxZ48Za5gS4+TNnyBasE6DwYp0da5oT4NprzpAtWCPAtdcaN1+sFXL/PoZt34bemzbgskqkG10ZUStnLnQtUwYp4kTd0aIn2VF4MZtNFF7M+FF48QA/NmGNADd/1rixljkBbv7MGbIF6wQovFhnx5rmBLj2mjNkC9YIcO21xs3Xas1SeVw6rF6Jw1eu6KEXT50GA8tXQK6kyWw3hcKLmQsovJjxo/DiAX5swhoBbv6scWMtcwLc/JkzZAvWCfTr2U1Xbt6mvfVGWJMELBLg2msRHKsZE+Daa4zQ0Q1sP3MGLZcvw/pTJ/U4syZOjN4vlcNrmTI7ZtwUXsxcQeHFjB+FFw/wYxPWCHDzZ40ba5kT4ObPnCFbsE6Awot1dqxpToBrrzlDtmCNANdea9ycXkuuhe60djVmHDyAB2qwyYLjoG2JkvgkT17EiBbNUcOn8GLmDgovZvwovHiAH5uwRoCbP2vcWMucADd/5gzZgnUCFF6ss2NNcwJce80ZsgVrBLj2WuPm1Fonr19D7w3rMXr3LvcQmxcughaFiyJ+UJAjh03hxcwtFF7M+FF48QA/NmGNADd/1rixljkBbv7MGbIF6wQovFhnx5rmBLj2mjNkC9YIcO21xs1ptS6pm4r6b9mEYTu24+bdu5CYlho5cqJzqdJIFz+B04b72HgovJi5h8KLGT8KLx7gxyasEeDmzxo31jInwM2fOUO2YJ0AhRfr7FjTnADXXnOGbMEaAa691rg5pZaILEPVTUUiushNRVIkcW6/ci8jX/IUThlmuOOg8GLmJgovZvwovHiAH5uwRoCbP2vcWMucADd/5gzZgnUCFF6ss2NNcwJce80ZsgVrBLj2WuNmZ60/z5/H6hPHseLYURy8eAF7L1zQw8mUMCF6limLKlmy2jm8SPdN4SXSyB6rQOHFjB+FFw/wYxPWCHDzZ40ba5kT4ObPnCFbsE6Awot1dqxpToBrrzlDtmCNANdea9yiqpYkxt119izWKKFllfqz9sQJnL9187HuXYlz6+XOg5jRo0fV0DzWD4UXM5QUXsz4UXjxAD82YY0AN3/WuLGWOQFu/swZsgXrBCi8WGfHmuYEuPaaM2QL1ghw7bXGLSpqrTv5L5osWYQDFy8+1l2O555D/hQpUTRVahROmQovpkoVFcPxWh8UXszQUngx40fhxQP82IQ1Atz8WePGWuYEuPkzZ8gWrBOg8GKdHWuaE+Daa86QLVgjwLXXGjdv1pKIllYrVmDK/r26m7zJkunjQyK0yJ+EsWN7s/sob5vCixlyCi9m/Ci8eIAfm7BGgJs/a9xYy5wAN3/mDNmCdQJBMeQOiGi4c+++9UZYkwQsEuDaaxEcqxkT4NprjNBjDcixonHqGuhv16zCJZUoN07MmGhbrAS+LPQiYkSTNco/C4UXM79SeDHjR+HFA/zYhDUC3PxZ48Za5gS4+TNnyBasE6DwYp0da5oT4NprzpAtWCPAtdcaN0/X2n3uLJosXYwtp0/rpitkyIgfK7yKdAmcfRW0JzhQeDGjSOHFjB+FFw/wYxPWCHDzZ40ba5kT4ObPnCFbsE6Awot1dqxpToBrrzlDtmCNANdea9w8Vet6SAi6rFuD4Tu2496DB0gdNx6+U1dBV8uazVNdOL4dCi9mLqLwYsaPwosH+LEJawS4+bPGjbXMCXDzZ86QLVgnQOHFOjvWNCfAtdecIVuwRoBrrzVuprVuKsFl4r69GLVzO+R6aCmf5c2HzqXKIH5QkGnzPlWfwouZuyi8mPGj8OIBfmzCGgFu/qxxYy1zAtz8mTNkC9YJUHixzo41zQlw7TVnyBasEeDaa42b1VqSOHfo9m0YsXMHLt66pZspmCIFBpV/Vd1UlMJqsz5dj8KLmfscI7yE3L2HOYvXYvna7fjn+ClULFcUjepUw4z5q1Aob3ZkTJfSzFIv1r52554XW2fTJPBsAtz8cWbYRYCbP7vIs18hQOGF88BOAlx77aQf2H1z7Y0a/5+4dhXfb96En/7cg5t37+pOX06fAc0KF9H/D+RC4cXM+44QXi5dvob6zftg319H3dZ8+M6raPPlB2jYqh92/nkIkwa3R+YMqc2s9VJtCi9eAstmwyXAzR8niF0EuPmzizz7pfDCOWA3Aa69dnsgcPvn2utd3/916RK6r1+LqQf2uzuqqq6G/qZoceRPnty7nftI6xRezBzlCOHl2+/GYNrclUidMinKFs+PybOWwSW8tOs1CjMXrMbr5Yuh77dfmFnrpdoUXrwEls1SeOEccCQBbv4c6ZaAGRQjXgLG1Y40lMKLI90SEIPi2us9N3dVSXP7bNro7qBe7jz4ukgxZEqY0Hud+mDLFF7MnOYI4aXMW18ifry4mDGmK4JjByF3ubpu4eX+/Qd448NWuHnrNlZMH2hmrZdqU3jxElg2S+GFc8CRBLj5c6RbAmZQFF4CxtWONJTCiyPdEhCD4trreTcvO3pEXQ29BMeuXtGN18+TF+1LlESyOHE935kftEjhxcyJjhBe8leojwplXkT/To20NaGFF/l7rS+6YN/BI9i+ZLSZtV6qTeHFS2DZLIUXzgFHEuDmz5FuCZhB9evZTdvavE37gLGZhjqHAIUX5/gi0EbCtddzHj938wZarljuPlaUI0kSDHulIgqnSuW5TvywJQovZk51hPBS8f2WuHz1Okb2bYm8OTM/JrwsXL4JLboMQZqUybDwl+/MrPVSbQovXgLLZim8cA44kgA3f450S8AMisJLwLjakYZSeHGkWwJiUFx7zd38QDUxZvcudFyzCpdv30bcWLHQrlgJNC5YCDGiRTPvwM9boPBi5mBHCC8DRk7FyElztCWpUyTByTMXkDhRfMSIHh3nLz4K/Xr/DXz9eU0za/+j9oZte9G53zicPX9Z3aSUDX3aN0SihPFw9MQZtO05EntV1E3aVMnQ5ZtPUCB3VndrFF686hY2HgYBbv44NewiwM2fXeTZrxCg8MJ5YCcBrr120g/svrn2Wvf/ocuXsVQdK/pF3VS06fQp3dCbKnFuv3IvI3W8+NYbDrCaFF7MHO4I4eXmrTv69qLNO/4/i3Ros0QEGd6nBeLGiW1mbTi1JeKmap22+K7DF8ifOwu6D5yAF7JlxPtvVcBHX3ZHqSJ5Ub92ZaxYtx09fpioom/6IlbMGLpFCi9ecwsbDocAN3+cHnYR4ObPLvLsl8IL54DdBLj22u2BwO0/0NfeS7du4bASUJKrvKDp4icIdyKI0LLq+DGsVH9WHz+Of69fc79f6n7/cnlUyvx84E4mi5ZTeLEI7lE1RwgvMpZ79+5j/rINWLF+O06evqCHJ9ElZYrlQ6XyRREzxkORw1tl+ryVWLdljxZeQheJuKlUuyXWzRniHsO7DTqiVeP3UaRATv1WCi/e8grbDY8AN3+cH3YRCPTNn13c2e9DAox44UywkwDXXjvpB3bfgbz2Dtq6Bb03bdDHg1wlUezYSBEnDlLGjYcU8eIhufr5ovr9k0KL6/2l0qTFq5kyo3GBggiOGTOwJ5NF6ym8WAT3qJpjhBczM8xr9xw0CXfv3sM/x0/hyPHTeDFfdnT438c4cOg4uvQfj5ljHybzk9Kiy1AUK/QCalQpp/9O4cWcP1uIPAFu/iLPjDU8QyCQN3+eIchWTAhQeDGhx7qmBLj2mhJkfasEAnHt/Xnfn+iyZg1OhIpYiQg/yd1SPFVqvJQ+A0qkSYOSSnRhMSdA4cWMoSOEl627DoRrhUTD3LodoqJf8ppZG05tyeGybfdBjPm+NZImToDWPUYiWZJEKFcyPwaOnIYpwzu6a7frNQrZs6RHnRoV9Wt37kmqJhYSiFoCsWJEw1113foDTr+oBc/eIPnnYqodYAiffZwNNhDo2a2L7rVN+29t6J1dBjoBrr2BPgPssz+Q1t55hw6h9coV2H/x0SmI+PHRqVRpfJwrt9sBl1R0y+kb13H6+g31R/1f/SylZNq0KJQipX2O8uOeg9RnDxbrBBwhvMj10REpe5aPi8jbLL1HIl6iq2S+coRIiohBnfqNR+cWddG+92jMndDL3W7TDj/oI1CuiJc7ShhiIYGoJhBLzde79++DuktUk2d/suzGVPMvRM0/FhKIagI9u3XVXbZp3yGqu2Z/JACuvZwEdhEIhLV3i0p823z5cqz791+NOak6PtS6aFE0zF8AQV5OO2GXX32p36AY0X1puI4bK4WXRy6ZOG0x9uz/Bz3bNtCvbNl5QCfRHdWvJV6p2RxrZv+I4NhB+neVP2qNrupmo0J5s+u/86iR4+Z1QAyI4c4B4WZHGhmI4c6OdESADopHjQLU8Q4xm2uvQxwRgMPw97W3yZJFGK9uHZISR+Vg+d+LhdG04IuIH/Tw8xeL/QR41MjMB44QXp511ChE5VuRXCuTpi9Gtszp0LpJbX30x1vl3IXL+lajMd+3QpaMafBNt2FIkzIZWjaqhfrN+6icLznQ4IMqWLh8IwaOmob5k3q7k+1SePGWV9hueAS4+eP8sIuAv2/+7OLKfiNG4GGoczR1zJcRVxEjxnd5kgDXXk/SZFuRIeCva+/1kBC89/ssrFA3EEn5PF9+tC5WHMnixI0MHr43CghQeDGD7AjhJTwTrt+4hdc/+AY133wZTT6pbmbtf9Re8MdG9B06GTdv30GJF3OjU/O6iB8vjrpl6TxadR+uI2LSp0mB7q0/Re4cmdytUXjxqlvYsBPd+gAAIABJREFUeBgEuPnj1LCLgL9u/uziyX4jR4DCS+R48d2eJcC117M82VrECfjj2vvvtWuoOnMa9l+4gNjqKNGEN6rgdV7zHPFJEcXvpPBiBtzxwouYV/PzTjhz7hKWTxtgZq2XalN48RJYNhsuAW7+OEHsIuCPmz+7WLLfyBOg8BJ5ZqzhOQJcez3Hki1FjoC/rb27z51F1RnTcfbmDXUVdFxMq/YWCjIpbuQmRRS/m8KLGXBHCC9yzOfJ8kBd1XLx8jXMW7oeIyfNQby4wdg4b5iZtV6qTeHFS2DZLIUXzgFHEvC3zZ8jIXNQYRKg8MLJYScBCi920g/svv1p7V1y5B/Unvs7bt69i9xJk2F6tepIo24uYnE2AQovZv5xhPASkVuNShbOg5F9W5hZ66XaFF68BJbNUnjhHHAkAX/a/DkSMAcVLgEKL5wgdhKg8GIn/cDu21/W3nG7d6HpsiX6Vs4KGTLi58pvIm6sWIHtXB+xnsKLmaN8QnjJnCE1hvRshgxpU5hZ66XaFF68BJbNUnjhHHAkAX/Z/DkSLgf1nwQovPwnIr7BiwQovHgRLpsOl4Cvr70itLRZuRyDt2/TdjYuUBA9ypRF9GiSMJ3FFwhQeDHzkiOEl6lzVjzTiuDgIKRNlQz5XsiCGA6+N5zCi9kkZG1rBLj5s8aNtcwJ+Prmz5wAW7CTAIUXO+mzb669nAN2EbB77d159izmHPorXPNzPJcEN+/dw5nr13Hy+jWcuXED59Sf+5JC4vYt7Dl/Xtf/ofwrqJcnr10o2a9FAhReLIJ7VM0RwouZCfbXpvBivw8CcQTc/AWi151hs92bP2dQ4CjsIkDhxS7y7FcIcO3lPLCLgJ1r7+bTp/Dm9Km4pq5+NikJgoL00aJy6TOYNMO6NhGg8GIG3jbhZeuuA5EeeaG82SNdJyoqUHiJCsrs40kC3PxxTthFwM7Nn102s1/nEKDw4hxfBOJIuPYGotedYbNda++af0/gnVkzcF2JLq9lzIQXU6UKE0iMaNGRKHZsJIwdhERBsZE4OBjxYwUhsbymRJfn1N9ZfJcAhRcz39kmvEQkoe6Tpu1ZPs7MWi/VpvDiJbBsNlwC3PxxgthFwK7Nn132sl9nEejXs5seUPM27Z01MI4mIAhw7Q0INzvSSDvW3uXHjqLG7Jm4pY4PfZQrNwZXeBXRmJPFkfMjKgZF4cWMMoUXM366NoUXD0BkE5EmwM1fpJGxgocI2LH589DQ2YwfEKDw4gdO9GETuPb6sPN8fOhRvfYu+ucw3pszG3fv30cjlQi390vlfJwgh29KgMKLGUHbhJeN2/ZFeuRFC+aMdJ2oqEDhJSoos48nCXDzxzlhF4Go3vzZZSf7dSYBCi/O9EugjIprb6B42nl2RuXaO/fQ3/hg7u+4p5LidiheEt8ULeY8IBxRlBOg8GKG3DbhJTLDnjxrGS5evoovPq4WmWpR9l4KL1GGmh2FIsDNH6eDXQSicvNnl43s17kEKLw41zeBMDKuvYHgZWfaGFVr74yDB1Bn/lzI9c/flyuPT/PldyYQjirKCVB4MUPuKOHl6IkzOHriNO7evee26vrNWxg4ciouXLqCzQtGmFnrpdoUXrwEls2GS4CbP04QuwhE1ebPLvvYr7MJUHhxtn/8fXRce/3dw861LyrW3in79uLTRQsQTWEY+VolvJfzBecC4ciinACFFzPkjhBerly7geadhmDt5t1hWpMsSSKsmD7QzFov1abw4iWwbJbCC+eAIwlExebPkYZzUI4gQOHFEW4I2EFQeAlY19tuuLfX3tG7d+F/y5ZoOydXqYrKz2ex3WYOwFkEKLyY+cMRwkuPHyZh0vTFYVqS94Xn0bhudZQpltfMWi/VpvDiJbBslsIL54AjCXh78+dIozkoxxCg8OIYVwTkQCi8BKTbHWG0N9fekbt24us/liI4RgxMq1YdL6VL7wibOQhnEaDwYuYPRwgvr9VqoXK4XEPnFvWQOFE8NGjRF+2++gjp06TAsJ9mIbp60gzu2QwJ48c1s9ZLtSm8eAksm6XwwjngSALe3Pw50mAOylEEKLw4yh0BNxgKLwHncscY7K21d9TOHWi2fBliRY+OX1SkS8VMmR1jMwfiLAIUXsz84QjhpcCrn6J0kbz4scdXOHX2AirU+Fr//HLJgghR+V7e/qQ98uXKgu6tPzWz1ku1Kbx4CSybpfDCOeBIAt7a/DnSWA7KcQQovDjOJQE1IAovAeVuRxnrjbXXJbrEiBYNE9+ogipZsjrKZg7GWQQovJj5wxHCiwgtUsYOaIVECeKjZNXGaN6wJj6p9YZ+XSJgdu87hHVzhphZ66XaFF68BJbNUnjhHHAkAW9s/hxpKAflSAJBMSTtYzTcuXffkePjoPybAIUX//avk63z9NrrEl2iK9FlTMXX8U72HE42n2NzAAEKL2ZOcITw0q7XKMxcsBqpUybFkin9UOT1hggJCVE5XfLh1u0QnXQ3UcJ4WDt7sJm1XqpN4cVLYNkshRfOAUcS8PTmz5FGclCOJUDhxbGuCYiBUXgJCDc70khPrr0u0UVk7OGvVcT7OXM50mYOylkEKLyY+cMRwsuJU+dQp2kP9QVWNC28dB84AT/PWPqYZW++VhK92n5mZq2XalN48RJYNkvhhXPAkQQ8uflzpIEclKMJUHhxtHv8fnAUXvzexY410FNrr0t0EUMHlX8FdfM48/ISxzoigAdG4cXM+Y4QXsSEy1evY+2m3Xi9fDHcvHUH/YZNwfK123BXhRKXLpoXLRvVUseQ4plZ66XaFF68BJbNUnjhHHAkAU9t/hxpHAfleAIUXhzvIr8eIIUXv3avo43zxNobWnTpW/ZlfJ6/gKNt5uCcRYDCi5k/HCG8rN/6J4oWeEHfXuSLhcKLL3rN98fMzZ/v+9BXLfDE5s9Xbee47SdA4cV+HwTyCLj2BrL37bU9MmvvkStX8O/1azih/n/i+nVcD7mDczduQK6NltKrTFk0LljIXoPYu88RoPBi5jJHCC+5y9VF8qSJdbRL5VeKI08O37rGjMKL2SRkbWsEuPmzxo21zAlEZvNn3htbIIHHCVB44YywkwDXXjvpB3bfrrV319nzOHHt6kNh5ar8UeLKtWs4deM6jl25irM3b4QL6tsSpdCySNHAhknrLRGg8GIJm7uSY4SX0GZkSJsSVZQAU/mVEsiUPpWZhVFQm8JLFEBmF08R4OaPk8IuAhRe7CLPfoUAhRfOAzsJcO21k37g9C0RKwcvXlB/LmL/hfP4+9Il9f8LOKnElYiUJLGDkUbdFJs6XnykjR8f6RIkRGr1/yyJE6NUmrQRaYLvIYGnCFB4MZsUjhBelq7aiqWrt2D5uu24fOXxB0qu7Jl0FMwb5YsjRbLEZtZ6qTaFFy+BZbPhEuDmjxPELgIUXuwiz34pvHAO2E2Aa6/dHvDP/q/duYOhO7Zj1l8HsOPs2XCNTKvEFBFRRFCR/4uokiZePKRNkEALLZkTJfJPSLTKdgIUXsxc4AjhxWXCPZVId+uuA/hjzTYsU3+O/XvGbV00dePR7j/GmlnrpdoUXrwEls1SeOEccCQBCi+OdEvADIoRLwHjakcaSuHFkW7x2UFduX0bQ7Zvw+DtW3FJ/ewqCYOCkP25JPpPjiT//ydf8mS4EXLPZ+3lwH2bAIUXM/85Snh50pQN2/bi++G/Yte+w/pXe5aPM7PWS7UpvHgJLJul8MI54EgCFF4c6ZaAGVS/nt20rc3btA8Ym2mocwhQeHGOL3x5JBdv3cKALZswfOcOlfg2RJuSVR0DalWsOF5OnwEp4z59kyvXXl/2uH+MncKLmR8dJbzcv/8AO/f+jRXrdmDl+h3Y99fRx6yj8GLmbNb2LwLc/PmXP33JGm7+fMlb/jdWCi/+51Nfsohrry95y3ljPacS3w7YslnfLnTjkeDyYsqUaF64KKpkyYrw7nfl2us8fwbaiCi8mHncEcLLwuUbsXztDqzasBMXL199zKLUKZOi0stF9R+n3nbEiBezScja1ghw82eNG2uZE+Dmz5whW7BOgMKLdXasaU6Aa685w0Btoeu6NeizaaPb/AoZMqJZ4SIomy59hJBw7Y0QJr7JiwQovJjBdYTwItdJhy6SRLdiuaL6eun8ubKYWRgFtSm8RAFkdvEUAW7+OCnsIsDNn13k2a8QoPDCeWAnAa69dtL3zb6XHzuKr5YtwaHLl7UB1bNmQ/Mi6jNO8uSRMohrb6Rw8c1eIEDhxQyqY4SXZEkS4bWyhbXYUjBPNkgyXV8pFF58xVP+NU5u/vzLn75kDTd/vuQt/xsrhRf/86kvWcS115e8Ze9Y5VhRq5Ur8Ov+fXogctvQiNcqoXjqNJYGxrXXEjZW8iABCi9mMB0hvEgS3SL5cyK6PFF8sFB48UGn+cGQufnzAyf6qAnc/Pmo4/xk2BRe/MSRPmoG114fdVwUDvuB6mvc7l34ds0qfVNRcIwYaKEiXJq9WBhB6merhWuvVXKs5ykCFF7MSDpCeDEzwf7aFF7s90EgjoCbv0D0ujNs5ubPGX4I1FFQeAlUzzvDbq69zvCDU0ex7/x5NFyyEFtOn9ZDLJkmrYpyqYiMCRMZD5lrrzFCNmBIgMKLGUAKL2b8dG0KLx6AyCYiTYCbv0gjYwUPEeDmz0Mg2YwlAhReLGFjJQ8R4NrrIZB+1szJ69cw6c8/0Vkl0JWSNDgOvitbDjVy5PSYpVx7PYaSDVkkQOHFIrhH1Si8mPGj8OIBfmzCGgFu/qxxYy1zAtz8mTNkC9YJUHixzo41zQlw7TVn6E8t7LtwAf3VTUVTD+5HyP37+jroennyolvpl5AgKMijpnLt9ShONmaBAIUXC9BCVaHw8gx+g8fOwJTZf2DljB/0b4+eOIO2PUdi78EjSJsqGbp88wkK5M7qrsmIF7NJyNrWCHDzZ40ba5kT4ObPnCFbsE4gKIZ8tImGO/fuW2+ENUnAIgGuvRbB+Vk1ualowJbNWHr0iLYsproU5N3sOfFN0WLI9txzXrGWa69XsLLRSBCg8BIJWM94K4WXJ6D8c+wUGrcdgKvXbriFl4++7I5SRfKifu3KWLFuO3r8MBELf+mLWDEfJsii8GI2CVnbGgFu/qxxYy1zAtz8mTNkC9YJUHixzo41zQlw7TVn6Kst3HvwANMP7MfArZux4+xZbUbcWLFQJ1duNCtcBKnjxfeqaVx7vYqXjUeAAIWXCEAK5y22CS/L126P9MjLlSwQ6TqRrVCvWS+8V7W8Flck4uX8xSuoVLsl1s0ZgpiPMpG/26AjWjV+H0UKPDy3SeElspT5fk8Q4ObPExTZhhUC3PxZocY6niJA4cVTJNmOFQJce61Q8486TZYswvg/92hjksQOxucFCqBh/gJIovK5REXh2hsVlNlHeAQovJjND9uEl9zl6kZ65HuWj4t0nchUmLlgNTZs3YtvGtdCtbrttPCydddBdOk/HjPHdnM31aLLUBQr9AJqVCmnX6PwEhnKfK+nCHDz5ymSbCeyBLj5iywxvt+TBCi8eJIm24osAa69kSXmH+9fcuQfVJ81A/FVhEunkqXxce48iBMzZpQax7U3SnGzs2cQoPBiNi1sF16CgmLhgQrdCwm5+5+WeFN4uXT5Gj5UR4omDGqrx+ESXtZu3o2BI6dhyvCO7vG16zUK2bOkR50aFfVr99X4WUggqglEV+eJOfeimjr7cxHg/ONcsItANJ2+Enig/mMhgagmwGdfVBO3v78rt28j++jROHvzJka8+irq58tn26A4/2xDz44VAZl/LNYJ2C68yPGdvC88j6IFc6Jk4TzInysLoomk+4ziOupj3dywa4qYUrTgC6hWsRQuXr7qFl627T6I9r1HY+6EXu7KTTv8gDLF8rkjXm6EMMGfN3zCNsMnEBwzuk4ueZ+fPThVopiAPKKDYkTHrbt89kUxenanCMTS6dWiIeQeH36cEFFPgGtv1DO3u8dPFszDlP37UDZdesx7p4Ztw+Haaxt6dvyIQNxY0cnCgIBtwsuyNduwfO02lax2B85duOw2IUniBChbogDKly6khJjcCI7t2avYwmJVsmpjdw4XicC5qCJgZCwSAfN2/W+xZvaP7rFU/qg1uqqbjQrlza6b41EjgxnIqpYJMNzZMjpWNCTAcGdDgKxuRIBHjYzwsbIhAa69hgB9rPqcv//C+3N/R1x1rGj7x/WQOr53E+iGh4drr49NHj8cLo8amTnVNuHFNWwROfYc+AcrVLLdP9QfubLZVWKrY0iliuTRIoyIMSKEREUJHfEi/dVv3gcv5suBBh9UwcLlGzFw1DTMn9TbLdRQeIkKr7CPJwlw88c5YRcBbv7sIs9+hQCFF84DOwlw7bWTftT2feHWLRQYPwYX1VGjwRVe1Xld7Cxce+2kz76FAIUXs3lgu/Dy5PDPnLuEFeu3Y83G3SrR7Z+4oq51lhJNnSnb/cdYM2sjWPtJ4eXk6fNo1X049uz/B+nTpED31p8id45M7tYovEQQLN/mUQLc/HkUJxuLBAFu/iIBi2/1OAEKLx5HygYjQYBrbyRg+fhba82ZjbmH/sZL6ojR3Lfftd0arr22uyDgB0DhxWwKOE54OXT0JFau34FN2/dhy84DuGqD8BJZpBReIkuM7/cEAW7+PEGRbVghwM2fFWqs4ykC/Xo+vGWweZv2nmqS7ZBAhAlw7Y0wKp9+4+R9e9Fg0QIkCArClg/r2HrEyAWSa69PTym/GDyFFzM32i683FPJQbfv+QvL1mzFHyrvy5Hjp90WyVEjSbhbvnRBfdQo6XMJzaz1Um0KL14Cy2bDJcDNHyeIXQS4+bOLPPsVAhReOA/sJMC11076UdP3yWvX8OLE8bh65w6GvvIaPsyVO2o6/o9euPY6wg0BPQgKL2but014WbRisxZa5FjR5SvX3VY8lygBypVUyXVLFUQJJbrECY6a5LomGCm8mNBjXasEuPmzSo71TAlw82dKkPVNCFB4MaHHuqYEuPaaEnR+/crTp2Ll8WN4NWMmTK9W3TED5trrGFcE7EAovJi53jbhJXe5unrkMdSVpPleyKJvMCqpEunKz9HDuE7azFTv1abw4j22bDlsAtz8cXbYRYCbP7vIs18hQOGF88BOAlx77aT/7L5v3r2L9Sf/xdoTx7H73Dm88XwWfGQxSmX8nt1osnQx4seKhW116iFV3HiOMZhrr2NcEbADofBi5nrbhRe5LlrlzcXtOyG4f/9BuNbsWT7OzFov1abw4iWwbDZcAtz8cYLYRYCbP7vIs18KL5wDdhPg2mu3B4CL6rahdf+e0FEpIrhsOf3/aQpco5PcLO9my47P8xdE7mTJIjTo49euovCE8bgeEoKRFSuhVo4XIlQvqt7EtTeqSLOfsAhQeDGbG7YLL5EZPoWXyNDie/2dADd//u5h59rHzZ9zfRMII2PESyB42bk2cu21xzcihozetROT9u7Bn+fPPzWIAilSoHTadIgbMybmqJuIQr+nUMqUqJM7L97LkRPxVCSLq2w4dRKbT57U4s3mU6cgwouUSpky47eqb9ljaDi9cu11nEsCbkAUXsxcbpvwsnzt9kiPXHK/OLEw4sWJXvH/MXHz5/8+dqqF3Pw51TOBMS4KL4HhZ6daybU3aj1z5uYN/Lh1C0bu3IFrSnxxlfzJk6OMuua5rPojgkt8FeESumw/cwbjdu/E5P37dASLlDhKlKmQISP+vX4NW58RJZMtcWIUSZUGXUqXRkoHHTFy2cW1N2rnHnt7mgCFF7NZYZvwYjZsZ9Wm8OIsfwTKaLj5CxRPO89Obv6c55NAGhGFl0DytvNs5dobNT7558oV9N+0AWNVzhVXSRMvPpoXKaqOAOVEwtixIzQQyf8y/eABjFHRMhtVhEvoUjRVahRPkwal0qTV/08SHCdCbdr1Jq69dpFnvy4CFF7M5oJtwsuUWcvCHHk0lfQlbtxgZMucDjmypDezMApqU3iJAsjs4ikC3PxxUthFgJs/u8izXyFA4YXzwE4CXHufpn/l9m2sVTlXJO/KNhVpEhQjhk5OK8d65I+IJHFjqp9VVIrrdf1/9fd46nWJVokbKybiq5//vnQJfTdvxMy/Dro7yqdytHxduCjeyZ7DyPX7L1zAkiP/oFCqVCiROo1RW3ZU5tprB3X2GZoAhRez+WCb8OK61ei/hp8nR2b06dAQGdOl/K+32vZ7Ci+2oQ/ojrn5C2j322o8N3+24g/4zoNiqIz8iIY79+4HPAsCiHoCXHuBk+qozurjx7FB5UZZrW4S2vOMnCue8MwbmZ9Ho4KF9HEiFoBrL2eB3QQovJh5wPHCi5iXPGlizBzTDYkTxTez1ku1Kbx4CSybDZcAN3+cIHYR4ObPLvLsVwhQeOE8sJNAIK+9IrI0WLjAnYQ2tB/yqqgUybWSODj4me65pY78XL9zR+VpuYsbd0NwTf0suVeuh8hr6v/qdtNr6nV57aMXcqHpi0WQM0kSO13tuL659jrOJQE3IAovZi63TXjZ99fRMEf+4MEDnD57EUtWbcGM+av0+xp8UAX/a/CumbVeqk3hxUtg2SyFF84BRxLg5s+RbgmYQVF4CRhXO9LQQBVe5MafUpMm4sLtW9ovktxWhJaXVDRKKfX/RBHMueJIp/rIoLj2+oij/HiYFF7MnGub8BLRYff68WdMmLpI53uZObZbRKtF6fsovEQpbnb2iECgbv44AewnwM2f/T4I5BFQeAlk79tve6CuvaV/mYgdZ8/idXX8Z+RrlSi02DAVufbaAJ1dPkaAwovZhHC88LJr32HUatgZcYKDsHnBCDNrvVSbwouXwLLZcAkE6uaP08J+Atz82e+DQB4BhZdA9r79tgfi2ltn/lx9M1DmRImwqtYHFF1smoZce20Cz27dBCi8mE0Gxwsv+/8+hrfrd0CsmDGwfcloM2u9VJvCi5fAslkKL5wDjiTAzZ8j3RIwg6LwEjCudqShgSa8DNm+Fa1WrkCcmDGxWoku2Zl3xbZ5ybXXNvTs+BEBCi9mU8Hxwsuwn2Zj0JjpSJMqGRZP7mtmrZdqU3jxElg2S+GFc8CRBLj5c6RbAmZQFF4CxtWONDSQhBe5HrrStN9wX+VenPRGFVTNms2RPgmUQXHtDRRPO9dOCi9mvrFNeDl4+Hi4Iz9/4QpWbdyJiVMX4+69e6j+ehl0a1XfzFov1abw4iWwbJbCC+eAIwlw8+dItwTMoCi8BIyrHWlooAgvp9SV0UUn/oSLt2/ja3XDUOdSpR3pj0AaFNfeQPK2M22l8GLmF9uEl9zl6kZ45MGxgzB1ZGdkzpA6wnWi8o0UXqKSNvtyEQiUzR897jwC3Pw5zyeBNCIKL4HkbefZGghr72119XP53yZjp0qmWy59Bsx6621EjxbNec4IsBFx7Q0whzvQXAovZk5xvPCSOkUS9GjzGYoWzGlmqRdrU3jxIlw2HSaBQNj80f3OJMDNnzP9Eiij6tfz4Q2Hzdu0DxSTaaeDCATC2utKppsufgKs/+AjJtN1yPzj2usQRwTwMCi8mDnfNuFl0vQl4Y5colwypE2BAnmy6cS6Ti4UXpzsHf8dWyBs/vzXe75tGTd/vu0/Xx89hRdf96Bvj9/f197QyXT/qPk+cidL5tsO86PRc+31I2f6qCkUXswcZ5vwYjZsZ9Wm8OIsfwTKaPx98xcofvRFO7n580Wv+c+YKbz4jy990RJ/XXuPX72Cn/fuRdf1a7Vbxr9eGW9ny+6LLvLbMXPt9VvX+oxhFF7MXGW78LJ110Ed2ZIsSSK3Jb8vWovFqzbj4qVryJMzMz6tXRlJn0toZqkXa1N48SJcNh0mAX/d/NHlzifAzZ/zfeTPI6Tw4s/edb5t/rT23gwJwcy/D2Linj1YeeL/L734smAh9ChT1vnOCLARcu0NMIc70FwKL2ZOsU14uXMnBF99+yNWrt+BH3t8hZdLFtSWDBg5FSMnzXnMqrTqKumpo7ogYfy4ZtZ6qTaFFy+BZbPhEvCnzR9d7VsEuPnzLX/522gpvPibR33LHn9Ye9ed/FeJLbsx/eABXFPii5TgGDHwprouum7uPCiTLj2YStd585Jrr/N8EmgjovBi5nHbhJch42dh8NgZevStGr+Pj2tUxPmLV1ChRjOE3L2HRAnjqUiYlNi97zAePHiARnWqoXG96mbWeqk2hRcvgWWzFF44BxxJgJs/R7olYAZF4SVgXO1IQ50gvFxXYsm1kDu4HnIX1+6o/98NwXX1fxFRHv7u4d9v3bv7FMP5hw9h+5kz7tdzJU2KT/MVwHvZcyBh7NiOZM5BPSTAtZczwW4CFF7MPGCb8PLOp99i319HUeWVEmjb9EMttMyYvwrte49G7KBYmPNTT6RRkS7jpizAd0MnI1f2TPhtRCcza71Um8KLl8CyWQovnAOOJMDNnyPdEjCDovASMK52pKGeFl4OXb6MzSoCZcuZ09h48iQ2nz7ldbsTBAWhds4X8GGuPCiQIoXX+2MHniHAtdczHNmKdQIUXqyzk5q2CS+FK32G2+q40drZg5Hg0RGiNj1GYvaiNXi9fDH0/fYLbdnpsxdRXkXBxIsbjI3zhplZ66XaFF68BJbNUnjhHHAkAW7+HOmWgBkUhZeAcbUjDTUVXv44dhTr/1VCixJY1ivB5fLt25G2M07MmIgXMxbiqS8q48eKhbjq5/hKTImnfo4XK0i9pn6v/h5f/yzvk989rJMoOBhl0qaLdJ+sYD8Brr32+yDQR0DhxWwG2Ca85Hm5HhInjI/Vswa5LXitVgucOHUOnVrURY0q5fTrN2/dgYg00dXTZteysWbWeqk2hRcvgWWzFF44BxxJgJs/R7olYAZF4SVgXO1IQyMrvFy6dQuL/jmM6X8dxLKjR3Dz7uPHf0QYKZIqNQqnSoViqdOon1MhSXAcR9rOQdlLgGuvvfzZO5TAG4NEgyH1AAAgAElEQVQYDAjYJrwUfaMhbt8Owcb5w/TRoqMnTuP1D1ppU2aP74EsGdPon12vM+LFwMus6pcEIrv580sINMoWAtz82YKdnT4iEBRD0n5Gw51798mEBKKcQETW3sPq+NCcv//CvEN/Y/W/Jx4bY7r4CVA+QwYUVSJL4ZSpkDtZsii3gR36JgGuvb7pN38aNYUXM2/aJrzUbtQVO/78G3VrVkLlV4rj+xFTsXbzbn2t9IrpA91W9Rn8C8b/thB5cmTGlOEdzaz1Um1GvHgJLJsNl0BENn9ESALeIMDNnzeoss2IEqDwElFSfJ83CIS39kpES7vVK7H73LnHupYEtpWfz4JqWbIhP3OqeMMtAdEm196AcLOjjaTwYuYe24SXCVMXodePPz81+oYfV8WXn7ytX2/ZdSjmLd2gf5bX5HdOLBRenOgV/x8ThRf/97FTLeTmz6meCYxxUXgJDD871cpnrb1XVJ6WliuW4+d9f7qHXVwdH6qWLTuqZMmKTAkTOtUcjsuHCHDt9SFn+elQKbyYOdY24SVEXYH3ZfuBWLVhl9uCF/Nlx/A+LRAnOEi/Vuernti8Yz9yZs2A8QPbIH48Z555pfBiNglZ2xoBCi/WuLGWOQFu/swZsgXrBCi8WGfHmuYEnlx7px88gBbL/8DZmzd04++qa5m/K1sOyeLENe+MLZBAKAJcezkd7CZA4cXMA7YJLzLsBw8eaGHl+MmzSJc6OQrnz4Fo0eTs9sMyYORUXL9xE03qva2vm3ZqofDiVM/497govPi3f51sHTd/TvaO/4+Nwov/+9jJFrrW3tPXb+CLJYuwUCXOlZIjSRIMfLkCSvHGICe7z6fHxrXXp93nF4On8GLmRluFF7OhO6c2hRfn+CKQRkLhJZC87Sxbuflzlj8CbTQUXgLN486yV9beETt2ovWqFfoq6ATqqub2xUvi8/wFECPUl4fOGjVH4w8EuPb6gxd92wYKL2b+s014mTJrWZgjl6iXuHGDkS1zOuTIkt7MwiioTeElCiCzi6cIUHjhpLCLADd/dpFnv0KAwgvngV0Ejl65gi+XLsayY0f1ED56IRe6lC7DY0V2OSTA+uXaG2AOd6C5FF7MnGKb8JK7XN0IjVxuM+rToSEypksZofebvGnoT7MweeYySP6ZkkXyoEvLeogbJ1hdaX0GbXuOxN6DR5A2VTJ0+eYTFMid1d0VhRcT6qxrlQCFF6vkWM+UADd/pgRZ34QAhRcTeqxrhcDd+/fx/ZbN6LNxPW7du4c8SZPh+/IVUFxdCc1CAlFFgGtvVJFmP2ERoPBiNjccL7yIecmTJsbMMd2QOFF8M2vDqb1oxWb8MHoaxvRvpZL4BqvEvz/gxXw50KhONXz0ZXeUKpIX9WtXxop129Hjh4lY+EtfxIoZ4//aOw/wqIouDH9JICQQEgIh9N6lI0U6IiAoNgQboiJgAUWR3qRLkY6gSFXEglJEiggqRao06R2khdBCSKWE/HMm/8YlpOzu3c1uNt/k2Sdbpr4zuzP3u2fO6BwpvDisW5hxKgQovHB4OIsAF3/OIs9yhQCFF46D9CSwLeQiuq79DcdvhCFH1qwY2aABOleuqqrwn0/C9KwPy8q8BDj3Zt6+d5WWU3gx1hNOE16OnEgw00wuiNPd0CthWLdpF5au3qSjdGnfGh92aWustamkPnD0tLZ0qV6pjI711Y9rcOjYGfTp+jJavtIbW1fMQBavBKGlbZch6NvtZdSqVl6/pvDisG5hxqkQoPDC4eEsAlz8OYs8yxUCE0aP1CB69h9EICTgMALiv6X/xvX45vAhxKtSWpcshfFNHkWZwFyIvRuHe/ImAwmkIwHOvekIm0UlS4DCi7GB4TThxdJqj/nsWyz46Tft72XZvITFVnqEd/pOxGMNa6BUsUIYPvGr+8ruNfxz1KlRAe1aN9FVib4Tlx5VYhkkcB8BH2VxdUst/rj248BIbwJynzebGn9y8cFAAulN4NNPEtYCvQdQeElv9pmlvIVKbOm/aSOuxcSgoJ8fpqltRS1LlNTN59ybWUaB67WTc6/r9Ulmq5Hc9GWwnYDLCy/7j5zGS+8Mg6+PN3b++qXtLbUi5Yz5y7Br3zHMGt8b23YfxJRZi/HDzCGJOQwcMxtlldPf19s9rt+L420PK+gyqr0IeCon1PHyR+XFXkiZj4UE5OAOD/V3j4PPQmKMZk8CI0cM19kNGvyxPbNlXiSAC5GR6LByJTZeOK9pvFe9OkYp57myxcgUOPdyoDiLAOdeZ5FnuSYCXmJ2xWAzAZcXXo6ePIc2nQZrfyp7182xuaGWJJQtTqOnLcS/50Mxadh7yrFuNuw5cByDxs7BygVjErPoPngqGtapkmjxwq1GltBlHHsT4FYjexNlfpYSoLmzpaQYzxEEuNXIEVSZ54bz5/D6qpW4FhuDasHB+OyxFqiaN+8DYDj3cqw4iwDnXmeRZ7kmAtxqZGwsuLzw8sXXyzFt7hIUVKcJrf1+vLHWppF63PTvEHo1DGMGvp3oODcsPALNXuiJzcs/g082b53Dkx36YYQ62ahG5bL6NYUXh3YLM0+BABd/HBrOIsDFn7PIs1whQOGF48DeBCbu/BvDt25GnLoB16ZMWXzZ/HG1nTJLssVw7rU3feZnKQHOvZaSYjxHEaDwYoys04SX46cTzDhTCteu38SmHfvwzU9rcVcd3fdcq4YY2beTsdamkvrvvUcwaso3+Gn2sEQnuqbonXqO0ycciYPfNet3YMrsxVi9cGxiPAovDusWZpwKAS7+ODycRYCLP2eRZ7kUXjgG7Ekg4vZtvL56Jdb+ewZZPT0xumFjvF21WqpFcO61Zw8wL2sIcO61hhbjOoIAhRdjVJ0mvFRs8obFNRdLk59mDUOJogUsTmNtxP6fzMKKdVvg9f+TiyR96eKFdLkhodfQd9RMHDx6BkUKBmNUv86oWK54YhEUXqylzfj2IMDFnz0oMg9bCHDxZws1prEXAVq82Itk5s7n6PVreH75Mvx78yby+PpiUetnULtA2utMzr2Ze9w4s/Wce51Jn2ULAQovxsaBywsvBYJz45P+b6F29YSjm10xUHhxxV5x/zpx8ef+feyqLeTiz1V7JnPUi8JL5uhnR7Zy2fFj6PLbr4hVFtXV8gbjx6efQf4cfhYVybnXIkyM5AACnHsdAJVZWkWAwotVuB6I7DThZeGSdanWXKxcihYKRrVKZRL9rRhrquNSU3hxHFvmnDIBLv44OpxFgIs/Z5FnuUKAwgvHgbUEYu7exZFr1xB59w6WnziOL/7Zq7N47aGKmN6shVXZce61Chcj25EA5147wmRWNhGg8GITtsREThNejFXbtVJTeHGt/sgsteHiL7P0tOu1k4s/1+uTzFQjby85ztIDt+PuZaZms60WElh/7iz2XbmCkzfCcCIsDMfVIyQ66oHUnz3WHK9XrGRhrv9F49xrNTImsBMBzr12AslsbCZA4cVmdDqhU4UXOb55zfq/cT7kCjq/8uQDLXm7zwS0blYXT7WoZ6yVDk5N4cXBgJl9sgS4+OPAcBYBLv6cRZ7lCgEKLxwHKRH49O8d+nSi5EL+7DlQNjAQpdXjtYcq4eH8+W0CybnXJmxMZAcCnHvtAJFZGCJA4cUQPucKL6OnLcQ3i9ciX95A/PHjpPtasu/QSbzcdYR+753Xnsb7b7Yx1lIHpqbw4kC4zDpFAlz8cXA4iwAXf84iz3IpvHAMpERg+p7d6Ldpg/742dJlUCFPHpTJpYQW9SifOzd8s2a1CzzOvXbByExsIMC51wZoTGJXAhRejOF0msXLpu378E7fibr2VR8qhdkTeiO7r09ia46ePIfB4+bok4QkzJ/cD7WquaaDXQovxgYhU9tGgIs/27gxlXECXPwZZ8gcbCdAixfb2blryvkH9uP9PxJ8B45RR0J3q17DYU3l3OswtMw4DQKcezlEnE2AwouxHnCa8NJtwGSs37IXdapXwJfjeyGL2THOpibdvn0Hb340DnsOHEfzRjUxefh7xlrroNQUXhwEltmmSoCLPw4QZxHg4s9Z5FmuEKDwwnFgTuC7I4fw1m9r0kV0kUI493L8OYsA515nkWe5JgIUXoyNBacJL81e7ImQ0GuYPb436tasmGIrTJYxBfMHYe3344211kGpKbw4CCyzpfDCMeCSBLj4c8luyTSVovCSabo6zYYuPnYUHX9dhXgV09GWLqbKUHhJs1sYwUEEOPc6CCyztZgAhReLUSUb0WnCS7VmnXDnbhzW/TABBfLlSbEVZy9cRqv2ffSR0nvXzTHWWgelpvDiILDMlsILx4BLEuDizyW7JdNUisJLpunqVBu64uQJtF+1AvfUQQ3D6jXARzVrpQsYCi/pgpmFJEOAcy+HhbMJUHgx1gNOE17qPPkuIqNi8MPMIahUrkSKrdi17xhe6/4JAvxzYMvy6cZa66DUFF4cBJbZUnjhGHBJAlz8uWS3ZJpKUXhx365edOQwhmzZjDzK59/D+fKrk4cKoEZwPjykHOV6esgx4glhzZnTePGXnxGnRJcBdR5B/zp10w0KhZd0Q82CkhDg3Msh4WwCFF6M9YDThBc5sUhOLnrh6Ucx5KPXU2xFz2Ez8OufO7QvmLmT+hprrYNSU3hxEFhmS+GFY8AlCXDx55LdkmkqReHF/br68LVr+EA5x90acjHZxvkoP4AixFQLDkYBv5wY9NdGHa93rdr4uG79dAVC4SVdcbMwMwKcezkcnE2AwouxHnCa8DLnu1WYOHORrn2Hti3Q8cVW+lhpU/j3fCg+//pn/PLbFv3WsF4d0bZ1Y2OtdVBqCi8OAstsKbxwDLgkAS7+XLJbMk2lJoweqdvas/+gTNPm9GjoyRs3cCr8Bg5evYqAbNlQVh3BXDpXLuTLnsNhxUfcvo2R27Zgxt49uowS/v4Y0aAR/FX5u0NDseXCeWy/FILwW7ceqEMvtbVoiNpilN6Bwkt6E2d5JgKcezkWnE2AwouxHnCa8BIdE4u2XYZABBZTyBPojxzZfRAeEYXwm1GJ78tx019NHaD9vLhioPDiir3i/nXi4s/9+9hVW8jFn6v2TOaoF4WX5Pv5VHg45h/Yh28PHcKte3FKMMmuRZO86n+weuTP4YfgHDlQQD1CoqJwIuy6FllEbDkWFpbi4MmRNSseyp0HpXIFajFGtv1UyBOEkgEBhgacbCsasGkjQmOiE4Q0JaQMTUFIkXpuUdYwWogJCcFzZcpglBJonBE49zqDOssUApx7OQ6cTYDCi7EecJrwItW+eOkqPho6HfuPnE6xFY3rVsXo/m9pHy+uGii8uGrPuHe9uPhz7/515dZx8efKveP+daPwcn8fi4Ax78B+/HXxgqHOL6y28BRTFicmTyrRcXdx7Pp1RN65k2y+ubP5oFaBAqit/LDI/zrqf3Yl0qQVZFvRh2pbkQgpEqrmzYuZzVuiYlBQWkld4nPOvS7RDZmyEpx7M2W3u1SjKbwY6w6nCi9S9XjlGG3z3wfw14792volJvYW/LL7onSJQmhavzqqKGsXVw8UXly9h9yzflz8uWe/ZoRWcfGXEXrJfetI4QXaUmXO/n/w/dEjkO06EsQPylOly6Bd2XLw8/bW78mJP1eUdUtodDSuKsuSi5HyPAqBPj4oF6i2EgUGolRALmXBkgc+WbIkO2guRkXiuLKIOapEmOPKSuaIEk52hF5CdDKCTCUlnlTPG4wAlX94bCzCVd1km1DcvXuJeR9S6a/fitX1HfhIPXz4cM0MNVg592ao7nKrynLudavuzJCNofBirNucLrwYq75rpKbw4hr9kNlqwcVfZutx12kvF3+u0xeZsSaZWXgRPyxd165JtBaR/heLkw4VK6FtmbKJgkt6jIsDSvzZczkUe5QIs01Zr+xXry0NTQoXwbRmLVBcWdhktMC5N6P1mPvUl3Ov+/RlRm0JhRdjPUfhxRg/nZrCix0gMgurCXDxZzUyJrATAS7+7ASS2dhEILMKL7P278NHf/6umRVQvlterVgR7StUVL5XctnE0d6JYu7exW4lxOy8dElvVxIHuf7K8ia3sn4RCxx/b/U6mzcCsnrD14ItSfaun73y49xrL5LMx1oCnHutJcb49iZA4cUYUQovxvhReLEDP2ZhGwEu/mzjxlTGCXDxZ5whc7CdQGYTXq7FxKDzmtVYd/ZfDe2pUqUxo1lz5FI+VhjSnwDn3vRnzhITCHDu5UhwNgEKL8Z6gMKLMX4UXuzAj1nYRoCLP9u4MZVxAlz8GWfIHGwnkJmEl/XnzqLjr6uUf5YYfcTzxMaP4oXyFWyHx5SGCXDuNYyQGdhIgHOvjeCYzG4EKLwYQ0nhxRg/Ci924McsbCPAxZ9t3JjKOAEu/owzZA62E8gMwsvtuDgM3rwJn+/dg3iFql7BQpjX8gkU9POzHRxT2oUA5167YGQmNhDg3GsDNCaxKwEKL8ZwUngxxo/Cix34MQvbCHDxZxs3pjJOgIs/4wyZg+0EvL3Eg4gHbsf9d1KO7bmlb8oYdRKQnOojRzWnFCSOiC4ST8InDRrh/RoPp29FWVqKBDj3cnA4iwDnXmeRZ7kmAhRejI0FCi/G+FF4sQM/ZmEbAS7+bOPGVMYJcPFnnCFzsJ1ARhBeToeH41T4DX308jF1BPMJdRzzMfW4pI5ytjRUVEc8z2v5pD7qmcF1CHDudZ2+yGw14dyb2Xrc9dpL4cVYn1B4McaPwosd+DEL2whw8WcbN6YyToCLP+MMmYPtBFxVeJFTfb4+eADjdmzH5ZjoFBtYNjAQwb7ZUwVQp2BBDK3XwHZITOkwApx7HYaWGadBgHMvh4izCVB4MdYDFF6M8aPwYgd+zMI2Alz82caNqYwT4OLPOEPmYDsBVxNeotXWoJn7/sHUXTtxNTZGN0wc4ZbNFYiygblRTlmslFNiSxn1vIz6z5CxCXDuzdj9l5Frz7k3I/eee9SdwouxfqTwYowfhRc78GMWthHg4s82bkxlnAAXf8YZMgfbCbiK8BJ5+za++Gcvpu3eheu3YnWDyufOje41auLFcuXh7eVleyOZ0mUJcO512a5x+4px7nX7Lnb5BlJ4MdZFFF6M8aPwYgd+zMI2Alz82caNqYwT4OLPOEPmYDsBRwovUcp6pe+GPxEaHQ1/ZbUS4O2N3L6+8Mvqfd/rv0NCMG3PLty4dUs3pF6BgviwZi20KlHS9oYxZYYgwLk3Q3STW1aSc69bdmuGahSFF2PdReHFGD8KL3bgxyxsI8DFn23cmMo4AS7+jDNkDrYTcJTwIqcIvbpyOY7fuGFx5Z4rXQY9a9ZG1eBgi9MwYsYmwLk3Y/dfRq49596M3HvuUXcKL8b6kcKLMX4UXuzAj1nYRoCLP9u4MZVxAlz8GWfIHGwn4AjhZcGhg/joz98RGxeH6kpEaZnEciVWOc4NV9YtpkfJgABt4VIkp7/tDWHKDEmAc2+G7Da3qDTnXrfoxgzdCAovxrqPwosxfvgrJBq34+6lmkvtYN80S9lxOcEhX2qB+ZCPOQHzxR/HT+pjg3zsyyelxR8525dzSrmlxXnj+XPYefGIOjnHF/ly5EDe7Oqhnger53KaTnD27Nr5a1r5SPmuOO+kJbxY0y45iaj77+vw/dHDGvfbVapifJOm+rk1+aTW88zHNb4X9hrPWT098XDebLgX717tshcf5uO49byHgptFjb879xKuO1zx9zmtaxn+Hmbs342mhf3S6mJ+ngoBCi8Gh8eYPVfTzOG9immfYvDZwTDmkwoB8nkQjrnwQj6pf33Ix758UhJeyNm+nFPKzRLO/X+fn+acMvqxN9KM44rz14TRI3W9e/YflGz9LeEj7Tpy/Traq61Fx8LC4JslC75o/jjalCmbmKel+aQFkfm4zvfCXuO5e6XANIUX9rv79bu9xg/zSX1skI/r8ulXPSitKY+fU3hx3BigxUvGVm6Tq31GuYNAi5eE3sso/WU+1jL6HR9avDz4y+HscShOYRcdPYJLUVH6NJ1KgV7wUndGJVxTjmLFWWyo+iw0Wj1iYiBHIDcrUS3VH3Bfryx4KLcXularjtw+KVtu2ns838FNeMALWZDjgfoJ57SEF0vqcyrsjLZ0EYsXOer529bPqKOf779JYkk+zu73pIBYn9TXJPbgQ4sXx1l0cDz/RyC53x9avKTOh+PH8Xxo8WJMU6DFizF+OnXk7Tg75MIsLCVwXN2dPBV+A+II0dPDA/7q1Akxm8/t4wM/9dzfO5s6fUK9p/7LXUx3Ddxn7q496/rt4j5z1+qj/Vevou3PS3ExKhKF/XJi6bNt9LHGaQURYcJv3VaPWNxURyOHxcbqU3quKJHmG+Xz5GzEzcQsulSugg8eroVi/in7NLkaE43NFy7grwvnIRennzRsnGIVYj0uIsrjPKI9/kUU/lX/E55He5zVabyU6FLl7kjkvdfogTzSEl5Sa/fO0EtYcuyoOpFot47Wtmw5TH+sObJnzZoWLn5OApoA514OBGcR4NzrLPIs10SAPl6MjQUKL8b46dQUXuwAMZksZBG/+vRpnAi7rk3Cj6v/1pw2IVnWVUd8jmnUBDXy5XNMJZ2YKxd/ToSfyYvm4s+2AbAnNBRrzpzGilMnEBIZhadKlcITJUuhRfEStmWoUq0+fQqvr16pLTeq5s2LJUp0ET8u9gg/KQuaaXt3Y7eqtymIUPGhEmCkLNmis1mJLNsvXsSWi+dx+uZ/Qo3Er5gnD75q1RrlzESgMM9d2O81BLEeIRZVsUTcmygT1+2+uCbhpVibtsjn56f814jfGt8HrHJOh4dj56UQbA+5iB3q/57Ll+/LZ3zjR/F21dStfiyqJCNlKgKcezNVd7tUYzn3ulR3ZMrKUHgx1u0UXizgd/bCZQwYPQuHj/+LQvmDMLzPm6hWsXRiSmuFlwiP47jhuQ9hHnvgGZ8FuVEDue5VQ/b4ohbU5r8o//5/kZvaHUirMkzHyCtOnsA3hw/h3M1whKs7rXJShNxptSTIHV1ps5hcJg0RdxLykjzl7q0pPK/27Q+r3zDVu7WWlO1KcTLi4u8uInDXIwJ3EKn+R+Gu2lIgr++q17fVZ7LFICGO+hwxCIyvrO54Pwr/+HKuhD7T18XRi784xGrrh5wO7Hc5pSZEbb25rATey3oLTjSuqsclZTVyWW3FuaucF9YvVBgNChbCw/nz29znvymhZY0SR1aeOoULKu/kgo/aGtS0aDG0LlUarUqUQJCFwsnU3bsw8K+NOsvmxYrjmydaO8RyY/PFC/hMlbXi1MnE6kud5QQg8xCorA7rK14PKcFlwcGDCFEWNRImKGe1b1YpiaNeE3HBa7l+zxO+8Isvoea9Yup/cfUo+f/npfTnIV6rlEAzWD/PfU8JPXFjsO18JAZs2oBnlSAvYahyFpw0FMyhhBglwpyPiMS12Pu3RPgpq5a6qn7Sr08p1km3FtncyUyYqQhkxLk3U3WQGzfW0XOvG6Nj0+xEgMKLMZAUXizg1+H9UahfqzI6vfIkNmzdi0+mfoM1341H1ixeOnVawssNz7244fEPrnnsUoLLXsQpw+rkgnd8bnWhWQN54usg8F515FCL0uTCkuPHMG//PqxXJ1dIEBPpqkF5UVUdgflQniBUDApCZfXakdtsbnuE4bLnn/COD0See3WVWbhPmiTPR0Zg/oH9+PrAgcQFedJEspiXLUIBPtmQR/kUyK8W1uXVIr5MrkCUUg9Z0PtYuH3onDKTH7V1KxYeOZRYzLvq7mb/OnXh63tD1X8jfOLzqkX9w8qXQMY7EtQZiz+TKCICyR0tmJhEEhFNopR4ckOLKCKcxKn/dzxUPP06Ia6tIVt8fgTfa4Lg+IZqvD2SajYRHsfUFoYzuOURioD4KkrUrGprsUyXAgFHLf4iPU7gnOcidXG+CveU8CbB/15F5IqviJwop55XMCTGiMjy/eHDyhfKYfxz5YrF/Su/sY/kL4BGRYqiQeHCqKOemwcReUW4kQv9e/HxWrT5Yu8e/HnurLZEMYXc2XyUuJJg5ZJD5SlbclYrMWOf2ipkHmrly4/OVasmHlXsn9VbnUiUHQWUqGAKXdeuwQIlXkt4s1JlTGnazOL22Brx5I0bmLZ7J+ao33EJIoI/UrAg6v1foKqgfp9N4YZi0v2PdVh64rh+q3bJy+jaagMCfD1RLu4DFIlrl2Y15Lu8O0sPnLweg2/W18XfpxOc+g1VQpn+n4zwYp6pzCH1CxVCw8JFtPWjzJEMJGCUgDPmXqN1Znr3IOCoudc96LAV6UGAwosxyhRe0uB3LewmWr7SG1tXzEAWJQpIaNtlCPp2exm1qpXXr82FF7nYDFPiilizhHkowUU9TxqyxQepC4lq+m6fhChcQLjnfsR4JAgppiBigIgCudRd/2vXS2HJ/jv49tBRXE1yFy+lJpQMCIDc/Ust+CvfKIWUqXahnP7qof6rhbSkKZUr1wPJIjyO4ornJlzx2KTqe+C+z/Pcq6cuihuri+NGyBZ//+JWrFvmqoX62n/PJKYpqsp7uUIFPK5M7HOpixERWuxlHp+04uITZuS2LRDBSoJftrt4/pF9eLrWf4KMX3wpzVqEr8D4h5WglLZ/BFu+etuVuftf589r8/xtyvxd+qiBumhppC4M6qk7sbnUHWNLgy2LP7lzvVmVLxd8YnovfiCkfLkwkfKzZYtEuIdYY+3DTY9DEIHNJJykJBhaWl+JJ3e5veNzKqHLD1ni/dX/nMj6/9dZ1Xj3SGLHFI2LuOK18T7RxlOJfEF6vDVS4k60+v6cU0LLSUQq3xC3PC49UJ2s8QHKaqYx8qnxmVuJNpaIhNa0yRQ3UllZbRG+iu0mxfhv5UuiuLLMKu4fgMI5c6JEQC4U8c+Joup1UfW6iPoOpBRilWh0y+MKfOMLJjsWRcQMVVtVigX4W2wdYUubUkpjz8Wf9GGI168477lUjy21nBkAACAASURBVDlLgrkYk1OJMWlZRC1WPj3EZ8m6s//el7381uX3k6OWsyOfOmJZjl6WozpNISQyUvXlOZxUW1bMgwjEsn3mWkwspC9SCxVUvFYlSuIJZWGRVLAxpRORePmJE1ilRJiNavykFqSuEq4oEUnCcGXJ1+PhmpZgMxRHfK/c8PwHYdiLM7H7EXsvGqVzPKR+L2uq71UNNZ/9ZwVqKui2xzVMPjYFE37Pgejb3sidPQ6zWz6O5oUrW1SXEGUhNGzLBiw8nPDbLeHlKkqC25rwPTc/1UgErpu3lbXj/33WBKh5hRYtFmFmJCsJ2DL3WlkEo5NAsgTsOfcSMQnYQoDCiy3U/ktD4SUNfrv3H8fwiV9h2byE4ysl9Br+OerUqIB2rZsog/jLOH9XWbIooeW652518XfigRxlQSoL01zx1dWjkrKyKJhsqXegtt3oLUj71MXvfrXIPYD1h/Ljt39K4/CF/3yUFPKPV4vPvOj40CMo6lMGN9XWmj1XLuMftX/9gLqLe+j6Vavu5qaEIJcSZfL5eSIoZyT8cl5Cbv8ryO0XgyD/aPVfLbr9SipLhtsIvXUaUbe89ePePQ9kR1G9dery1VKYtv10onWL3DV+vnQZtK9YSZujOzrIdoXrnttw2WODtm45cdUDCzdVxa5ThXXRwTlv472mFwGfhDuyErJluYvsPncQ5J0XJXwqq0v8vKlW0xPeSkzIph4J/73is973esf5aOw4H4Gt58OU4JL20ePiE0GEEDGFb6jurKe25SCtxZ9spRBxR0QWLfYoUSCtUCL4OioUvoxKRS7jocKhyOl7//av+4UTEVCUeKKEE28RUkREkdfqf5Z4P/08q/qvX6vPs8Y/KOalVR/T52Hqu3XZY6O2sopRTjhTC2IpJpZYEiRurMf9fh2C7jVQIkxT7bTTFM/SepjHk++dMN2oLsxFbEnqP8KSPAvn9EHhAE/k9b+NfAE3kCvgGgICTqvv2A0EZFcX9df8ERoWpITXYjh/PRAhYT44cS0et+LiE7PPqRxKV8ydR1uElVEX+TKGROQx96thSV2siWOPxZ+Izec8FuOS12/KuiVhnMl3qEBcKxS510aJKRXV+7HqN/GQEmQOq9/EQxDxN8ojYZtJ0pBUjDl4MSe+U2LLIiW6yIk/EsTK5OVy5dG5SjVtGWhpECe0IqZtVn29SfX1USXmmgfZwhKshBuxSAny9dXPS6r+EMsWEVetCTKuVp05pX/Pr0THqEeUFlkuR6lTif4vtpjym9/yCTyvfK44IkR6nFI3EXbhusdONSftViLs9VSLke95oBKvcyvxWkTsm57H9NYisXSLCC+Kz1c9ge0XErZafVjjYYxo8KDTXFMBwmDCzh2YuGtnYplNS3uiTeOlKBAYgf3DntPvp3SctCN4ME8SMBFIa+4lKRJwFAF7zL2OqhvzzRwEKLwY62cKL2nw27LzAKbMWowfZg5JjDlwzGyULVUEr7d7HB7jxxvrAStSNyh3Hs2qHkHlog/e1U8um1OheRBzO/VTfW7G+OBahC/CIn1x5WYOXI/MjqsROfRze4WqxULwaKWTeKTMObU9y3knQImIUhBNcfFiDUz4Kxx/nE04PSM9Q+E84ahY+BIqFb2sL6zvxHnhyIUgHDqfDwfPOd4BcNGgMCWqhKKiElZEVLl910uJesE4dC5Y/2cwRqBsgStKsBLR6jKyZLmnvlvZcV19v+Q7Jd8teS3ft4hYyy2bjNWIqYVAmQJX0aLqcTQofwbedvgNuhmdDZdu5ESuHDEIDkh+66ijyN+MyYbwKB9lgXlPixDpFeRo5yA8rH5FayIXxNrTQ0kqZ3AVSpzBP2K3lGxVSuNVVEQ3ZWnmi/F//43eGzZYVeVHChTAxEcfVb5ZCuISNmIH+mPPsBY6j8pDllqVFyOTAAmQAAmQAAmkTKCNsmplcBwBCi9psN1z4DgGjZ2DlQvGJMbsPngqGtapoi1eHC28lFB3S99Re/07VqqkHAZmVx40DuuF7lXs1v+VK1mHjY4bUb6IiiiK+Mg6iI0ojRuRgTgXEaGcFv738FYm9yYTffHHkje7Os7Z7zqyZld3pbPvRbH857WVjLOCP0qhAB5VgksTBKLSfdXYeekSTiifBZeUv4CrypnmRbWtQJ6HqkdIdLg6dcQyZ7+pta1Y7lhUKxaOKkWuK8HlKvyyR6q7+LfVFplb+n/ScFAJIAfP5VePYBy9GKSEGWPHYWuhpWhootji53N/mwJQVl1I1dYXU0HKyfOmszew4dw5rFePjeoOP0PqBERoMfEtX+gysmW1XFiUC/eYyBKIvFkI4ZHBSpDxUwKNN0Ij4tVYjNGOX2UrWJncOVAqyAMFc0Uhf+7ryB90CnHepxIvdK8r0TQkzB/nruVSYoAfzl4JwIXrAVrsyczBJ+sdJfie0oJL0aAbmRmFTW33RoAWWhIeymITFVLNR6w/r2KPnpeuYKeyXsqqUg5R6R66L91+ZZX5wi+/6JPqUgtiKfRpkyZoU6bMfdGicBZb0EOJPv85+rWpgUxEAiRAAiRAAiRwHwEKL44dEBRe0uAbFh6BZi/0xObln8Enm7eO/WSHfhihTjaqUbmsfp2Wc13HdiFzz6wEaO6cWXve+e2mubPz+yAz18DbS86088DtuHuZGQPb7iQCnHudBJ7FgnMvB4GzCXCrkbEeoPBiAb9OPcfh4Srl0KV9a6xZvwNTZi/G6oVjE53tUnixACKj2J0AF392R8oMLSTAxZ+FoBjNIQQovDgEKzO1kADnXgtBMZrdCXDutTtSZmglAQovVgJLEp3CiwX8QkKvoe+omTh49AyKFAzGqH6dUbFc8cSUFF4sgMgodifAxZ/dkTJDCwlw8WchKEZzCAEKLw7BykwtJMC510JQjGZ3Apx77Y6UGVpJgMKLlcAovBgDllxqCi/2Z8oc0ybAxV/ajBjDMQS4+HMMV+ZqGQEKL5ZxYizHEODc6xiuzDVtApx702bEGI4lQOHFGF9avBjjp1NTeLEDRGZhNQEu/qxGxgR2IsDFn51AMhubCFB4sQkbE9mJAOdeO4FkNlYT4NxrNTImsDMBCi/GgFJ4McaPwosd+DEL2whw8WcbN6YyToCLP+MMmYPtBCi82M6OKY0T4NxrnCFzsI0A517buDGV/QhQeDHGksKLMX4UXuzAj1nYRoCLP9u4MZVxAlz8GWfIHGwnQOHFdnZMaZwA517jDJmDbQQ499rGjansR4DCizGWFF6M8aPwYgd+zMI2Alz82caNqYwT4OLPOEPmYDsBCi+2s2NK4wQ49xpnyBxsI8C51zZuTGU/AhRejLGk8GKMH1OTAAmQAAmQAAmQAAmQAAmQAAmQAAmQQIoEKLxwcJAACZAACZAACZAACZAACZAACZAACZCAgwhQeHEQWGZLAiRAAiRAAiRAAiRAAiRAAiRAAiRAAhReOAZIgARIgARIgARIgARIgARIgARIgARIwEEEKLzYCHbWwhX4atEa3I2LwxOPPYKB3V+Fl5enjbkxGQmkTuCPv3ZjwsxFuHLtBsqVKoJhvd9EyaIFdCKORY6e9CIwfd5S/LD8T2xcOlUXefbCZQwYPQuHj/+LQvmDMLzPm6hWsXR6VYflZAICd+7cxbCJX+G3DX/DL4cvPujcFs88Xl+3fNP2ffhk6jf6d7GqGndjB76NoNwBmYAKm5heBH79cwfkd+/O3TjkD86NYb06oljhfJx706sDMmE5K9ZtxbAJ8zGyb2c83qRWIoHUfu+4DsyEA8UBTZZr2smzfsK871fjr5+nITAgZ2Ipn3/9M75f9gdkTq5XqxKG9+6I7L4+XAda2Q8UXqwEJtG37TqEQePm4Ksp/RGQMwfe7TdJiS918PKzj9mQG5OQQOoEQq+E4ek3BmDmuJ6oUqEUps1dgr0Hj2PepH4cixw86UbgzLlL6DZgMiIioxOFlw7vj0L9WpXR6ZUnsWHrXn0RvOa78ciaxSvd6sWC3JvAZ3OX4sSZCxg94C39f8inc/HtjMG4rRZ/LV/ujfFD3kWtahUw+csfEXL5GiYO7ebeQNi6dCNw+eoNPff++OVQFCkYjG8Wr8XajTv12o/rwHTrhkxV0PxFv2LXP0e1mNzxpScShZebat5N6feOYzFTDRGHNvb9gVNQvnRRfLFguV7nmYSX3zbsxNQ5izF3Yl91A8QH7w+aioerlEPX158B14HWdQmFF+t46djDJ32NAurOR5f2rfXrP7fs0dYv8yf3syE3JiGBtIWXfYdPonmjmjqiWBfIBfAfP07iWOTgSTcCHXuMwYtPN9XiikzI18JuouUrvbF1xQxk8UoQWtp2GYK+3V5WF8Ll061eLMi9CTzW7iPMmdgHxYvkv6+hYomwZNVGfPlpL/2+CIKN23yAbWo8entndW8obF26ENipLoBlvbd8/ihd3vHT5/Fmj7HYtGwa59506YHMV8iRE2e1VXPnnp/ihacfTRReUvu9GzP9O16TZL6h4pAWy/gT4aVy0473CS8Hjp7Wli7VK5XR5X714xocOnYGfbq+zHWglT1B4cVKYBK9U89xeOmZpokXwqfPhqCjmozXL55sQ25MQgLWEZjz3SocVT+O4wa/w7FoHTrGtpHAsl//wvbdh9Gn20t45o2BekLevf84hqstIMvmjUzMtdfwz1GnRgW0a93ExpKYjAT+IyB3eRs91x293nkRC5esRTZvb3Tv1AZNG9TAzAW/KPEvHAPUNl9TEOHl66kDEreCkCUJGCEQGRWDJzv009amcjEiY+6ksrri3GuEKtNaQqDTR+PuE15S+70bPukrXpNYApVxLCaQVHhJmvCdvhPxWMMaKFWsENeBFlNNiEjhxUpgEr19t5F4u8NTaPRIVZ364qWrePbNQdix6gsbcmMSErCcwF879mOEugO3YNpABAfl4li0HB1j2kjgRngkXlVbihZMG6BzMAkvW3YewJRZi/HDzCGJOQ8cMxtl1d2619s9bmNpTEYC/xG4oOZWsap6/8026PxKa+w/cgpv9R6PX74ajW+XrtM+1kSUMYXmL/XC1BHvo0KZYsRIAnYhsPy3zRg8di5yKPN6n2ze2rK5aKF8nHvtQpeZpEQgqfAifjdS+r0bOXkBr0k4lOxKIDXhZcb8Zdi17xhmje+NbbsPch1oJXkKL1YCk+ide32KNq0aab8uEo6ePIe3+0ygxYsNLJnEcgLicO3zr37G52N66IUfx6Ll7BjTdgIiptSuXkE7NA0Lj0gUXvYcOI5BY+dg5YIxiZl3HzwVDetUocWL7biZ0oyAWLzUbd0V21d+rh3rSjBdkPx7/hJCQq9hSM83ElNI3O+/GEKLF44iuxAQs3vxZSBiizgPX7N+h3I8uRgrvh6Nt/tO4DrQLpSZSXIEkgovX37zS4q/dyMmf82xyGFkVwLJCS/x8fEYPW0h/j0fiknD3lOOdbOB60DrsVN4sZ4ZRk1ZgFz+fujW8TmdetXv27F45Qa9D52BBBxBQE41mjpnCWZP6H3fqR0ci46gzTzNCdR7uluiDxeZeMOUBUzuXDm1BUybTh9j8/LP9J1gCWKWP0KdbFSjcllCJAG7EBAx5cdZw1C4QF6dn/jYePX55uru7z29/UgcnUoQZ5QtX+mjfbxkzZrFLmUzk8xNQPwYHFBWVp8OfjcRRLVmnbD6208x97uVXAdm7uHh0NYnFV7EuWlKv3fjZnzHsejQ3sh8mScnvIxTvoRCr4ZhjDo90HSAgtyMa/ZCT64DrRgiFF6sgGWKunv/MfQZ8YXeS55D3YV7q9d4vRfz+Scb2ZAbk5BA6gTCI6LwnNrKJuPNdPHBschR4wwC5hYvUr74uxLP9uJoXO4GT5m9GKsXjk0UapxRR5bpXgTEmXN0zC0M7fUGDh09g7eUdalYHPj6ZNPbkMYOehu1qpbHmM++RWR0jD5SmoEE7EFg898HMGT8PH2qkZzusXXnQfQcPkP7uNp36CTXgfaAzDySJZBUeImKjk3x947XJBxE9iaQVHj5e+8RZXTwDX6aPeyB9R3XgdbRp/BiHa/E2HInZPbCFbhzNw7PtmygT/Lw8PCwMTcmI4GUCSxdvUlv6Uh6F3f9T5ORK8BPexfnWOQISg8CSYUX2erRd9RMHFQXxHLc6qh+nVGxXPH0qArLyCQE5LSiAWq72449h5WllT96v/uidq4rYdvuQxg24Stl7RKGmiK+qCOn5TeRgQTsRWCWWufJ6VnK2A85/bLrtV7NquV09px77UWZ+ZgIyMmAJ5QD57vq2sLL0xMenh5KTH5LnW5UO9XfO45FjiGjBMSfX5O2H+ps5AQj0zXHuh8mYMIXi7Bi3RZ4/f8ES4lTungh/KSsUbkOtI48hRfreDE2CZAACZAACZAACZAACZAACZAACZAACVhMgMKLxagYkQRIgARIgARIgARIgARIgARIgARIgASsI0DhxTpejE0CJEACJEACJEACJEACJEACJEACJEACFhOg8GIxKkYkARIgARIgARIgARIgARIgARIgARIgAesIUHixjhdjkwAJkAAJkAAJkAAJkAAJkAAJkAAJkIDFBCi8WIyKEUmABEiABEiABEiABEiABEiABEiABEjAOgIUXqzjxdgkQAIkQAIkQAIkQAIkQAIkQAIkQAIkYDEBCi8Wo2JEEiABEiABEiABEiABEiABEiABEiABErCOAIUX63gxNgmQAAmQAAmQAAmQAAmQAAmQAAmQAAlYTIDCi8WoGJEESIAESIAESIAESIAESIAESIAESIAErCNA4cU6XoxNAiRAAiRAAiRAAiRAAiRAAiRAAiRAAhYToPBiMSpGJAESIAESIAESIAESIAESIAESIAESIAHrCFB4sY4XY5MACZAACZAACZAACZAACZAACZAACZCAxQQovFiMihFJgARIgARIgARIgARIgARIgARIgARIwDoCFF6s48XYJEACJEACJEACJEACJEACJEACJEACJGAxAQovFqNiRBIgARIgARIgARIgARIgARIgARIgARKwjgCFF+t4MTYJkAAJkAAJkAAJkAAJkAAJkAAJkAAJWEyAwovFqBiRBEiABEiABEiABEiABEiABEiABEiABKwjQOHFOl6MTQIkQAIkQAIkQAIkQAIkQAIkQAIkQAIWE6DwYjEqRiQBEiABEshIBNZv2YtuAybrKk//5EM0qVfNpat/4dJVLFu9CY81fBjlSxfVdd2x5wg69hijny+YNgA1Kpd1aBv+PR+KoRPm4cCRM6qceLz16lPo0r51smXeuXMXPyz/E6v/2I6T/15EVHQMfLJlQ9FCwWjW6GF0eukJeHtndUo7klbYKEdX6JuUOn7D1n/Qtf8keHh4YNHMIbh89UbiuDelyZrFC7kCcqJSuRJ4qkVdNG9UC56eHg4dS2llfvDoGbz4zjDEx8dj5rieaFC7clpJ+DkJkAAJkAAJZFgCFF4ybNex4iRAAiRAAqkRyGjCy+df/4zP5i7FyL6d8Fyrhk4RLHoM+Qy/bdipL8prVi2H1s3q4fknGz2AWS6W3+03EZu279efZfHyQk6/7AiPiMS9e/H6vUaPVMXnY3ro53sPnoDkLWHqyA9QuXyJdB28RoWX5PrG2W0SgLdv38EzHQfi7IXLeOGpJhjS8w2Yj/uUID9S4yFMHv6e7jNnhsHj5mLJqo0oXiQ/ls0bBRGIGEiABEiABEjAHQlQeHHHXmWbSIAESIAE7rsAzQgWL+3eGopDx844VXh54e2hEEsEc9EkuaG085+jeP2D0fqjN15oie6dn0c2Zd0SERmNkZMXYMW6rfqzBdMGKiudMk4fjUaFl+T6xumNUhUQ0ULECy8vT6z7YSKCg3LdN+7Hf/wu6itLEhFoxCppzrcrsfnvA7rqTetXx7RRHzi1GSGh19D8pV7a6uWT/l3wzOP1nVofFk4CJEACJEACjiJA4cVRZJkvCZAACZCAUwlYa/ESe+s2vvh6OX79cwcuXb4G/5w58Ki6OO3RpZ3apuGn27Jp+z6803eifr5hyRR8u3SduvjdhOiYWFR9qDQ+/ug1FCkYnNhusUT4ZOo3+HvvES1MtGhcC2+82BJPduin48wa3wtxcfEqzwkPsFo2byTCbkQmbjVaOH0QRPCQMiOjYpItLzngclG7SG0J+mnlRpxSF9/yuljhfHi6RX10aNdCW6scOXEWz3f++IHknV5+Ah+9/cID7y9VW6IGjZ2j3//xy6F4qGzxxDjhN6OwbM1fmkOVCiURlDsg2S1T5iz//GkyZi5YrgUbL09PtGpaB/27t8ffaqvVuBnfQbZAlS5RCEOVRYeprJ9WbMCQ8fMS+0LKkbB7/zF0eP8T/dy0PSsl4UUu/Gd89TO27jqIa2E3EZwnl96S1q3jc/BX1iBi0WNJ35hvA7OEty1jKbm+NQllzRvV1BYsElIb91K3Dz6eht837dZxv50xWI2jUvp5WiyOnz6PZzsO0nE/7vEaXnymaWKV1m7ciQ8/TrBo+nrqADxcpSwk/swFv2DvgeO4qtgGqu9Qrarl8e7rz6BE0QKJad/tNwkbt/2DahVLQ8Y4AwmQAAmQAAm4IwEKL+7Yq2wTCZAACZCAVRYvcXH38OZHY7Ww4ZfDF/VrVcLh4//qLRwVyhTDd59/rLdBbN9zGG/2GKvpPt6ktop/BPmDc2srEQkiDiydM1Jv1YmJvY2nXu+vL2gllCpeSF3ch6N44fx6642Er6b0h69PNkz44gedtymPfEGBWmQ4H3I1UXiR7UcieEg97tyNe6C8lLp84JjZWPbrX/rjwgXyIotKf+bcJf1arB6mjuyuyrmCEZO+1vWKio7VYkm5UkW0AGLa9mSevwhJb3yY4HumXs1KGNyjg/Ltki/FUZec8GHOsmmDGjhx+gJib93SPkokdHypFURcKa5EosPHz+JuXBwKKNa/fvepFouMCi/hEVFo22UILirfOvnz5kb5MkW1QCQimrRJRDHpV0v6xlx4sYS3+GOxZiwlB1Y4Pdr2Q/3R2EFvq21hdfXztATHk2cu4Ok3Buq4nV95Ej3eaqe2iKXNQuKbhB4TH1O9RISTsSn9s/aHCbioxvwzbwzQ3wHZRiQinIhnZy+EahFzyewRyJc3UCc3F/E2LZuG3LlypjiO+AEJkAAJkAAJZFQCFF4yas+x3iRAAiRAAqkSSOsC1DzxirVb0XfUTP3Wd8oKoIqyAtDCyWv9EHL5euL2H3MBQUSWb6cPRo7sPpg2d4m2lpHwvRJpKitLjx9XrMfQ8fP1e/3eewUd2rbQF/WvvjcKR0+e0++bLtjDwiPQ4Jn39Xsp+XiRC9VZ43trgWPQ2NmQOpuXlxwMc4uNbm88i67qIWG22nIy6csf9XOxlBCLCQmmLTUtH62NCUO6pshXLCde6z5aW5eYgog6YulQq1p5bTUSqJy5mkJywov5e9UrlcH8Kf206NNCbT0Rix4J4wa/gycfewQLl6xVlkML9Xsmiwqjwos4BZ4wc5HOc+7EPprrqt+3o/eIz/V7qxeO046CLekbUz9aw9uasZRcR5hbmaxRYpTwl2DJuK/buituqm1hjzWsgakjumsHyZaw+Hbp7xg1ZYEWvjb9PE1bBclYaPL8h7h6PTxRyFnw028Y89m3WnBZ9c1YLUSK75+ew6arvo3VVl8ibko4dTZEfc/66+cZYUtgil8KfkACJEACJEACqRCg8MLhQQIkQAIk4JYELLkANTVcLrblolvu2K9blLCVSIJYgXz/8x9opk4amjLi/fu2zIgjU3FoKkGsNcTJqQQRLES4ECFHxBGfbN7Y+sv0xBN+zAUZa4SX3l1f0v5UJIgvGBFJzMtLrhNN1hdSh83LP9N1kSA+P+o93S1BXGpRD2MGvKXft1R4kbjRMbcwa+EK7WdELrrNQ9asWdDxxVb4QPl+kZCW8DKqX2c827KBjvt2nwn4a8d+LWhtW/G5vmgXy6NW7fvoz8cOVNYdzesatngxr69sj4pR1jayFatLr/H6I9NJO9YIL9bwNmeS1lhKrm+//OYXTJm9WG9h2/3brMQoloz7pu16IPRKWKJlj6UsxDKmcZsPICdayZiRsbP/8Cm89O5wnYVsjytTonCi6Ci+Z97p8DQaKkfLclJXcs5zRbip1qyztmiSbW2yvY2BBEiABEiABNyNAIUXd+tRtocESIAESEATsOQC1IRKrFD2KF8UKQWxbvlZnbpifrE8d1Jf1KleQSe5fiMCDZ+932JFtiTJdhKxmhDrCVMw36ZjjfAyW1m71K1ZUWcjQodcAEswt5BJWv8O749SVinH9XaPlQsStgaZgviZkS1H4vxWnOBKsEZ4Mc9LHLfu2ncM23cfwp+b9+CWEnYkmESStISXeZP6oXb18jpNnxFfYOXv2/TWrOXzR+n35IK/3lPd9PNhvTqibevGhoUXEZ0mfblIb8MSS5ukwWR9YY3wYg1va8bSA5VTb3w643vMX/SrdqgrPnJMIa1xLwJH9eadtQWKCFjSR5aykDI+Gjoda9b/nShGyklccupT2ZKFsXTuSF0NsaZ5pesInFbWLKaQ3Tcb5DSl19o9rq2izINYewln09an5NrL90iABEiABEggIxOg8JKRe491JwESIAESSJFAWheg5glNwov4nzD5yjD/PMDfD12VU9CUnLQmd3HesccYHV+2sKxemOAXRoK5bw9rhBdzPyIpiQFJYaQmBLRq31f73JDtQbJ9R4Ktwot5ueIzpe1bQyBWJKatLGkJL+Zt6ztSWQopJ7viY2bJnBE6a7mQl+0xEpITXtYvnoy8yjFuSnyTK19OX/pu2e9628x7bz6nhZ5LaluZbKWRYG/hJSlva8ZScoN82IT5WPTL+gdEtbTGvbnz4Q+7tEWX9q31SVSWsJB6mJwii/XUFmXJJQKj+AZKaq0i2+pkO5hsv/rnUILvIAliBTP9kx5oWKdyYrNavtIH5y5exivPLDMc8AAAClhJREFUPYaBH3RIrrl8jwRIgARIgAQyNAEKLxm6+1h5EiABEiCBlAikdQFqns5kZZEn0B8bl05NEao1F8um7Uu+PrLVaAZk+40EOWFo2MSv9HNHCy8mp6dJtxqJhUN9tdVILFPaPNEII/q8qetjqfAyedZP+mI7b54AfDr43Qd4ydYT2YJSo3JZ3UZHCC8izohII0EsLcTiQvNVYoSIEuZ8kyu/2Qsfaf89j9arjs8+SbAeMvfRYovwYg1va8ZScgPSFosX2dYjTqSlbAkm3zCWspA04oj6McXuyrUbmDTsPfQe/rneJiRb9GSrXnJByj1w5DQGjZujt+U1rlsVM0b3SIwq1mJiNUaLlxR/evgBCZAACZBABidA4SWDdyCrTwIkQAIkkDwBc+Fl/Mfvon7t/+6wm1J4qCc5lYNQc+e6JmezshVjsLpQlGOGH29SS5/uY83F8sIl6/RR0hL6v98erz7fXN/1b99tpD5qV4JJeDG36BDri3dfe0Z/bk15yVEQXyniM0WCeb7mzoDl9B45pUaCpcKLWIWIo1UJ4ndGjhaWLS83I6Kx6o9tGP/5D9rpqmwr6dvtZYcIL7I1TCyVJLz16lPan4zwfaXbCH1xb843OY7iEFbEA3Hy+uWnvfRJUR3VSU2mLWciKD3xWJ37rG3S6htreBvtW0t8vJjGfbway2LdJMc7/7llj2Zjbl1iKQvTGJuonBLP+W6VFruOnTqPmlXL6RO6TGHG/GVYt2mX3o5kcugsnw0eN1f7BEoqvFR9rBN9vCT3BeZ7JEACJEACbkOAwovbdCUbQgIkQAIkYE7AXHhJiYwcHb19ZcId+9fe/0RtiTipnblWKl8SYeoOvGx/kJNbvv9iCIqpY42tuViOUNtjxI+KCDcSShQtgGvKN0sR5fPFdPy0+RYb011/cUBaXh1h3Uc50717917icdK2bDWScgeMnoWf12zWdZA2iMWCHB8twdzaRV5bKrzcCI9Ep57jcOTE2RQHXaH8QfoYbrEicoTFi7TjaXVkselo7IrliuutQrWV3x05pUfC/Mn9tD+R5Mo3P/ZZxBc59lu2lMlYEGsdOSVIjrR+SYlK1vSNpbytGUvJQTY/1ejXb8fpE4QkWDLu5fjuT9WJUSZny9awkDLMTyKS16btX6Z6mtdNjmOXbWAicskR7RLEwkgsjSSIH5jWPNUoxe8RPyABEiABEnAPAhRe3KMf2QoSIAESIIEkBCy5ADUJL5JUfFJMV3fqf9uwE5fViS8B/jn0Rft7HZ/TookEay+WxRpg5OSvsU9dyOdUIs8T6mhkuegVvxgSxKmtOLeV8Mdfu7WFjDjODQ4KxMRh3RAdfcuw8CKWJ3Iyk/jbMDk7lZNn2j7VGG2fbAwPD7H7SQiWCi8SV458/mbxWvyxebcWP+SUI1+fbFrcaVK3Gjq0a4GAnDlS5JYSS0t9vEjGUu4I4XvoFMR5qwhJ7ds0S3Q8/MXYntqXSHJliQ8asdwRKxVh9Gj96uinLJP2Kksa2TIUodr31quttfWRNX1jKW9rx1LSL7icSiSnE0kwOTGW5ymNexHApN+fV33eqmnt+/rdGhamerysnOfuU0KlCIUblyUcLW0epB4LFv+GY+rodLGEyh2YEw+VLa5PuxILGVNYunqT5i1BtvlJPRlIgARIgARIwN0IUHhxtx5le0iABEiABFyagGz1eG/AFF1HObVHnLoykIAtBF54e6i2nmqqRKNpoxL81KRXMIl0pqPWbS333X6TsHHbP6hWsTQWTh9kazZMRwIkQAIkQAIuTYDCi0t3DytHAiRAAiSQUQnIEctDx8/T23r6v/8qWjSuqZvSSzkjla0wYlGzaek0fcoLAwnYQkD8pYjfFNket+6HiciXN9CWbKxOs3jlRnz86VydTny7mFuwWJPZpSvX0fzFnvpo60/6d8Ezj9e3JjnjkgAJkAAJkECGIUDhJcN0FStKAiRAAiSQkQiIDxKxSBA/KHJksfgeET8XJse6H/d4TTulZSABWwncVqdSPf3GQO2LqF3rJhja6w1bs7Io3dQ5i/GjOjVKTiCSINvmpo3sblHa5CKJeCMiTvEi+bFs3ii9bYmBBEiABEiABNyRAIUXd+xVtokESIAESMAlCIjvDDl95nflv0Xu7mfNkgXlSxdVp/20QPNGCRYwDCRghIDJp4v46lk0c4j2o+Ko8NncpZj7/Sr4Kn86ssWoT9eXkSO7j03FyRapF98Zpv3rzBzXEw2SOXXMpoyZiARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQhQeHGPfmQrSIAESIAESIAESIAESIAESIAESIAEXJAAhRcX7BRWiQRIgARIgARIgARIgARIgARIgARIwD0IUHhxj35kK0iABEiABEiABEiABEiABEiABEiABFyQAIUXF+wUVokESIAESIAESIAESIAESIAESIAESMA9CFB4cY9+ZCtIgARIgARIgARIgARIgARIgARIgARckACFFxfsFFaJBEiABEiABEiABEiABEiABEiABEjAPQj8DxKUYWqdtDZoAAAAAElFTkSuQmCC", + "text/html": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "# CUSUM Chart\n", + "obj_cusum.plot_cusum_plotly()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.0" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/package/utils.py b/src/package/utils.py new file mode 100644 index 0000000000000000000000000000000000000000..2e7a1f4d2d325c853b033680158df873b5a7a51a --- /dev/null +++ b/src/package/utils.py @@ -0,0 +1,145 @@ +""" +Utilities to handle different operations +""" + +import os +import pandas as pd +import great_tables as gt +from collections import OrderedDict +import tomli +import numpy as np + +with open(os.path.abspath("../../config/config.toml"), "rb") as file_config: + config = tomli.load(file_config) + + +def get_greattable_as_html(df: pd.DataFrame) -> gt.GT: + """ + Get the great_table as HTML from Pandas dataframe. + + Args: + df (pd.DataFrame): Dataframe to rendera as a table. + + Returns: + gt.GT: Table in HTML format. + """ + table_great_table = gt.GT(data=df) + + return table_great_table.as_raw_html() + + +def populate_summary_table_ARL0_k(summary_table_df_ARL0_k: pd.DataFrame, h) -> gt.GT: + """ + Populate ARLTheoretical.summary_table_df_ARL0_k. + + Args: + summary_table_df_ARL0_k (pd.DataFrame): Dataframe of ARL0 and its respective values of k. + h (float): Normalized threshold. + + Returns: + gt.GT: Table of ARL0 and k in HTML format. + """ + table_great_table_ARL0_k = ( + gt.GT(summary_table_df_ARL0_k) + .tab_header( + title=gt.html( + f"Reference Values for an intended ARL0 with normalized threshold, h = {h}" + ) + ) + .data_color( + palette=[ + config["color"]["blue_005"], + config["color"]["blue_020"], + config["color"]["blue_040"], + ] + ) + ) + + if config["control"]["save_figure"] == "true": + table_great_table_ARL0_k.save( + os.path.abspath( + os.path.join( + "../../", config["path_output"]["path_figure"], "table_ARL0_k.png" + ) + ), + scale=3, + window_size=(1200, 1600), + ) + print( + "Created", + os.path.abspath( + os.path.join( + "../../", config["path_output"]["path_figure"], "table_ARL0_k.png" + ) + ), + ) + + return table_great_table_ARL0_k.as_raw_html() + + +def populate_summary_table_ARL1_k( + summary_table_df_ARL1_k: pd.DataFrame, dict_ARL0_k: OrderedDict, h +) -> gt.GT: + """ + Populate Multiindex table specific for ARLTheoretical.summary_table_df_ARL1_k + + Args: + summary_table_df_ARL1_k (pd.DataFrame): Dataframe with ARL1 and k values. + dict_ARL0_k (OrderedDict): Data Dictionary with the mapping between ARL0 and k. + h (float): Normalized threshold. + + Returns: + gt.GT: Table for ARL1 and k in HTML format. + """ + list_ARL_0 = [str(ARL_0) for ARL_0 in dict_ARL0_k.keys()] + list_k = ["{:.2f}".format(k) for k in dict_ARL0_k.values()] + + format_k_ARL_0 = lambda k, ARL_0: gt.html(str(k) + "
" + "(" + str(ARL_0) + ")") + + column_label_dict = { + ARL_0: format_k_ARL_0(k, ARL_0) for ARL_0, k in zip(list_ARL_0, list_k) + } + + table_great_table_ARL1_k = ( + gt.GT(summary_table_df_ARL1_k) + .tab_header( + title=gt.html( + f"Estimate of steady state ARL (ARL1) based on the computed reference values and intended zero-state ARL (ARL0) with normalized threshold, h = {h})" + ) + ) + .tab_stubhead(label="Shift in mean") + .tab_spanner( + label=gt.html("Reference Values
(Intended ARL0)"), + columns=list_ARL_0, + ) + .cols_move_to_start(columns=["Shift in mean"]) + .cols_label(**column_label_dict) + .data_color( + palette=[ + config["color"]["blue_005"], + config["color"]["blue_020"], + config["color"]["blue_040"], + ] + ) + ) + + if config["control"]["save_figure"] == "true": + table_great_table_ARL1_k.save( + os.path.abspath( + os.path.join( + "../../", config["path_output"]["path_figure"], "table_ARL1_k.png" + ) + ), + scale=3, + window_size=(1200, 1600), + ) + print( + "Created", + os.path.abspath( + os.path.join( + "../../", config["path_output"]["path_figure"], "table_ARL1_k.png" + ) + ), + ) + + return table_great_table_ARL1_k.as_raw_html() diff --git a/tests/test.py b/tests/test.py new file mode 100644 index 0000000000000000000000000000000000000000..7a07d4bac37dac883cb54d184e8addc452282b4e --- /dev/null +++ b/tests/test.py @@ -0,0 +1,56 @@ +""" +Test the basic functionality of the package. +""" + +import os +import sys + +current_directory = os.path.dirname(__file__) +sibling_directory = os.path.join(current_directory, "..", "src") +sys.path.append(sibling_directory) + +import unittest +from package.cusum import CUSUM +from package.ARLTheoretical import get_ARL_1_h_mu1_k +import tomli +import pandas as pd + + +class TestCUSUM(unittest.TestCase): + """ + Test class for CUSUM to check functionality. + """ + + def test_cusum(self): + obj_cusum = CUSUM() + + path_file_config = os.path.abspath("../config/config.toml") + with open(os.path.abspath(path_file_config), "rb") as file_config: + obj_cusum.config = tomli.load(file_config) + + ref_value = 0.5 + normalized_threshold = 4 + pre_change_days = 60 + + obj_cusum.df_metric = pd.read_csv(os.path.abspath("../config/spec-60-60.csv")) + obj_cusum.data = obj_cusum.df_metric[obj_cusum.df_metric.columns[1]].to_numpy() + obj_cusum.set_timeline(obj_cusum.data) + + obj_cusum.change_detection( + pre_change_days=pre_change_days, + normalized_ref_value=ref_value, + normalized_threshold=normalized_threshold, + ) + + self.assertEqual( + obj_cusum.S_lo[-1], 2.31, "Cumulative (negative) sum does not match." + ) + + def test_rpy2(self): + arl_1 = get_ARL_1_h_mu1_k(h=4, k=0.2996, mu1=1.2) + + self.assertEqual(arl_1, 4.4304, "Package rpy2 is not working properly") + + +if __name__ == "__main__": + unittest.main()