diff --git a/.gitignore b/.gitignore index e8dfdac0..886048ea 100644 --- a/.gitignore +++ b/.gitignore @@ -89,4 +89,8 @@ site/ out # Sphinx +doc/html +doc/_build +doc/xml +doc/latex #_static diff --git a/.readthedocs.yml b/.readthedocs.yml index 0842047c..8fd5f15a 100644 --- a/.readthedocs.yml +++ b/.readthedocs.yml @@ -3,7 +3,7 @@ version: 2 build: os: "ubuntu-24.04" tools: - python: "miniconda3-3.12-24.9" + python: "mambaforge-22.9" conda: environment: conda/environment.yml diff --git a/README.md b/README.md index e98ac12b..64108dd4 100644 --- a/README.md +++ b/README.md @@ -2,14 +2,14 @@ --- -[![Docs](https://readthedocs.org/projects/stat_tool/badge/?version=latest)](https://stat-tool.readthedocs.io/) +[![Docs](https://readthedocs.org/projects/stat-tool/badge/?version=latest)](https://stat_tool.readthedocs.io/) [![Build Status](https://github.com/openalea/stat_tool/actions/workflows/conda-package-build.yml/badge.svg?branch=main)](https://github.com/openalea/stat_tool/actions/workflows/conda-package-build.yml?query=branch%3Amaster) [![License](https://img.shields.io/badge/License--CeCILL-C-blue)](https://www.cecill.info/licences/Licence_CeCILL-C_V1-en.html) [![Anaconda-Server Badge](https://anaconda.org/openalea3/stat_tool/badges/version.svg)](https://anaconda.org/openalea3/stat_tool) --- -[Read Latest Documentation](https://stat_tool.readthedocs.io/) - [Browse GitHub Code Repository](https://github.com/openalea/stat_tool/) +[Read Latest Documentation](https://stat-tool.readthedocs.io/) - [Browse GitHub Code Repository](https://github.com/openalea/stat_tool/) --- @@ -23,19 +23,6 @@ Thanks to all that ontribute making this package what it is ! -## Note for developers +## Installation -- Compile and install with - - pip install -e . - -after activation of the conda environment depicted in the online documentation. - - * Compilation options for developers such as WITH_TEST, WITH_EFENCE are defined in pyproject.toml. They can be used with - - pip install --no-build-isolation --config-settings=cmake.define.WITH_TEST=TRUE -e . - pip install --no-build-isolation --config-settings=cmake.build-type="Debug" -e . - -and also combined: - - pip install --no-build-isolation --config-settings=cmake.define.WITH_TEST=TRUE --config-settings=cmake.define.WITH_EFENCE=TRUE --config-settings=cmake.build-type="Debug" -e . +See instructions on documentation, section [Installation](./installation.md) diff --git a/TODO b/TODO new file mode 100644 index 00000000..512ce340 --- /dev/null +++ b/TODO @@ -0,0 +1,7 @@ +- [x] Fix “ContinousParametric” and “ContinousParametricProcess” classes API documentation +- [x] Move "Usage Example" from "User guide" section (user/index.rst) to "Usage" (usage.md) section +- [ ] Add docstrings to constants. Simply add "///" instead of "//" ? Find how to transfert comments from doxygen xml to breathe +- [x] Welcome page: better integrate code lines (`pip install...`). Also move section "Note for developpers" into a more appropriated section ? +- [ ] Move objects description from "tutorials.rst" into "Usage" section +- [ ] Ensure that warnings are raise is non-existing keyword arguments are used in functions (e.g. Nbiteration in place of NbIteration) +- [ ] Have wrapper documentation be transferred to python module. diff --git a/conda/environment.yml b/conda/environment.yml index c8183d73..fe410f9e 100644 --- a/conda/environment.yml +++ b/conda/environment.yml @@ -4,6 +4,7 @@ channels: - conda-forge dependencies: - scikit-build-core + - setuptools_scm - cmake - boost - matplotlib-base diff --git a/doc/Makefile b/doc/Makefile index 8b08d3a2..de3a4ffd 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -4,6 +4,7 @@ # You can set these variables from the command line. SPHINXOPTS = SPHINXBUILD = sphinx-build +DOXYGENBUILD = doxygen SPHINXATUOBUILD = sphinx-autobuild PAPER = BUILDDIR = _build @@ -49,60 +50,70 @@ help: .PHONY: clean clean: + rm -Rf xml + rm -Rf html rm -rf $(BUILDDIR)/* rm -rf generated/* rm -rf auto_gallery/ + +.PHONY: doxygen +doxygen: Doxyfile + $(DOXYGENBUILD) + @echo + @echo "Doxygen build finished. The HTML pages are in ./html." + + .PHONY: html -html: +html: doxygen $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." .PHONY: rtdhtml -rtdhtml: +rtdhtml: doxygen $(SPHINXBUILD) -T -j auto -E -W --keep-going -b html -d $(BUILDDIR)/doctrees -D language=en . $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." .PHONY: livehtml -livehtml: +livehtml: doxygen # @echo "$(SPHINXATUOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html" $(SPHINXATUOBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html .PHONY: dirhtml -dirhtml: +dirhtml: doxygen $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." .PHONY: singlehtml -singlehtml: +singlehtml: doxygen $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml @echo @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." .PHONY: html-noplot -html-noplot: +html-noplot: doxygen $(SPHINXBUILD) -D plot_gallery=0 -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html @echo @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." .PHONY: pickle -pickle: +pickle: doxygen $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle @echo @echo "Build finished; now you can process the pickle files." .PHONY: json -json: +json: doxygen $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json @echo @echo "Build finished; now you can process the JSON files." .PHONY: htmlhelp -htmlhelp: +htmlhelp: doxygen $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp @echo @echo "Build finished; now you can run HTML Help Workshop with the" \ @@ -128,7 +139,7 @@ applehelp: "bundle." .PHONY: devhelp -devhelp: +devhelp: doxygen $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp @echo @echo "Build finished." @@ -138,19 +149,19 @@ devhelp: @echo "# devhelp" .PHONY: epub -epub: +epub: doxygen $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub @echo @echo "Build finished. The epub file is in $(BUILDDIR)/epub." .PHONY: epub3 -epub3: +epub3: doxygen $(SPHINXBUILD) -b epub3 $(ALLSPHINXOPTS) $(BUILDDIR)/epub3 @echo @echo "Build finished. The epub3 file is in $(BUILDDIR)/epub3." .PHONY: latex -latex: +latex: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." @@ -158,33 +169,33 @@ latex: "(use \`make latexpdf' here to do that automatically)." .PHONY: latexpdf -latexpdf: +latexpdf: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through pdflatex..." $(MAKE) -C $(BUILDDIR)/latex all-pdf @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." .PHONY: latexpdfja -latexpdfja: +latexpdfja: doxygen $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex @echo "Running LaTeX files through platex and dvipdfmx..." $(MAKE) -C $(BUILDDIR)/latex all-pdf-ja @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." .PHONY: text -text: +text: doxygen $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text @echo @echo "Build finished. The text files are in $(BUILDDIR)/text." .PHONY: man -man: +man: doxygen $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man @echo @echo "Build finished. The manual pages are in $(BUILDDIR)/man." .PHONY: texinfo -texinfo: +texinfo: doxygen $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo." @@ -192,57 +203,57 @@ texinfo: "(use \`make info' here to do that automatically)." .PHONY: info -info: +info: doxygen $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo @echo "Running Texinfo files through makeinfo..." make -C $(BUILDDIR)/texinfo info @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo." .PHONY: gettext -gettext: +gettext: doxygen $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale @echo @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale." .PHONY: changes -changes: +changes: doxygen $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes @echo @echo "The overview file is in $(BUILDDIR)/changes." .PHONY: linkcheck -linkcheck: +linkcheck: doxygen $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck @echo @echo "Link check complete; look for any errors in the above output " \ "or in $(BUILDDIR)/linkcheck/output.txt." .PHONY: doctest -doctest: +doctest: doxygen $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest @echo "Testing of doctests in the sources finished, look at the " \ "results in $(BUILDDIR)/doctest/output.txt." .PHONY: coverage -coverage: +coverage: doxygen $(SPHINXBUILD) -b coverage $(ALLSPHINXOPTS) $(BUILDDIR)/coverage @echo "Testing of coverage in the sources finished, look at the " \ "results in $(BUILDDIR)/coverage/python.txt." .PHONY: xml -xml: +xml: doxygen $(SPHINXBUILD) -b xml $(ALLSPHINXOPTS) $(BUILDDIR)/xml @echo @echo "Build finished. The XML files are in $(BUILDDIR)/xml." .PHONY: pseudoxml -pseudoxml: +pseudoxml: doxygen $(SPHINXBUILD) -b pseudoxml $(ALLSPHINXOPTS) $(BUILDDIR)/pseudoxml @echo @echo "Build finished. The pseudo-XML files are in $(BUILDDIR)/pseudoxml." .PHONY: dummy -dummy: +dummy: $(SPHINXBUILD) -b dummy $(ALLSPHINXOPTS) $(BUILDDIR)/dummy @echo @echo "Build finished. Dummy builder generates no files." diff --git a/doc/api.rst b/doc/api.rst deleted file mode 100644 index a65b84ff..00000000 --- a/doc/api.rst +++ /dev/null @@ -1,27 +0,0 @@ -C++ Documentation -################# - -.. toctree - :maxdepth: 2 - - - .. doxygenclass:: stat_tool:: - :project: stat_tool - :members: - - .. autodoxygenindex:: - :project: stat_tool - - .. doxygennamespace:: stat_tool::Clusters - - .. doxygennamespace:: stat_tool - -.. contents:: - :local: - :depth: 2 - -.. doxygenindex:: - - - - diff --git a/doc/api/classes.rst b/doc/api/classes.rst index e65c9cd3..1e580f28 100644 --- a/doc/api/classes.rst +++ b/doc/api/classes.rst @@ -15,9 +15,9 @@ Classes :members: .. doxygenclass:: stat_tool::CompoundData :members: -.. doxygenclass:: ContinousParametric +.. doxygenclass:: stat_tool::ContinuousParametric :members: -.. doxygenclass:: ContinousParametricProcess +.. doxygenclass:: stat_tool::ContinuousParametricProcess :members: .. doxygenclass:: stat_tool::Convolution :members: diff --git a/doc/api/functions.rst b/doc/api/functions.rst deleted file mode 100644 index a84f0de5..00000000 --- a/doc/api/functions.rst +++ /dev/null @@ -1,33 +0,0 @@ -Functions -========= - -.. doxygenfunction:: cumul_computation(int nb_value, const double *pmass, double *pcumul) -.. doxygenfunction:: cumul_distance_computation(int dim, double *distance) -.. doxygenfunction:: pattern_sort(int nb_pattern, double *distance, int nb_sorted_pattern) -.. doxygenfunction:: von_mises_concentration_computation -.. doxygenfunction:: q_q_plot_computation(double min_value, double step, int nb_step, double *theoretical_cdf, int nb_value, double **empirical_cdf) -.. doxygenfunction:: q_q_plot_computation(int nb_value, double **cdf) const -.. doxygenfunction:: q_q_plot_print(const char *path, int nb_value, double **qqplot) -.. doxygenfunction:: q_q_plotable_write(SinglePlot &plot, int nb_value, double **qqplot) -.. doxygenfunction:: cumul_matching_plot_print -.. doxygenfunction:: set_seed -.. doxygenfunction:: column_width(double min_value, double max_value) -.. doxygenfunction:: column_width(int min_value, int max_value) -.. doxygenfunction:: column_width(int nb_value, const double *value, double scale) -.. doxygenfunction:: column_width(int value) -.. doxygenfunction:: plot_print(const char *path) -.. doxygenfunction:: plot_print(const char *path) const -.. doxygenfunction:: plot_print(const char *path, const FrequencyDistribution *histo = NULL) const -.. doxygenfunction:: plot_print(const char *path, const Histogram *histo1 = NULL, const FrequencyDistribution *histo2 = NULL) -.. doxygenfunction:: plot_print(const char *path, double *concentration, double scale) const -.. doxygenfunction:: plot_print(const char *path, double *cumul, double *concentration, double shift = 0.) const -.. doxygenfunction:: plot_print(const char *path, double *standard_residual = NULL) const -.. doxygenfunction:: plot_print(const char *path, int ilength = I_DEFAULT, const Curves *curves_0 = NULL, const Curves *curves_1 = NULL) const -.. doxygenfunction:: plot_print(const char *path, int nb_dist, const Distribution **dist, double *scale, int *dist_nb_value, int nb_histo, const FrequencyDistribution **histo) -.. doxygenfunction:: plot_print(const char *path, int nb_dist, const Distribution **dist, double *scale, int *dist_nb_value, int nb_histo, const FrequencyDistribution **histo) -.. doxygenfunction:: plot_print(const char *path, int nb_histo = 0, const FrequencyDistribution **histo = NULL) const -.. doxygenfunction:: plot_print(const char *prefix, const char *title, int process, FrequencyDistribution **empirical_observation = NULL, FrequencyDistribution *marginal_distribution = NULL, model_type model = HIDDEN_MARKOV) const -.. doxygenfunction:: plot_print(const char *prefix, const char *title, int process, FrequencyDistribution **empirical_observation = NULL, FrequencyDistribution *marginal_distribution = NULL, model_type model = HIDDEN_MARKOV) const -.. doxygenfunction:: plot_print(const char *prefix, const char *title, int process, Histogram **observation_histogram = NULL, FrequencyDistribution **observation_distribution = NULL, Histogram *marginal_histogram = NULL, FrequencyDistribution *marginal_distribution = NULL, int nb_value = I_DEFAULT, double **empirical_cdf = NULL, model_type model = HIDDEN_MARKOV) const -.. doxygenfunction:: log_computation(int nb_value, const double *pmass, double *plog) -.. doxygenfunction:: cumul_method diff --git a/doc/api/index.rst b/doc/api/index.rst index 722766b7..385e054f 100644 --- a/doc/api/index.rst +++ b/doc/api/index.rst @@ -2,23 +2,23 @@ API Reference ============= .. toctree:: - :maxdepth: 4 + :maxdepth: 2 + :caption: AML API: ../user/list.rst - python + +.. toctree:: + :maxdepth: 2 + :caption: Python API: + + ../user/autosum.rst .. toctree:: - :maxdepth: 4 - :hidden: + :maxdepth: 2 :caption: C++ API: classes enums constants - - - .. functions - .. doxygenindex:: - diff --git a/doc/api/python.rst b/doc/api/python.rst deleted file mode 100644 index 8fc697fb..00000000 --- a/doc/api/python.rst +++ /dev/null @@ -1,7 +0,0 @@ -Python API ----------- - -.. toctree:: - :maxdepth: 2 - - ../user/autosum.rst diff --git a/doc/conf.py b/doc/conf.py index 30e06695..d90c9bbd 100644 --- a/doc/conf.py +++ b/doc/conf.py @@ -1,5 +1,6 @@ # -*- coding: utf-8 -*- import os +import subprocess import sys from importlib.metadata import metadata @@ -56,8 +57,13 @@ ".md": "markdown", } +# C++ API breathe_projects = {"stat_tool": "xml"} breathe_default_project = "stat_tool" +# Run doxygen when building on readthedocs +read_the_docs_build = os.environ.get("READTHEDOCS", None) == "True" +if read_the_docs_build: + subprocess.call("doxygen", shell=True) # The master toctree document. master_doc = "index" @@ -89,6 +95,7 @@ # documentation. html_theme_options = { "header_links_before_dropdown": 6, + "show_toc_level": 2, "sidebarwidth": 200, "collapse_navigation": "false", "icon_links": [ @@ -162,5 +169,5 @@ # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = {"python": ("https://docs.python.org/", None)} -breathe_projects = {'stat_tool': 'xml'} -breathe_default_project = 'stat_tool' +breathe_projects = {"stat_tool": "xml"} +breathe_default_project = "stat_tool" diff --git a/doc/contents.rst b/doc/contents.rst deleted file mode 100644 index f8398e3f..00000000 --- a/doc/contents.rst +++ /dev/null @@ -1,62 +0,0 @@ -.. Do not edit. -.. File automatically generated by sphinx_tools.py, revision 1695, on Thu Jun 25 12:14:22 2009 - -.. _stat_tool: - - -VPlants Stat_tool documentation -############################### - -Module description -================== - -.. sidebar:: Summary - - :Version: |version| - :Release: |release| - :Date: |today| - :Author: See `Authors`_ section - :ChangeLog: See `ChangeLog`_ section - -.. topic:: Overview - - .. include:: user/overview.txt - -Documentation -============= - -.. toctree:: - :maxdepth: 2 - :numbered: - - User Guide - Reference Guide - Administration - -- A `PDF <../latex/main.pdf>`_ version of |stat_tool| documentation is - available. - -.. seealso:: - - More documentation can be found on the - `openalea `__ wiki. - -Authors -======= - -.. include:: ../AUTHORS.txt - -ChangeLog -========= - -.. include:: ../ChangeLog.txt - -License -======= - -|stat_tool| is released under a Cecill-C License. - -.. note:: `Cecill-C `_ - license is a LGPL compatible license. - -.. |stat_tool| replace:: VPlants.Stat_tool diff --git a/doc/extra.md b/doc/extra.md index 91e6c8a7..1c812c61 100644 --- a/doc/extra.md +++ b/doc/extra.md @@ -1,22 +1,24 @@ # Additional resources for stat_tool +```{contents} Table of Contents +:depth: 1 +:backlinks: +``` + ```{include} ../CONTRIBUTING.md ``` ```{include} ../AUTHORS.md - :start-after: - :end-before + ``` ## License ```{include} ../LICENSE - :start-after: - :end-before + ``` ```{include} ../CHANGELOG.md - :start-after: - :end-before + ``` diff --git a/doc/installation.md b/doc/installation.md index 1021a2de..ea12ff2b 100644 --- a/doc/installation.md +++ b/doc/installation.md @@ -38,8 +38,18 @@ mamba activate stat_tool # Clone stat_tool and install git clone https://github.com/openalea/stat_tool.git cd stat_tool -pip install . - +pip install --no-build-isolation -e . # (Optional) Test your installation cd test; pytest ``` + +Compilation options for developers such as WITH_TEST, WITH_EFENCE are defined in pyproject.toml. They can be used with + +```bash +pip install --no-build-isolation --config-settings=cmake.define.WITH_TEST=TRUE -e . +pip install --no-build-isolation --config-settings=cmake.build-type="Debug" -e . +``` +and also combined: +```bash +pip install --no-build-isolation --config-settings=cmake.define.WITH_TEST=TRUE --config-settings=cmake.define.WITH_EFENCE=TRUE --config-settings=cmake.build-type="Debug" -e . +``` diff --git a/doc/usage.md b/doc/usage.md index 8c97d444..2d983629 100644 --- a/doc/usage.md +++ b/doc/usage.md @@ -1,6 +1,15 @@ # Usage +```{toctree} +:maxdepth: 1 +:caption: Basic usage examples + +Convolution +Histogram +Plotting +Vectors +``` ```{nbgallery} examples/clustering.ipynb - +``` diff --git a/doc/user/admin.rst b/doc/user/admin.rst index ef7c752e..5b71392f 100644 --- a/doc/user/admin.rst +++ b/doc/user/admin.rst @@ -5,7 +5,7 @@ Current Developments .. topic:: This page is not part of the documentation - This is a wokrsheet to gather various information about current of future development. + This is a worksheet to gather various information about current of future development. .. contents:: diff --git a/doc/user/index.rst b/doc/user/index.rst index 2e5f1741..15d7077d 100644 --- a/doc/user/index.rst +++ b/doc/user/index.rst @@ -22,7 +22,6 @@ From original AML documentation description.rst syntax.rst syntax2.rst - list.rst tutorials and examples ======================= @@ -30,9 +29,7 @@ tutorials and examples .. toctree:: :maxdepth: 1 - tutorial.rst gnuplot_versus_matplotlib.rst - plotting.rst aml2py.rst troubleshooting.rst diff --git a/doc/user/plotting.rst b/doc/user/plotting.rst deleted file mode 100644 index 6abb74ee..00000000 --- a/doc/user/plotting.rst +++ /dev/null @@ -1,10 +0,0 @@ -Usage Example -============= - -This is a simple example to illustrate the usage of plotting - - - - -.. plot:: pyplots/example1.py - :include-source: diff --git a/doc/user/tutorial.rst b/doc/user/tutorial.rst index 4a9141e2..867b9b4d 100644 --- a/doc/user/tutorial.rst +++ b/doc/user/tutorial.rst @@ -41,13 +41,13 @@ be sufficient to allow you to declare and manipulate other objects such as :func:`~openalea.stat_tool.vectors.VectorDistance`. -.. include:: histogram.rst -.. include:: convolution.rst -.. include:: vectors.rst +.. .. include:: histogram.rst +.. .. include:: convolution.rst +.. .. include:: vectors.rst .. just to prevent annoying warnings -.. only:: html +.. .. only:: html .. toctree:: :hidden: diff --git a/pyproject.toml b/pyproject.toml index 54752332..8ca35f19 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -82,14 +82,14 @@ doc = [ "sphinx-copybutton", "ipython_genutils", "nbsphinx", + "ninja", "breathe", - "doxygen" ] # section specific to conda-only distributed package (not used by pip yet) [tool.conda.environment] channels = ["openalea3", "conda-forge"] -dependencies = ["boost", "matplotlib-base"] +dependencies = ["boost", "matplotlib-base", "doxygen"] [project.urls] Repository = "https://github.com/openalea/stat_tool" diff --git a/src/cpp/stat_tool/reestimation.hpp b/src/cpp/stat_tool/reestimation.hpp index 71bbbe33..b054b178 100644 --- a/src/cpp/stat_tool/reestimation.hpp +++ b/src/cpp/stat_tool/reestimation.hpp @@ -1325,7 +1325,7 @@ double Reestimation::negative_binomial_estimation(DiscreteParametric *dist int i, j; int max_inf_bound , inf_bound, swap; double diff , shift_mean , parameter , probability , likelihood , max_likelihood = D_INF; - double max_param; double min_param = DOUBLE_ERROR; + double max_param; double min_param = DOUBLE_ERROR, cparam; double dmin_param, dmax_param, left_l, right_l; DiscreteParametric *dist_cpl = NULL, *dist_cpr = NULL; bool moment_estimation_failure = false; @@ -1422,12 +1422,13 @@ double Reestimation::negative_binomial_estimation(DiscreteParametric *dist left_l = this->likelihood_computation(*dist_cpl); right_l = this->likelihood_computation(*dist_cpr); for (j=0; j < BISECTION_NB_ITER; j++) { + cparam = (dist_cpl->parameter + dist_cpr->parameter) / 2; // current candidate if (left_l < right_l) { - dist_cpl->parameter = (dist_cpl->parameter + dist->parameter) / 2; + dist_cpl->parameter = cparam; dist_cpl->computation(); left_l = this->likelihood_computation(*dist_cpl); } else { - dist_cpr->parameter = (dist_cpl->parameter + dist_cpr->parameter) / 2; + dist_cpr->parameter = cparam; dist_cpr->computation(); right_l = this->likelihood_computation(*dist_cpr); } diff --git a/src/cpp/stat_tool/stat_tools.h b/src/cpp/stat_tool/stat_tools.h index 16db7c88..549ea932 100644 --- a/src/cpp/stat_tool/stat_tools.h +++ b/src/cpp/stat_tool/stat_tools.h @@ -67,7 +67,7 @@ namespace stat_tool { /**************************************************************** * - * Constants + * Enums */ @@ -220,105 +220,168 @@ namespace stat_tool { AUXILIARY // auxiliary variable (smoothing/piecewise linear function) }; - // Discrete parametric distributions - - const int MAX_INF_BOUND = 10000; // maximum lower bound - const int MAX_DIFF_BOUND = 10000; // maximum difference between lower and upper bounds - const double MAX_MEAN = 10000.; // maximum mean - const int MAX_SEQUENCE_LENGTH = 10000; // maximum sequence length for computing prior segment length distributions - - const double B_PROBABILITY = 0.8; // threshold for using the backward computation of the binomial probability mass function - const double B_THRESHOLD = 1000.; // threshold for using the computation in log of the binomial probability mass function - const double P_THRESHOLD = 90.; // threshold for using the computation in log of the Poisson probability mass function - const double NB_THRESHOLD = 500.; // threshold for using the computation in log of the negative binomial probability mass function - - const double SAMPLE_NB_VALUE_COEFF = 5.; // factor for deducing the number of possible values of a distribution - // from the number of possible values of a frequency distribution - const int INF_BOUND_MARGIN = 5; // range of values for the lower bound - const int SUP_BOUND_MARGIN = 3; // range of values for the upper bound - const double POISSON_RATIO = 0.7; // minimum mean/variance ratio for estimating a Poisson distribution - const double POISSON_RANGE = 0.1; // range for selecting a Poisson distribution by time scaling of - // another discrete distribution - const double NB_VALUE_COEFF = 2.; // factor for deducing the number of values of a distribution from - // the number of values of an initial distribution - - const int MIN_RANGE = 10; // minimum interval of values for applying the rejection sampling method - const double MAX_SURFACE = 3.; // maximum surface for applying the rejection sampling method - const int DIST_NB_ELEMENT = 1000000; // maximum sample size for simulation - - // Renewal process estimated on the basis of time interval data - - const int NB_COMPLETE_INTERVAL = 3; // minimum number of complete time intervals - const double RENEWAL_LIKELIHOOD_DIFF = 1.e-5; // threshold for stopping the EM iterations - const int RENEWAL_NB_ITER = 10000; // maximum number of EM iterations - const double RENEWAL_DIFFERENCE_WEIGHT = 0.5; // default penalty weight (1st- or 2nd-order difference cases) - const double RENEWAL_ENTROPY_WEIGHT = 0.05; // default penalty weight (entropy case) - const double MAX_VALUE_COEFF = 10.; // coefficient for deducing the maximum value of an inter-event distribution - - // Continuous parametric distributions - - const double CONTINUOUS_POSITIVE_INF_BOUND = 1.e-12; // inf bound of positive continuous distribution support (bug boost C++) - - const double GAMMA_TAIL = 1.e-3; // gamma distribution tail - const int GAMMA_NB_STEP = 1000; // number of steps for computing a discretized gamma distribution - const int GAMMA_NB_SUB_STEP = 10; // number of sub-steps for computing a discretized gamma distribution -// const int GAMMA_MIN_MEAN = 0.1; // minimum mean of the gamma distribution - const double GAMMA_INVERSE_SAMPLE_SIZE_FACTOR = 5.; // factor for the gamma distribution corrected moment estimator - const double GAMMA_MIN_SHAPE_PARAMETER = 0.1; // minimum shape parameter (gamma distribution) - const double GAMMA_DEFAULT_SCALE_PARAMETER = 1; // default scale parameter (gamma distribution) - const double GAMMA_ZERO_FREQUENCY_THRESHOLD = 0.999; // threshold on the zero relative frequency (gamma distribution estimation) - const double GAMMA_SHAPE_PARAMETER_THRESHOLD = 3.; // threshold on the shape parameter (gamma distribution estimation) - const double GAMMA_FREQUENCY_THRESHOLD = 100.; // threshold on the frequency (gamma distribution estimation) - const double GAMMA_ITERATION_FACTOR = 0.5; // factor (gamma distribution estimation) - const int GAMMA_MAX_NB_ITERATION = 5; // maximum number of iterations (gamma distribution estimation) -// const double GAMMA_VARIATION_COEFF_THRESHOLD = 1.e-2; threshold on le coefficient de variation (gamma distribution estimation) - - const double INVERSE_GAUSSIAN_TAIL = 1.e-3; // inverse Gaussian distribution tail - const int INVERSE_GAUSSIAN_NB_STEP = 1000; // number of steps for computing a discretized inverse Gaussian distribution - const int INVERSE_GAUSSIAN_NB_SUB_STEP = 10; // number of steps for computing a discretized inverse Gaussian distribution - - const double GAUSSIAN_TAIL = 5.e-4; // Gaussian distribution tail - const int GAUSSIAN_NB_STEP = 1000; // number of steps for computing a discretized Gaussian distribution - const int GAUSSIAN_NB_SUB_STEP = 10; // number of steps for computing a discretized Gaussian distribution - const double GAUSSIAN_MIN_VARIATION_COEFF = 1.e-3; // minimum coefficient of variation (Gaussian distribution estimation) - - const int VON_MISES_NB_STEP = 3600; // number of steps for computing a discretized von Mises distribution - const int VON_MISES_NB_SUB_STEP = 10; // number of steps for computing a discretized von Mises distribution -// const double VON_MISES_CONCENTRATION_THRESHOLD = 10.; threshold on the concentration parameter for applying -// the Gaussian approximation for computing a von Mises distribution - - const int CHI2_FREQUENCY = 2; // minimum theoretical sample size for a Chi2 goodness of fit test - - const int MARGINAL_DISTRIBUTION_MAX_VALUE = 25000; // maximum value for the building of a marginal frequency distribution - const int HISTOGRAM_FREQUENCY = 10; // average frequency for defining the bin width of an histogram - const double SKEWNESS_ROUNDNESS = 1.e-2; // rounding on the coefficient of skewness - - const int NB_ERROR = 10; // maximum number of recorded errors - - const int LINE_NB_CHARACTER = 100; // number of characters per line for sequences - - const int ASCII_NB_VALUE = 15; // maximum number of values (ASCII display) - const int ASCII_SPACE = 2; // number of empty spaces between 2 columns (ASCII display) - const double ASCII_ROUNDNESS = 1.e-5; // rounding on the cumulative distribution function - // for bounding a distribution (ASCII display) - const double SPREADSHEET_ROUNDNESS = 1.e-7; // rounding on the cumulative distribution function - // for bounding a distribution (spreadsheet output) - const int DISPLAY_NB_INDIVIDUAL = 50; // maximum number of displayed individuals - - const int PLOT_NB_DISTRIBUTION = 15; // maximum number of plotted distributions - const int PLOT_NB_HISTOGRAM = 15; // maximum number of plotted histograms - const double PLOT_ROUNDNESS = 1.e-5; // rounding on the cumulative distribution function - // for bounding a plotted distribution - const double PLOT_SHIFT = 0.2; // shift between 2 plotted frequency distributions - const double PLOT_MAX_SHIFT = 0.5; // maximum shift between the first and last plotted frequency distributions - const int TIC_THRESHOLD = 10; // minimum number of plotted graduations - const double PLOT_MASS_THRESHOLD = 1.e-3; // minimum value for plotting a zero mass after the last possible value - const double YSCALE = 1.1; // scale factor for y axis in plots - const double PLOT_RANGE_RATIO = 4.; // threshold for plotting from 0 - - // random generator - //STAT_TOOL_API std::mt19937 mt; - //STAT_TOOL_API std::uniform_real_distribution rand_unif; + +/**************************************************************** + * + * Constants + */ + + +// Constants for Discrete parametric distributions + +/// maximum lower bound +const int MAX_INF_BOUND = 10000; +/// maximum difference between lower and upper bounds +const int MAX_DIFF_BOUND = 10000; +/// maximum mean +const double MAX_MEAN = 10000.; +/// maximum sequence length for computing prior segment length distributions +const int MAX_SEQUENCE_LENGTH = 10000; +/// threshold for using the backward computation of the binomial probability mass function +const double B_PROBABILITY = 0.8; +// threshold for using the computation in log of the binomial probability mass function +const double B_THRESHOLD = 1000.; +/// threshold for using the computation in log of the Poisson probability mass function +const double P_THRESHOLD = 90.; +/// threshold for using the computation in log of the negative binomial probability mass function +const double NB_THRESHOLD = 500.; + +/// factor for deducing the number of possible values of a distribution from the number of possible values of a frequency distribution +const double SAMPLE_NB_VALUE_COEFF = 5.; + +/// range of values for the lower bound +const int INF_BOUND_MARGIN = 5; +/// range of values for the upper bound +const int SUP_BOUND_MARGIN = 3; +/// minimum mean/variance ratio for estimating a Poisson distribution +const double POISSON_RATIO = 0.7; +/// range for selecting a Poisson distribution by time scaling of another discrete distribution +const double POISSON_RANGE = 0.1; + +/// factor for deducing the number of values of a distribution from the number of values of an initial distribution +const double NB_VALUE_COEFF = 2.; + +/// minimum interval of values for applying the rejection sampling method +const int MIN_RANGE = 10; +/// maximum surface for applying the rejection sampling method +const double MAX_SURFACE = 3.; +/// maximum sample size for simulation +const int DIST_NB_ELEMENT = 1000000; + +// Renewal process estimated on the basis of time interval data +/// minimum number of complete time intervals +const int NB_COMPLETE_INTERVAL = 3; +/// threshold for stopping the EM iterations +const double RENEWAL_LIKELIHOOD_DIFF = 1.e-5; +/// maximum number of EM iterations +const int RENEWAL_NB_ITER = 10000; +/// default penalty weight (1st- or 2nd-order difference cases) +const double RENEWAL_DIFFERENCE_WEIGHT = 0.5; +/// default penalty weight (entropy case) +const double RENEWAL_ENTROPY_WEIGHT = 0.05; +/// coefficient for deducing the maximum value of an inter-event distribution +const double MAX_VALUE_COEFF = 10.; + +// Continuous parametric distributions + +/// inf bound of positive continuous distribution support (bug boost C++) +const double CONTINUOUS_POSITIVE_INF_BOUND = 1.e-12; + + /// gamma distribution tail +const double GAMMA_TAIL = 1.e-3; +/// number of steps for computing a discretized gamma distribution +const int GAMMA_NB_STEP = 1000; +/// number of sub-steps for computing a discretized gamma distribution +const int GAMMA_NB_SUB_STEP = 10; +/// factor for the gamma distribution corrected moment estimator +const double GAMMA_INVERSE_SAMPLE_SIZE_FACTOR = 5.; +/// minimum shape parameter (gamma distribution) +const double GAMMA_MIN_SHAPE_PARAMETER = 0.1; +/// default scale parameter (gamma distribution) +const double GAMMA_DEFAULT_SCALE_PARAMETER = 1; +/// threshold on the zero relative frequency (gamma distribution estimation) +const double GAMMA_ZERO_FREQUENCY_THRESHOLD = 0.999; +/// threshold on the shape parameter (gamma distribution estimation) +const double GAMMA_SHAPE_PARAMETER_THRESHOLD = 3.; +/// threshold on the frequency (gamma distribution estimation) +const double GAMMA_FREQUENCY_THRESHOLD = 100.; +/// factor (gamma distribution estimation) +const double GAMMA_ITERATION_FACTOR = 0.5; +/// maximum number of iterations (gamma distribution estimation) +const int GAMMA_MAX_NB_ITERATION = 5; + +/// inverse Gaussian distribution tail +const double INVERSE_GAUSSIAN_TAIL = 1.e-3; +/// number of steps for computing a discretized inverse Gaussian distribution +const int INVERSE_GAUSSIAN_NB_STEP = 1000; +/// number of steps for computing a discretized inverse Gaussian distribution +const int INVERSE_GAUSSIAN_NB_SUB_STEP = 10; + +/// Gaussian distribution tail +const double GAUSSIAN_TAIL = 5.e-4; +/// number of steps for computing a discretized Gaussian distribution +const int GAUSSIAN_NB_STEP = 1000; +/// number of steps for computing a discretized Gaussian distribution +const int GAUSSIAN_NB_SUB_STEP = 10; +/// minimum coefficient of variation (Gaussian distribution estimation) +const double GAUSSIAN_MIN_VARIATION_COEFF = 1.e-3; + +/// number of steps for computing a discretized von Mises distribution +const int VON_MISES_NB_STEP = 3600; +/// number of steps for computing a discretized von Mises distribution +const int VON_MISES_NB_SUB_STEP = 10; + +/// minimum theoretical sample size for a Chi2 goodness of fit test +const int CHI2_FREQUENCY = 2; + +/// maximum value for the building of a marginal frequency distribution +const int MARGINAL_DISTRIBUTION_MAX_VALUE = 25000; +/// average frequency for defining the bin width of an histogram +const int HISTOGRAM_FREQUENCY = 10; +/// rounding on the coefficient of skewness +const double SKEWNESS_ROUNDNESS = 1.e-2; + +/// maximum number of recorded errors +const int NB_ERROR = 10; + +/// number of characters per line for sequences +const int LINE_NB_CHARACTER = 100; + +/// maximum number of values (ASCII display) +const int ASCII_NB_VALUE = 15; +/// number of empty spaces between 2 columns (ASCII display) +const int ASCII_SPACE = 2; +/// rounding on the cumulative distribution function for bounding a distribution (ASCII display) +const double ASCII_ROUNDNESS = 1.e-5; + +/// rounding on the cumulative distribution function for bounding a distribution (spreadsheet output) +const double SPREADSHEET_ROUNDNESS = 1.e-7; + + +/// maximum number of displayed individuals +const int DISPLAY_NB_INDIVIDUAL = 50; + +/// maximum number of plotted distributions +const int PLOT_NB_DISTRIBUTION = 15; +/// maximum number of plotted histograms +const int PLOT_NB_HISTOGRAM = 15; +/// rounding on the cumulative distribution function for bounding a plotted distribution +const double PLOT_ROUNDNESS = 1.e-5; + +/// shift between 2 plotted frequency distributions +const double PLOT_SHIFT = 0.2; +/// maximum shift between the first and last plotted frequency distributions +const double PLOT_MAX_SHIFT = 0.5; +/// minimum number of plotted graduations +const int TIC_THRESHOLD = 10; +/// minimum value for plotting a zero mass after the last possible value +const double PLOT_MASS_THRESHOLD = 1.e-3; +/// scale factor for y axis in plots +const double YSCALE = 1.1; +/// threshold for plotting from 0 +const double PLOT_RANGE_RATIO = 4.; + + /**************************************************************** * * Class definition @@ -1033,11 +1096,17 @@ namespace stat_tool { double* cumul_computation() const; }; - /// @brief make visible these global variables + /// Random number generator STAT_TOOL_API extern std::mt19937 mt; + /// Uniform random number generator STAT_TOOL_API extern std::uniform_real_distribution rand_unif; + /// @brief Set seed of random generator + /// @param seed value of seed + /// @param generator generator to initialize STAT_TOOL_API void set_seed(int seed, std::mt19937 &generator); + /// @brief Set seed of random generator + /// @param seed value of seed STAT_TOOL_API void set_seed(int seed); STAT_TOOL_API int column_width(int); diff --git a/src/cpp/stat_tool/vectors.h b/src/cpp/stat_tool/vectors.h index f390ca60..906145a9 100644 --- a/src/cpp/stat_tool/vectors.h +++ b/src/cpp/stat_tool/vectors.h @@ -55,26 +55,37 @@ namespace stat_tool { * Constants */ - - const int VECTOR_NB_VARIABLE = 60; // maximum number of variables - const int DISTANCE_NB_VECTOR = 2000; // maximum number of vectors for the computation - // of a matrix of pairwise distances - const int SUP_NORM_DISTANCE_NB_VECTOR = 10; // minimum number of vectors for the computation - // of the sup norm distance - const int CONTINGENCY_NB_VALUE = 100; // maximum number of categories for the computation - // of a contingency table - const int DISPLAY_CONTINGENCY_NB_VALUE = 20; // maximum number of categories for the display of - // a contingency table - const int VARIANCE_ANALYSIS_NB_VALUE = 100; // maximum number of levels for the analysis of variance - const int DISPLAY_CONDITIONAL_NB_VALUE = 100; // maximum number of values of the display of - // the conditional distributions - const int PLOT_NB_VALUE = 30; // threshold for the writing of frequencies (Gnuplot output) - - const int NB_CATEGORY = 50; // maximum number of categories - - const int MIN_NB_ASSIGNMENT = 1; // minimum number of assignments of individuals (1st iteration of the MCEM algorithm) - const int MAX_NB_ASSIGNMENT = 10; // maximum number of assignments of individuals (MCEM algorithm) - const double NB_ASSIGNMENT_PARAMETER = 1.; // parameter for the number of assignments of individuals (MCEM algorithm) +/// maximum number of variables +const int VECTOR_NB_VARIABLE = 60; +/// maximum number of vectors for the computation of a matrix of pairwise distances +const int DISTANCE_NB_VECTOR = 2000; + +/// minimum number of vectors for the computation of the sup norm distance +const int SUP_NORM_DISTANCE_NB_VECTOR = 10; + +/// maximum number of categories for the computation of a contingency table +const int CONTINGENCY_NB_VALUE = 100; + +/// maximum number of categories for the display of a contingency table +const int DISPLAY_CONTINGENCY_NB_VALUE = 20; + +/// maximum number of levels for the analysis of variance +const int VARIANCE_ANALYSIS_NB_VALUE = 100; +/// maximum number of values of the display of the conditional distributions +const int DISPLAY_CONDITIONAL_NB_VALUE = 100; + +/// threshold for the writing of frequencies (Gnuplot output) +const int PLOT_NB_VALUE = 30; + +/// maximum number of categories +const int NB_CATEGORY = 50; + +/// minimum number of assignments of individuals (1st iteration of the MCEM algorithm) +const int MIN_NB_ASSIGNMENT = 1; +/// maximum number of assignments of individuals (MCEM algorithm) +const int MAX_NB_ASSIGNMENT = 10; +/// parameter for the number of assignments of individuals (MCEM algorithm) +const double NB_ASSIGNMENT_PARAMETER = 1.; enum vector_transformation { VECTOR_COPY , diff --git a/src/openalea/stat_tool/output.py b/src/openalea/stat_tool/output.py index b50e10a0..3393ba11 100644 --- a/src/openalea/stat_tool/output.py +++ b/src/openalea/stat_tool/output.py @@ -49,8 +49,9 @@ def add_doc(function): """a simple decorator to replace f's docstring by a new one The new one is the docstring of the function's name capitalized. - E.g: if function's name is display, then - >>> display.__doc__ = Display.__doc__ + E.g: if function's name is display, then:: + + display.__doc__ = Display.__doc__ """ name = function.__name__ @@ -144,6 +145,7 @@ def Plot(obj, *args, **kargs): In the case of Markovian models or sequences, the graphical outputs are grouped as follows: + - "SelfTransition": add outgoing server thunderbirdself-transition probability as a function of the index parameter (non-homogeneous Markov chain), - "Observation": observation distributions attached to each state of the @@ -215,11 +217,16 @@ def Plot(obj, *args, **kargs): convolution_data or compound_data * "StateProfile" only if the first mandatory argument is of type hidden_markov or hidden_semi-markov. + Title: (string) graphic title (the default: no title). + nbcol: (int) number of columns in the output figure - * Show: + + Show: (dict) + Display options + * legend_size: 10 * legend_nbcol: 2 * legend_loc: best @@ -281,54 +288,58 @@ def Save(obj, *args, **kargs): the index parameter t computed from the parameters of a hidden Markovian model for the sequence (ViewPoint="StateProfile"). - .. note:: The persistence mechanism is implemented by the Save function. + Note + ---- + + The persistence mechanism is implemented by the Save function. Parameters ---------- - obj: object of the STAT module (except objects of type vector_distance), - file_name : (string), - histo : (_FrequencyDistribution, _DiscreteMixtureData, _ConvolutionData, _CompoundData), - vec : (_Vectors), - timev : (_TimeEvents, _RenewalData), - seq : (_Sequences, _DiscreteSequences, _MarkovData, _SemiMarkovData, _Tops). - dist : (_Distribution, _Mixture, _Convolution, _Compound), - hmc : (_HiddenMarkov), - hsmc : (_HiddenSemiMarkov). + obj: object of the STAT module (except objects of type vector_distance), + file_name : (string), + histo : (_FrequencyDistribution, _DiscreteMixtureData, _ConvolutionData, _CompoundData), + vec : (_Vectors), + timev : (_TimeEvents, _RenewalData), + seq : (_Sequences, _DiscreteSequences, _MarkovData, _SemiMarkovData, _Tops). + dist : (_Distribution, _Mixture, _Convolution, _Compound), + hmc : (_HiddenMarkov), + hsmc : (_HiddenSemiMarkov). Keywords -------- - ViewPoint : (string) - point of view on the object ("Data" or "Survival" or "StateProfile"). + ViewPoint : (string) + Point of view on the object ("Data" or "Survival" or "StateProfile"). + This optional argument can be set at : - * "Data" only if the first argument is of type `_Sequences`, + + * "Data" only if the first argument is of type `_Sequences`, `_DiscreteSequences`, `_MarkovData`, `_SemiMarkovData` or `_Tops`, - * "Survival" only if the first argument is of type `_Distribution`, + * "Survival" only if the first argument is of type `_Distribution`, `_Mixture`, `_Convolution`, `_Compound`, `_FrequencyDistribution`, `_DiscreteMixtureData`, `_ConvolutionData` or `_CompoundData` - * "StateProfile" only if the first argument is of type `_HiddenMarkov or + * "StateProfile" only if the first argument is of type `_HiddenMarkov or `_HiddenSemiMarkov`. - Detail : (int) + Detail : (int) level of detail: 1 (default value) or 2. This optional argument can only be used if the optional argument ViewPoint is not set, or if the optional argument ViewPoint is set at "Data" and if the first mandatory argument is of type `_Vectors`, `_Sequences`, `_DiscreteSequences`, `_MarkovData`, `_SemiMarkovData` or `_Tops`. - Format : (string) - file format: "ASCII" (default format), "Binary" or "SpreadSheet". + file format: "ASCII" (default format), "Binary" or "SpreadSheet". These file formats cannot be specified if the optional argument ViewPoint is set at "Data". The optional argument Format can only be set at "Binary" if the optional argument ViewPoint is not set. - Format : (string) + Format : (string) format of sequences (only relevant for multivariate sequences): "Column" (default value) or "Line". This optional argument can only be used if the optional argument ViewPoint is set at "Data", and hence, if the first argument is of type `_Sequences`, `_DiscreteSequences`, `_MarkovData`, `_SemiMarkovData` or `_Tops`. If the first argument is of type `_Vectors`, use Format="Data" to actually save the data rather than their summary. - Sequence : (int) + Sequence : (int) identifier of a sequence. This optional argument can only be used if the optional argument ViewPoint is set at "StateProfile", and hence, if the first mandatory argument is of type `_HiddenMarkov` or `_HiddenSemiMarkov`. @@ -361,8 +372,8 @@ def Save(obj, *args, **kargs): Todo ---- - In the statInterface, Format is used for ViewPoint=="Data" need to be - clarified + In the statInterface, Format is used for ViewPoint=="Data" need to be + clarified """ return obj.save(*args, **kargs) diff --git a/src/openalea/stat_tool/plot.py b/src/openalea/stat_tool/plot.py index d0979a03..f53ad84a 100644 --- a/src/openalea/stat_tool/plot.py +++ b/src/openalea/stat_tool/plot.py @@ -1,5 +1,5 @@ #!/usr/bin/env python -#-*- coding: utf-8 -*- +# -*- coding: utf-8 -*- """Plot functions .. topic:: plot.py summary @@ -9,17 +9,17 @@ :Code status: mature :Documentation status: to be completed - :Authors: Thomas Cokelaer , + :Authors: Thomas Cokelaer , Samuel Dufour-Kowalski :Revision: $Id$ -.. inheritance-diagram:: openalea.stat_tool.plot +.. .. inheritance-diagram:: openalea.stat_tool.plot """ + __version__ = "$Id$" -import sys DISABLE_PLOT = False @@ -28,45 +28,45 @@ # buildbot cannot close the windwos popped up by the method/function Plot/plot # So, we test if the command "python setup.py nosetests" has been used. # Still, using nosetests executable, windows should pop up. -if ("nosetests" in sys.argv) or ("pytest" in sys.argv[0]): - DISABLE_PLOT = True - +# if ("nosetests" in sys.argv) or ("pytest" in sys.argv[0]): +# DISABLE_PLOT = True class plotter(object): - """ Abstract base class for all plotter """ + """Abstract base class for all plotter""" + def _init__(self): pass - + def plot(self, obj, title, groups=None, *args, **kargs): - """ Plot obj with title """ + """Plot obj with title""" raise NotImplementedError() class fakeplot(plotter): - def __init__(self): plotter.__init__(self) def plot(self, obj, title, groups=None, *args, **kargs): - """ Plot obj with title """ + """Plot obj with title""" return class gnuplot(plotter): - """ GNUPlot implementation """ + """GNUPlot implementation""" def __init__(self): - """ Initialize GnuPlot """ + """Initialize GnuPlot""" plotter.__init__(self) import Gnuplot + self.session = Gnuplot.Gnuplot() def plot(self, plotable, title, groups=None, *args, **kargs): """ - Plot a plotable with title - groups : list of group (int) to plot + Plot a plotable with title + groups : list of group (int) to plot """ import Gnuplot @@ -74,20 +74,20 @@ def plot(self, plotable, title, groups=None, *args, **kargs): g = self.session # Title & border - #multiset.border + # multiset.border # nb subplot _nbx = len(multiset) # For each subplot for _i, multiplot in enumerate(multiset): # Group filter - if(groups and multiplot.group not in groups): + if groups and multiplot.group not in groups: continue g.title(multiplot.title) - #yoffset = i * plotsize + # yoffset = i * plotsize - #g('set origin 0.0, %f'%(yoffset)) - #g('set size 1.0, %f'%(plotsize)) + # g('set origin 0.0, %f'%(yoffset)) + # g('set size 1.0, %f'%(plotsize)) # Labels g.xlabel(multiplot.xlabel) @@ -96,7 +96,6 @@ def plot(self, plotable, title, groups=None, *args, **kargs): # List of argument for the plot function plot_list = [] for singleplot in multiplot: - style = singleplot.style legend = singleplot.legend _color = singleplot.color @@ -109,9 +108,9 @@ def plot(self, plotable, title, groups=None, *args, **kargs): p = Gnuplot.Data(x, y) if style: - #todo: check that this option works. + # todo: check that this option works. p.set_option(with_=style) - + if legend: p.set_option(title=legend) plot_list.append(p) @@ -119,17 +118,16 @@ def plot(self, plotable, title, groups=None, *args, **kargs): # Range _xrange = multiplot.xrange _yrange = multiplot.yrange - if(_xrange.min != _xrange.max): - g('set xrange[%f:%f]'%(_xrange.min, _xrange.max)) - if(_yrange.min != _yrange.max): - g('set yrange[%f:%f]'%(_yrange.min, _yrange.max)) + if _xrange.min != _xrange.max: + g("set xrange[%f:%f]" % (_xrange.min, _xrange.max)) + if _yrange.min != _yrange.max: + g("set yrange[%f:%f]" % (_yrange.min, _yrange.max)) # Tics - if(multiplot.xtics > 0): - g('set xtics 0, %f'%(multiplot.xtics)) - if(multiplot.ytics > 0): - g('set ytics 0, %f'%(multiplot.ytics)) - + if multiplot.xtics > 0: + g("set xtics 0, %f" % (multiplot.xtics)) + if multiplot.ytics > 0: + g("set ytics 0, %f" % (multiplot.ytics)) g.plot(*plot_list) eval(input("Press Enter to continue")) @@ -146,33 +144,53 @@ class mplotlib(plotter): """ - linestyles = ('-', '--', ':', '.') - pointstyles = ('o', '^', 'x', '+', 's', 'v', '>', '<') - colors = ('g', 'r', 'y', 'b', 'k', 'm', 'c') + linestyles = ("-", "--", ":", ".") + pointstyles = ("o", "^", "x", "+", "s", "v", ">", "<") + colors = ("g", "r", "y", "b", "k", "m", "c") def __init__(self): - """ Initialize matplotlib """ + """Initialize matplotlib""" plotter.__init__(self) import matplotlib - #matplotlib.use('Qt4Agg') + + # matplotlib.use('Qt4Agg') import pylab + self.pylab = pylab self.matplotlib = matplotlib def plot(self, plotable, title, groups=None, *args, **kargs): """Plot a plotable with title - :param plotable: a plotable instance from standard stat_tool objects such as :func:`Distribution` - :param groups: list of group (int) to plot - :param Show: - :param nbcol: - :param legend_size: 10 - :param legend_nbcol: 2 - :param legend_loc: best - :param legend: True/False - + Parameters + ---------- + plotable: object of type Plotable + A plotable instance from the ``stat_tool`` object such as :func:`Distribution`. + title: str + Title of the plot + groups: list of group (int) + List of group indices to plot. + + Other Parameters + ---------------- + Show : bool, optional + If True (default), display the figure. + nbcol : int, optional + Number of columns in the figure layout. + legend_size : int, optional + Legend font size (default: 10). + legend_nbcol : int, optional + Number of columns in the legend (default: 2). + legend_loc : str, optional + Legend location (default: ``"best"``). + legend : bool, optional + Whether to display the legend. + y_maxrange_ratio : float, optional + Multiply the maximum y-range by this value (default: 1). + + Notes + ----- show=True by default will pop up the figure - y_maxrange_ratio=1 multiply max y range by this value """ show = kargs.get("Show", True) @@ -180,25 +198,24 @@ def plot(self, plotable, title, groups=None, *args, **kargs): fontsize = kargs.get("fontsize", 10) options_y_maxrange_ratio = kargs.get("y_maxrange_ratio", 1.1) line2d = {} - line2d['linewidth'] = kargs.get("linewidth", 1) + line2d["linewidth"] = kargs.get("linewidth", 1) legend_size = kargs.get("legend_size", 10) legend_nbcol = kargs.get("legend_nbcol", 1) legend_loc = kargs.get("legend_loc", "best") legend_on = kargs.get("legend", True) - #legend_size = kargs.get("legend_kwds", {}) - #Plot(seq1, ViewPoint="Data", nbcol=2, legend_kwds={'prop':{'size':9}}) + # legend_size = kargs.get("legend_kwds", {}) + # Plot(seq1, ViewPoint="Data", nbcol=2, legend_kwds={'prop':{'size':9}}) fig_id = kargs.get("FigureId", 1) pylab = self.pylab matplotlib = self.matplotlib multiset = plotable - - if len(multiset)==1: + if len(multiset) == 1: nbcol = 1 # Title & border - #if title: pylab.suptitle(title) - #multiset.border + # if title: pylab.suptitle(title) + # multiset.border # Configure figure f1 = pylab.figure(fig_id, figsize=(10, 10)) @@ -207,8 +224,8 @@ def plot(self, plotable, title, groups=None, *args, **kargs): f1.set_facecolor("w") # Count group - group_size = {} # Group size - group_index = {} # group counter + group_size = {} # Group size + group_index = {} # group counter for multiplot in multiset: g = multiplot.group try: @@ -219,7 +236,7 @@ def plot(self, plotable, title, groups=None, *args, **kargs): group_size[g] = 1 group_index[g] = 0 - f = pylab.figure(fig_id + g ) + f = pylab.figure(fig_id + g) f.set_facecolor("w") # nb subplot @@ -231,15 +248,18 @@ def plot(self, plotable, title, groups=None, *args, **kargs): for i, multiplot in enumerate(multiset): g = multiplot.group # Group filter - if(groups and g not in groups): + if groups and g not in groups: continue # Select window - pylab.figure(fig_id + g ) + pylab.figure(fig_id + g) # Select Subplot - pylab.subplot(group_size[g]%nbcol+group_size[g]//nbcol, - nbcol , group_index[g] + 1) + pylab.subplot( + group_size[g] % nbcol + group_size[g] // nbcol, + nbcol, + group_index[g] + 1, + ) group_index[g] += 1 pylab.title(multiplot.title) @@ -251,20 +271,20 @@ def plot(self, plotable, title, groups=None, *args, **kargs): legends = [] # Impulses do not show up at the boundaries of plot adjust_xrange_impulse = False - + # List of argument for the plot function for j, singleplot in enumerate(multiplot): style = singleplot.style legend = singleplot.legend color = singleplot.color - label = singleplot.label - if(not color): + label = singleplot.label + if not color: color = self.colors[j % len(self.colors)] x = [] y = [] labels = [] - for i in range(0,len(singleplot)): + for i in range(0, len(singleplot)): x.append(singleplot.get_label_x(i)) y.append(singleplot.get_label_y(i)) @@ -277,7 +297,7 @@ def plot(self, plotable, title, groups=None, *args, **kargs): labels = singleplot.get_label_text(i) matplotlib.pyplot.text(x, y, labels) pylab.hold(True) - # break # nothing else to be done in principle + # break # nothing else to be done in principle else: print("Warning. Empty data.") for i in range(0, singleplot.get_label_size()): @@ -291,66 +311,74 @@ def plot(self, plotable, title, groups=None, *args, **kargs): pass # continue to the normal plots - # Manage style pointstyle = self.pointstyles[j % len(self.pointstyles)] if "impulses" in style: l = pylab.vlines(x, 0, y, **line2d) - adjust_xrange_impulse = True + adjust_xrange_impulse = True elif "linespoints" in style: - #l = pylab.plot(x, y, '-', x, y, pointstyle) - l = pylab.plot(x, y, pointstyle + '-',**line2d) + # l = pylab.plot(x, y, '-', x, y, pointstyle) + l = pylab.plot(x, y, pointstyle + "-", **line2d) elif "points" in style: - l = pylab.plot(x, y, pointstyle,**line2d) + l = pylab.plot(x, y, pointstyle, **line2d) elif "lines" in style: - l = pylab.plot(x, y, '-', **line2d) + l = pylab.plot(x, y, "-", **line2d) elif "histeps" in style: - l = pylab.plot(x, y, linestyle='steps-mid', **line2d) + l = pylab.plot(x, y, linestyle="steps-mid", **line2d) else: - l = pylab.plot(x, y, style,**line2d) + l = pylab.plot(x, y, style, **line2d) - if(color): + if color: pylab.setp(l, color=color) - if (adjust_xrange_impulse): + if adjust_xrange_impulse: axes = pylab.gca() for child in axes.get_children(): if isinstance(child, matplotlib.spines.Spine): - child.set_color('#f5f5f5') - #child.set_color('#ffffff') + child.set_color("#f5f5f5") + # child.set_color('#ffffff') lines.append(l) legends.append(legend) # Legend try: import warnings + with warnings.catch_warnings(record=True) as w: - #Plot(seq1, Viewpoint="Data", nbcol=2, + # Plot(seq1, Viewpoint="Data", nbcol=2, # legend_kwds={'prop':{'size':9}}) kwds = {} - kwds['prop'] = {'size':legend_size} - kwds['ncol'] = legend_nbcol - kwds['loc'] = legend_loc - if legend_on is True and len(legends)<15: + kwds["prop"] = {"size": legend_size} + kwds["ncol"] = legend_nbcol + kwds["loc"] = legend_loc + if legend_on is True and len(legends) < 15: lg = pylab.legend(lines, legends, **kwds) - lg.legendPatch.set_alpha(0.1) # transparency + lg.legendPatch.set_alpha(0.1) # transparency if w: # it seems that matplotlib.collections.LineCollection appear # last in legends - new_legends = [] # permutation of legends with LineCollection at the end - index_begin_line_collection = 0 # where LineCollection objects begin + new_legends = [] # permutation of legends with LineCollection at the end + index_begin_line_collection = ( + 0 # where LineCollection objects begin + ) for li in range(len(lines)): current_legend = legends[li] - if str(lines[li].__class__) == "": + if ( + str(lines[li].__class__) + == "" + ): new_legends += [current_legend] else: - new_legends.insert(index_begin_line_collection, current_legend) + new_legends.insert( + index_begin_line_collection, current_legend + ) index_begin_line_collection += 1 pylab.legend(new_legends, **kwds) except Exception as e: import warnings - warnings.warn('legend failed:'+str(e)) + + warnings.warn("legend failed:" + str(e)) # Grid pylab.grid(bool(multiplot.grid)) @@ -359,21 +387,25 @@ def plot(self, plotable, title, groups=None, *args, **kargs): _xrange = multiplot.xrange _yrange = multiplot.yrange a = pylab.gca() - if(_xrange.min != _xrange.max): + if _xrange.min != _xrange.max: a.set_xlim([round(_xrange.min, 5), round(_xrange.max, 5)]) - if(_yrange.min != _yrange.max): - a.set_ylim([round(_yrange.min, 5), - round(_yrange.max*options_y_maxrange_ratio, 5)]) + if _yrange.min != _yrange.max: + a.set_ylim( + [ + round(_yrange.min, 5), + round(_yrange.max * options_y_maxrange_ratio, 5), + ] + ) # Tics xt = round(multiplot.xtics, 5) - if(xt > 0): + if xt > 0: xmin, xmax = pylab.xlim() pylab.xticks(pylab.arange(xmin, xmax, xt)) yt = round(multiplot.ytics, 5) - if(yt > 0): + if yt > 0: ymin, ymax = pylab.ylim() pylab.yticks(pylab.arange(ymin, ymax, yt)) @@ -382,6 +414,7 @@ def plot(self, plotable, title, groups=None, *args, **kargs): return f1 + PLOTTER = None @@ -411,7 +444,7 @@ def get_plotter(): _plotter = mplotlib() except ImportError: - #_plotter = gnuplot() + # _plotter = gnuplot() pass set_plotter(_plotter) diff --git a/test/test_compound.py b/test/test_compound.py index 11dbf714..d14e0df6 100644 --- a/test/test_compound.py +++ b/test/test_compound.py @@ -6,7 +6,7 @@ __version__ = "$Id$" -from .tools import interface, robust_path as get_shared_data +from .tools import DISABLE_PLOT, interface, robust_path as get_shared_data from openalea.stat_tool.compound import Compound from openalea.stat_tool.data_transform import ExtractDistribution diff --git a/test/test_compound_functional.py b/test/test_compound_functional.py index a35ace8b..1badf2fb 100644 --- a/test/test_compound_functional.py +++ b/test/test_compound_functional.py @@ -10,10 +10,10 @@ import numpy as np try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data diff --git a/test/test_convolution.py b/test/test_convolution.py index fd23f085..3b91f3bb 100644 --- a/test/test_convolution.py +++ b/test/test_convolution.py @@ -6,7 +6,7 @@ __version__ = "$Id$" -from .tools import interface, runTestClass +from .tools import DISABLE_PLOT, interface, runTestClass from openalea.stat_tool import Convolution, Estimate from openalea.stat_tool.data_transform import ExtractDistribution diff --git a/test/test_distance_matrix.py b/test/test_distance_matrix.py index 5eaccb86..6109ebe3 100644 --- a/test/test_distance_matrix.py +++ b/test/test_distance_matrix.py @@ -8,7 +8,7 @@ __version__ = "$Id$" from .tools import robust_path as get_shared_data -from .tools import interface +from .tools import DISABLE_PLOT, interface from openalea.stat_tool.cluster import Clustering, ToDistanceMatrix from openalea.stat_tool.comparison import Compare diff --git a/test/test_distribution.py b/test/test_distribution.py index fe6ea72c..1bb93ebc 100644 --- a/test/test_distribution.py +++ b/test/test_distribution.py @@ -3,7 +3,7 @@ __version__ = "$Id$" -from .tools import interface +from .tools import DISABLE_PLOT, interface from openalea.stat_tool._stat_tool import _DiscreteParametricModel diff --git a/test/test_histogram.py b/test/test_histogram.py index bf64e93f..13483236 100644 --- a/test/test_histogram.py +++ b/test/test_histogram.py @@ -2,10 +2,10 @@ try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data import openalea.stat_tool as stat_tool diff --git a/test/test_matrix.py b/test/test_matrix.py index 20a5d9e3..098cc8c5 100644 --- a/test/test_matrix.py +++ b/test/test_matrix.py @@ -3,10 +3,10 @@ __version__ = "$Id$" try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data from openalea.stat_tool.comparison import Compare diff --git a/test/test_mixture.py b/test/test_mixture.py index ea5c24b8..53b311b6 100644 --- a/test/test_mixture.py +++ b/test/test_mixture.py @@ -3,10 +3,10 @@ __version__ = "$Id$" try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data from openalea.stat_tool.data_transform import ExtractDistribution diff --git a/test/test_mixture_functional.py b/test/test_mixture_functional.py index b22cf98e..c4c0249b 100644 --- a/test/test_mixture_functional.py +++ b/test/test_mixture_functional.py @@ -2,10 +2,10 @@ Mixture functional test from exploratory.aml and stat_tool_test.aml files """ try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data from openalea.stat_tool.cluster import Cluster diff --git a/test/test_multivariate_mixture.py b/test/test_multivariate_mixture.py index 609430a2..4bd5dff7 100644 --- a/test/test_multivariate_mixture.py +++ b/test/test_multivariate_mixture.py @@ -6,28 +6,26 @@ """ try: - from .tools import interface + from .tools import DISABLE_PLOT, interface except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface +import os +import tempfile +from pathlib import Path -# from openalea.stat_tool.plot import DISABLE_PLOT +import pytest -from openalea.stat_tool.distribution import Binomial, Poisson +from openalea.stat_tool.distribution import Binomial, Poisson, set_seed from openalea.stat_tool.multivariate_mixture import _MultivariateMixture from openalea.stat_tool.vectors import Vectors -from openalea.stat_tool.distribution import set_seed - -import os, tempfile - -import pytest -from pathlib import Path @pytest.fixture def path(): return Path(__file__).parent + @pytest.fixture def data(): d11 = Binomial(0, 12, 0.1) @@ -38,16 +36,18 @@ def data(): d22 = Poisson(0, 5.0) d23 = Poisson(0, 0.20) - data = _MultivariateMixture( - [0.1, 0.2, 0.7], [[d11, d21], [d12, d22], [d13, d23]] - ) + data = _MultivariateMixture([0.1, 0.2, 0.7], [[d11, d21], [d12, d22], [d13, d23]]) assert data.nb_component == 3 assert data.nb_variable == 2 return data + @pytest.fixture def myi(data, path): - return interface(data, str((path / "data" / "mixture_mv1.mixt")), _MultivariateMixture) + return interface( + data, str((path / "data" / "mixture_mv1.mixt")), _MultivariateMixture + ) + @pytest.fixture def my_estimate(path): @@ -59,44 +59,55 @@ def my_estimate(path): return m, v + def test_constructor_from_file(myi): # raise error (proba non equal to 1) when nosetests used from parent directory. myi.constructor_from_file() + def test_constructor_from_file_failure(myi): myi.constructor_from_file_failure() + def test_print(myi): myi.print_data() + def test_display(myi): myi.display() myi.display_versus_ascii_write() myi.display_versus_str() + def test_len(data): c = data assert len(c) == 3 + # def test_plot(data): # data.plot(1) - # data.plot(2) +# data.plot(2) + def test_plot(myi): myi.plot() myi.plot_write() # data.plot(2) + def test_plot_write(myi): myi.plot_write() + def test_file_ascii_write(myi): myi.file_ascii_write() + def test_estimate(my_estimate): m, v = my_estimate assert m, v + def test_mixture_plots(my_estimate): m, v = my_estimate m.plot() @@ -107,23 +118,28 @@ def test_mixture_plots(my_estimate): marginal.plot() assert m, v + def test_spreadsheet_write(myi): myi.spreadsheet_write() + def test_simulate(myi): myi.simulate() + def test_extract(my_estimate): m, v = my_estimate for i in range(1, v.nb_variable + 1): m2 = v.extract(i) assert m2 + def test_extract_data(my_estimate): m, v = my_estimate d = m.extract_data() assert d + def test_simulate2(): d11 = Binomial(0, 12, 0.1) d12 = Binomial(0, 12, 0.5) @@ -156,6 +172,7 @@ def test_simulate2(): estimation_failed = False assert m_estim_nbcomp + def test_permutation(data): data1 = data @@ -165,12 +182,12 @@ def test_permutation(data): assert str(data1) == str(data2) + def test_cluster_data(my_estimate): """Clustering using the mixture model""" m, v = my_estimate clust_entropy = m.cluster_data(v, True) - with tempfile.NamedTemporaryFile(delete=False) as tmp: clust_entropy.file_ascii_write(tmp.name, False) @@ -180,6 +197,7 @@ def test_cluster_data(my_estimate): assert clust_entropy.nb_variable == m.nb_variable + 2 assert clust_plain.nb_variable == m.nb_variable + 1 + def test_cluster_data_file(my_estimate): """Clustering using the mixture model, reading data from a file""" m, v = my_estimate @@ -192,10 +210,12 @@ def test_cluster_data_file(my_estimate): assert clust_entropy.nb_variable == m.nb_variable + 2 + if __name__ == "__main__": + def path(): return Path(__file__).parent - + def data(): d11 = Binomial(0, 12, 0.1) d12 = Binomial(0, 12, 0.5) @@ -211,7 +231,7 @@ def data(): assert data.nb_component == 3 assert data.nb_variable == 2 return data - + def my_estimate(path): data_file = str((path / "data" / "cluster_vectors.vec")) v = Vectors(data_file) @@ -220,9 +240,12 @@ def my_estimate(path): m = v.mixture_estimation(3, 300, []) return m, v - - myi = interface(data, str((path() / "data" / "mixture_mv1.mixt")), _MultivariateMixture) + + myi = interface( + data, str((path() / "data" / "mixture_mv1.mixt")), _MultivariateMixture + ) myi.data = data() + print(DISABLE_PLOT) test_constructor_from_file(myi) test_constructor_from_file_failure(myi) test_print(myi) @@ -240,4 +263,5 @@ def my_estimate(path): test_simulate2() test_permutation(data()) test_cluster_data(my_estimate(path())) - test_cluster_data_file(my_estimate(path())) \ No newline at end of file + test_cluster_data_file(my_estimate(path())) + diff --git a/test/test_multivariate_mixture_functional.py b/test/test_multivariate_mixture_functional.py index 377c45cb..92fc8994 100644 --- a/test/test_multivariate_mixture_functional.py +++ b/test/test_multivariate_mixture_functional.py @@ -61,3 +61,6 @@ def test1(): clust_entropy = m_estim_nbcomp.cluster_data(v , True) clust_plain = m_estim_nbcomp.cluster_data(v , False) + +if __name__ == "__main__": + test1() \ No newline at end of file diff --git a/test/test_output.py b/test/test_output.py index c6ebeb9b..f3b406ad 100644 --- a/test/test_output.py +++ b/test/test_output.py @@ -1,8 +1,10 @@ """output tests""" -try: +try: + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data from openalea.stat_tool.convolution import Convolution @@ -42,23 +44,20 @@ def test_plot_mixture_1(self): def test_plot_mixture_2(self): m = self.get_mixture_2() - if DISABLE_PLOT == False: - m.plot() + m.plot() def test_plot_mixture_data(self): mixt1 = Mixture( 0.6, Distribution("B", 2, 18, 0.5), 0.4, Distribution("NB", 10, 10, 0.5) ) mixt_histo1 = Simulate(mixt1, 200) - - if DISABLE_PLOT == False: - mixt1.plot() - mixt_histo1.plot() + + mixt1.plot() + mixt_histo1.plot() def test_plot_convolution(self): - convol1 = Convolution("data/convolution1.conv") - if DISABLE_PLOT == False: - Plot(convol1.extract_elementary(1), convol1.extract_elementary(2)) + convol1 = Convolution("data/convolution1.conv") + Plot(convol1.extract_elementary(1), convol1.extract_elementary(2)) histo_b2 = Histogram("data/nothofagus_antarctica_bud_2.his") histo_s2 = Histogram("data/nothofagus_antarctica_shoot_2.his") @@ -71,42 +70,34 @@ def test_plot_convolution(self): Estimator="PenalizedLikelihood", Weight=0.5, ) - if DISABLE_PLOT == False: - Plot(convol31.extract_elementary(1)) + Plot(convol31.extract_elementary(1)) def test_plot_convolution_data(self): convol1 = Convolution("data/convolution1.conv") - convol_histo1 = Simulate(convol1, 200) - if DISABLE_PLOT == False: - convol_histo1.plot() + convol_histo1 = Simulate(convol1, 200) + convol_histo1.plot() def _test_plot_distribution_set(self): d1 = Distribution("B", 2, 18, 0.5) d2 = Distribution("NB", 10, 10, 0.5) d3 = Distribution("U", 10, 20) - - if DISABLE_PLOT == False: - Plot(d1, d2, d3) - d1.old_plot() + + Plot(d1, d2, d3) + d1.old_plot() def test_plot_survival(self): d1 = Distribution("B", 2, 18, 0.5) - - if DISABLE_PLOT == False: - d1.plot(ViewPoint="Survival") + d1.plot(ViewPoint="Survival") histo1 = Simulate(d1, 200) - if DISABLE_PLOT == False: - histo1.plot(ViewPoint="Survival") + histo1.plot(ViewPoint="Survival") def test_plot_parametric_model(self): dist1 = Distribution("NB", 0, 3.5, 0.3) histo1 = Simulate(dist1, 200) - if DISABLE_PLOT == False: - Plot(histo1) - dist2 = Estimate(histo1, "NB", MinInfBound=0, InfBoundStatus="Fixed") - if DISABLE_PLOT == False: - Plot(dist2) + Plot(histo1) + dist2 = Estimate(histo1, "NB", MinInfBound=0, InfBoundStatus="Fixed") + Plot(dist2) def test_output_plot_viewpoint_survival(): @@ -114,7 +105,6 @@ def test_output_plot_viewpoint_survival(): Plot(d1) Plot(d1, ViewPoint="Survival") - def test_output_display_detail(): d1 = Distribution("B", 2, 19, 0.5) print(Display(d1)) @@ -148,3 +138,20 @@ def test_output_display_viewpoint_data(): except: assert True + +if __name__ == "__main__": + T = Test() + T.test_plot_convolution() + T.test_plot_convolution_data() + T.test_plot_mixture_1() + T.test_plot_mixture_2() + T.test_plot_mixture_data() + T.test_plot_parametric_model() + T._test_plot_distribution_set() + T._test_old_plot() + T.test_plot_survival() + test_output_display_detail() + test_output_display_viewpoint_data() + test_output_display_viewpoint_survival() + test_output_plot_viewpoint_survival() + diff --git a/test/test_plot.py b/test/test_plot.py index ef08769d..fd7b3f1c 100644 --- a/test/test_plot.py +++ b/test/test_plot.py @@ -5,26 +5,19 @@ try: from .tools import robust_path as get_shared_data except ImportError: - from tools import robust_path as get_shared_data + pass import openalea from openalea.stat_tool import _stat_tool -from openalea.stat_tool.plot import DISABLE_PLOT, get_plotter, gnuplot - -from openalea.stat_tool.plot import get_plotter, gnuplot -from openalea.stat_tool.plot import DISABLE_PLOT - - +from openalea.stat_tool.plot import get_plotter, gnuplot class Test: - def test_plotable(self): p = _stat_tool.SinglePlot() p.add_point(_stat_tool.PlotPoint(1.0, 1.2)) p.add_point(_stat_tool.PlotPoint(2.0, 3.2)) - assert isinstance(p, openalea.stat_tool._stat_tool.SinglePlot) p2 = _stat_tool.MultiPlot(2) @@ -79,8 +72,8 @@ def test_plotable2(self): # test plot plotter = get_plotter() - if DISABLE_PLOT == False: - plotter.plot(p, "test_plot") + # if DISABLE_PLOT == False: + plotter.plot(p, "test_plot") def get_plotable(self): p = _stat_tool.MultiPlotSet(3) @@ -134,8 +127,8 @@ def get_plotable(self): def test_matplotlib(self): a = self.get_plotable() plotter = get_plotter() - if DISABLE_PLOT == False: - plotter.plot(a, "test_plot") + # if DISABLE_PLOT == False: + plotter.plot(a, "test_plot") def test_gnuplot(self): try: @@ -143,10 +136,9 @@ def test_gnuplot(self): except ModuleNotFoundError: pass else: - if DISABLE_PLOT: - return + # if DISABLE_PLOT: + # return a = self.get_plotable() plotter = gnuplot() - if DISABLE_PLOT == False: - plotter.plot(a, "test_plot") - + # if DISABLE_PLOT == False: + plotter.plot(a, "test_plot") diff --git a/test/test_regression.py b/test/test_regression.py index e16a7113..dfda9c74 100644 --- a/test/test_regression.py +++ b/test/test_regression.py @@ -1,10 +1,10 @@ """Regression tests""" try: - from .tools import interface + from .tools import DISABLE_PLOT, interface from .tools import robust_path as get_shared_data except ImportError: - from tools import interface + from tools import DISABLE_PLOT, interface from tools import robust_path as get_shared_data from openalea.stat_tool._stat_tool import _RegressionKernel as RegressionKernel diff --git a/test/test_vector_distance.py b/test/test_vector_distance.py index 007054db..a02177a7 100644 --- a/test/test_vector_distance.py +++ b/test/test_vector_distance.py @@ -3,7 +3,7 @@ :Author: Thomas Cokelaer, Thomas.Cokelaer@inria.fr """ -from .tools import interface, runTestClass +from .tools import DISABLE_PLOT, interface, runTestClass from openalea.stat_tool.vectors import VectorDistance diff --git a/test/test_vectors.py b/test/test_vectors.py index cb64ba8a..854b5457 100644 --- a/test/test_vectors.py +++ b/test/test_vectors.py @@ -1,7 +1,11 @@ """vectors tests""" -from .tools import interface, runTestClass -from .tools import robust_path as get_shared_data +try: + from .tools import DISABLE_PLOT, interface, runTestClass, _remove_file + from .tools import robust_path as get_shared_data +except ImportError: + from tools import DISABLE_PLOT, interface, runTestClass, _remove_file + from tools import robust_path as get_shared_data from openalea.stat_tool.enums import variance_type from openalea.stat_tool.vectors import ( @@ -138,12 +142,14 @@ def test_variance_analysis(vec10): assert vec10.variance_analysis(1, 4, 1, "whatever", variance_type["O"]) == str( va ) + _remove_file("whatever") try: va = VarianceAnalysis(vec10, 1, 4, "DUMMY") assert False except: assert True + _remove_file("result") def test_contingency_table(vec10): """test contingency table""" @@ -151,9 +157,19 @@ def test_contingency_table(vec10): assert ct and str(ct) ct2 = vec10.contingency_table(1, 4, "what", OutputFormat.ASCII) + _remove_file("what") + _remove_file("result") assert ct == ct2 + def test_rank_computation(vec10): ComputeRankCorrelation(vec10, Type="Kendall", FileName="test") # ComputeRankCorrelation(vec10, Type="Spearman", FileName="test") - + _remove_file("test") + +if __name__ == "__main__": + vec10 = Vectors(get_shared_data("chene_sessile.vec")) + test_vectors_container() + test_variance_analysis(vec10) + test_contingency_table(vec10) + test_rank_computation(vec10) \ No newline at end of file diff --git a/test/tools.py b/test/tools.py index fbd09fee..ee0b9b40 100644 --- a/test/tools.py +++ b/test/tools.py @@ -7,21 +7,26 @@ __version__ = "$Id$" import os +import sys -from openalea.stat_tool import Simulate -from openalea.stat_tool.output import Display, Save import openalea.stat_tool.plot -from openalea.stat_tool.distribution import set_seed +# !!! Do not plot in nosetests !!! +# buildbot cannot close the windwos popped up by the method/function Plot/plot +# So, we test if the command "python setup.py nosetests" has been used. +# Still, using nosetests executable, windows should pop up. +if ("nosetests" in sys.argv) or ("pytest" in sys.argv[0]): + DISABLE_PLOT = openalea.stat_tool.plot.DISABLE_PLOT = True +else: + DISABLE_PLOT = openalea.stat_tool.plot.DISABLE_PLOT = False -DISABLE_PLOT = openalea.stat_tool.plot.DISABLE_PLOT = True - +# DISABLE_PLOT = openalea.stat_tool.plot.DISABLE_PLOT = True from pathlib import Path import openalea.stat_tool as st -from openalea.stat_tool import get_shared_data - - +from openalea.stat_tool import Simulate, get_shared_data +from openalea.stat_tool.distribution import set_seed +from openalea.stat_tool.output import Display, Save def runTestClass(myclass): functions = [x for x in dir(myclass) if x.startswith("test")] @@ -48,7 +53,7 @@ class interface: :Usage: In your test file, add:: - >>> from .tools import interface + >>> from .tools import DISABLE_PLOT, interface Then, if we consider the Compound class case, create a class as follows:: diff --git a/test/what b/test/what deleted file mode 100644 index c946724f..00000000 --- a/test/what +++ /dev/null @@ -1,26 +0,0 @@ -contingency table - - 1 2 3 4 -1995 1 41 3 1 46 -1996 38 7 1 0 46 -1997 18 27 1 0 46 - 57 75 5 1 138 - -deviation table - - 1 2 3 4 -1995 -18 16 1.33333 0.666667 -1996 19 -18 -0.666667 -0.333333 -1997 -1 2 -0.666667 -0.333333 - -chi-square contribution table - - 1 2 3 4 -1995 0.270397 0.162371 0.0169137 0.0211421 -1996 0.301275 0.205501 0.00422842 0.00528553 -1997 0.000834557 0.00253705 0.00422842 0.00528553 - -chi-square test (6 degrees of freedom) -chi-square value: 63.0653 critical probability: 1.07046e-11 -reference chi-square value: 12.5916 reference critical probability: 0.05 -reference chi-square value: 16.8119 reference critical probability: 0.01 diff --git a/test/whatever b/test/whatever deleted file mode 100644 index d201ed4e..00000000 --- a/test/whatever +++ /dev/null @@ -1,22 +0,0 @@ -value 1995 1996 1997 -sample size 46 46 46 -mean 2.08696 1.19565 1.63043 -variance 0.170048 0.205314 0.282609 -standard deviation 0.412369 0.453116 0.53161 -mean absolute deviation 0.202268 0.323251 0.493384 -coefficient of concentration 0.0584239 0.137945 0.15913 -coefficient of skewness 2.64171 2.3056 -0.08945 -coefficient of kurtosis 9.96979 4.16166 -1.08981 - - frequency distribution 1995 frequency distribution 1996 frequency distribution 1997 cumulative distribution 1995 function cumulative distribution 1996 function cumulative distribution 1997 function -0 0 0 0 0 0 0 -1 1 38 18 0.0217391 0.826087 0.391304 -2 41 7 27 0.913043 0.978261 0.978261 -3 3 1 1 0.978261 1 1 -4 1 1 - -Kruskal-Wallis test -chi-square test 2 degrees of freedom -chi-square value 58.1932 critical probability 2.30942e-13 -reference chi-square value 5.99146 reference critical probability 0.05 -reference chi-square value 9.21034 reference critical probability 0.01