Skip to content
Tags give the ability to mark specific points in history as being important
  • v1.1.1
    BETSE 1.1.1 (Nicer Nestor) released.
    
    Significant changes include:
    
    * Dependencies bumped:
      * setuptools >= 38.2.0. The same version of setuptools required by
        BETSEE is now required by BETSE, ensuring parity between the two
        codebases and avoiding painful dependency conflicts. For uniformity,
        this dependency is repeated in both the top-level "pyproject.toml"
        and "tox.ini" configuration files.
    * Issues resolved:
      * pypa/pip#6163 and pypa/pip#6434. This commit circumvents a countably
        infinite number of issues introduced by both pip 19.0.0 and 19.1.0 -
        all pertaining to PEP 517 and 518, which is to say "pyproject.toml".
        The mere existence of a "pyproject.toml" file fundamentally breaks
        pip in inexplicable and horrifying ways: a significantly worse state
        of affairs than the pre-PEP 517 and 518 days of setuptools yore. Say
        what you will of setuptools ("...so much hate"), but at least it
        sorta worked. The same cannot be said of recent pip versions, which
        absolutely do not work whatsoever. "Die, pip! Die!" Specifically:
        * pypa/pip#6163 resolved. All files and subdirectories of the
          project directory containing the top-level "setup.py" script are
          now safely registered to be importable modules and packages.
          Technically, this should not be needed. The current build
          framework (e.g., pip, setuptools) should implicitly guarantee this
          to be the case. Indeed, the obsolete setuptools-based
          "easy_install" script does so. Sadly, pip >= 19.0.0 fails to do so
          for projects defining a top-level "pyproject.toml" file. Although
          upstream purports to have resolved this, the most recent stable
          release of pip continues to suffer this. This is suffering.
        * pypa/pip#6434 resolved. The top-level "pyproject.toml" file now
          explicitly declares a default value for the "build-backend" key.
          Doing so safeguards backward compatibility with pip 19.1.0, which
          erroneously violated PEP 51{7,8} by failing to fallback to a sane
          default value in the absence of this key. If this key is left
          undeclared, pip 19.1.0 fails on attempting to perform an editable
          (i.e., developer-specific) installation of this project.
      * tox-dev/tox#765 resolved. "tox" bundles an obsolete version of
        "virtualenv" itself bundling obsolete versions of both "pip" and
        "setuptools", which obstructs sanity. Our "tox.ini" configuration
        resolves this issue by instructing "tox" to manually update both
        "setuptools" and "virtualenv" to their most recent stable releases.
      * Entry points (i.e., wrapper scripts) resolved. Specifically:
        * Windows-specific entry points installable. Entry points yet again
          install as expected under non-WSL Windows variants (i.e., vanilla,
          Cygwin Windows).
        * Dependency entry points preserved. Long-standing issues with a
          custom monkey patch applied by our top-level "setup.py" script at
          setuptools-based application installation time have now been
          resolved. Previously, this patch globally applied to all
          dependencies installed by "easy_install" (but neither "pip" nor
          "conda", which fortuitously remain unaffected). Now, this monkey
          patch only locally applies to this project and downstream
          consumers of this project (e.g., BETSEE).
      * Setuptools validation relaxed. Validation of the currently installed
        version of setuptools has been relaxed to accept recent non-standard
        version strings (e.g., "41.6.0.post20191029").
    * Testing improved:
      * GitLab CI + "tox". Specifically:
        * Rewrote the top-level ".gitlab-ci.yml" file from the ground up to
          test both installation and runtime on all supported Python 3.x
          versions (rather than runtime on the most recent stable Python 3.x
          version) and leverage industry standards, including:
          * A test matrix exercising all official Python version-tagged
            Docker images rather than a single unofficial Python
            version-agnostic Docker image (i.e., "continuumio/anaconda3").
            Non-slim images are currently preferred to slim variants with
            names suffixed by "-slim" (e.g., "python:3.8-slim"), as the
            latter fail to include C and C++ compilers required to build and
            install wheels for Python packages both lacking official wheels
            and containing mandatory C extensions (e.g., "psutil").
          * The Python-specific "pip" and Debian-based "apt" package
            managers rather than the Anaconda-based "conda" package manager.
            An initial "apt" package cache is now explicitly created before
            attempting to install system-wide packages requiring this cache.
          * The high-level "tox" wrapper rather than the lower-level
            "pytest" test harness.
          * The standard "virtualenv" package rather than GitLab-CI
            internals for isolating test results between different Python
            3.x versions.
          * YAML anchor-based key mapping interpolation rather than external
            scripts for resolving DRY between different Python 3.x versions.
        * Defined a top-level "tox.ini" configuration file, installing all
          optional runtime dependencies to maximize test coverage.
        * Removed the top-level "requirements-pip.txt" file, which was
          frankly superfluous.
    * Documentation revised:
      * Installation instructions rewritten. These instructions have been
        revised from the ground up for simplicity, consistency, and with an
        increased emphasis on the standard pip ecosystem rather than the
        increasingly non-standard Anaconda ecosystem. Specifically:
        * "README.rst" truncated. The top-level "README.rst" file now
          provides only minimal instructions for installing BETSE under the
          two most popular platform-agnostic package managers: pip
          (recommeded) and Anaconda.
        * "INSTALL.rst" added. A new "doc/rst/INSTALL.rst" file providing
          verbose platform-specific instructions for installing BETSE under
          each supported platform (i.e., Linux, macOS, Windows) as
          well as Git-based development and Docker-based containerization
          has now been added.
        * "INSTALL.md" obsoleted. The "doc/md/INSTALL.md" file has been
          removed in favor of the new "doc/rst/INSTALL.rst" file, whose
          underlying reStructuredText is significantly easier to maintain.
        * The sub-level "doc/rst/INSTALL.rst" file
      * pip-based editable installation. The top-level "README.rst" file now
        advises developers to leverage pip rather than setuptools when
        performing an editable installation of this project.
      * "setup.cfg"-based PyPI documentation. The top-level "setup.cfg" file
        now transcludes the contents of the top-level "README.rst" file, a
        substantial improvement over the prior code-based approach strewn
        throughout the codebase (e.g., "setup.py", "betse_setup.buputil").
      * Extraneous files removed. All irrelevant image masks have now been
        pruned from the "doc/yaml/paper" subdirectory. Doing so reduces the
        filesize of release tarballs, minimizes the maintenance burden, and
        presumably eliminates bitrot.
    * Git maintenance:
      * pip directories untracked. All top-level pip-specific temporary
        directories (e.g., "pip-wheel-metadata") are now ignored with
        respect to Git tracking.
    * API generalized:
      * Renamed:
        * The "betse.util.path.command" subpackage to
          "betse.util.os.command".
        * The "betse.util.test.tests" submodule to
          "betse.util.test.tsttest".
      * Generalized the top-level py.test-specific "conftest.py" plugin:
        * Defined a new private _clean_imports() function to perform the
          following when the active Python interpreter is isolated to a venv
          (e.g., due to being exercised by "tox"):
          1. If the top-level directory for this project is listed in the
             global list of all import directories (i.e., "sys.path"),
             remove this directory from this list. Doing so prevents this
             test session from accidentally importing from modules not
             isolated to this venv, including this project being tested.
          2. If the first directory on this list is not isolated to this
             venv, raise an exception. This condition implies that modules
             will be imported from outside this venv, which entirely defeats
             the purpose of isolating tests with "tox" to a venv.
          3. If the top-level "betse" package is not isolated to this venv,
             raise an exception. This condition implies that this project
             has been imported from outside this venv.
        * Refactored the pytest_sessionstart() hook run at test session
          startup to sanitize import directories by calling the newly
          defined _clean_imports() function. Specifically, if this session
          is isolated to a venv, this hook now removes all import
          directories not isolated to this venv from "sys.path" -- as
          required for sane "tox"-based testing. (See above.)
      * Generalized the top-level "setup.py" script:
        * Called the newly defined
          betse_setup.buputil.die_unless_setuptools_version_at_least()
          validator to ensure the currently installed version of setuptools
          satisfies all installation-time requirements.
        * Added a new "test" key-value pair to the setuptools-specific
          "extras_require" dictionary, enabling "tox" to install all
          mandatory testing requirements of this application without
          duplicating those requirements in the top-level "tox.ini" file.
      * Generalized the "betse.exceptions" submodule:
        * Defined new "BetseFunctionUnimplementedException",
          "BetseProcessException", and "BetseProcessNotFoundException"
          classes.
        * Renamed the "BetseOSShellEnvException" class to
          "BetseShellEnvException".
      * Generalized the "betse.metadeps" submodule:
        * Defined a new "SETUPTOOLS_VERSION_MIN" global, providing the
          minimum version of "setuptools" required at both install- and
          runtime. Previously, this global was inaccessibly hardcoded into
          the coarse-grained "RUNTIME_MANDATORY" global.
      * Generalized the "betse.lib.setuptools.command.supcommand" submodule:
        * Defined a new "SetuptoolsCommandDistributionTypes" global tuple of
          all distribution types commonly passed to methods called by the
          "setuptools.command.easy_install.easy_install" class, suitable for
          use in type checking.
      * Defined a new "betse.lib.setuptools.command.supcmdbuild" submodule,
        preserving the most critical of the contents of the prior
        implementation of the "betse_setup.bupbuild" submodule:
        * For safety, this submodule now safely monkey patches
          "easy_install" in an application-local manner.
        * For reusability, this submodule is now generically applicable to
          arbitrary applications -- including both BETSE and downstream
          consumers thereof (e.g., BETSEE).
        * Refactored the _scriptwriter_get_args_patched() class method to:
          * Accept any "ScriptWriter" or "VersionlessRequirement" instance
            as the passed "distribution" parameter.
          * Silently defer to the default ScriptWriter.get_args() method
            under non-WSL Windows variants (i.e., vanilla, Cygwin Windows).
      * Generalized the "betse.util.cli.cliabc" submodule:
        * Improved the CLIABC._options_top() method to print human-readable
          version specifiers when the "-V" and "--version" options are
          passed, complete with optional human-readable codename (e.g.,
          "BETSE 1.1.0 (Nice Nestor)").
      * Defined a new "betse.util.os.process" subpackage:
        * Defined a new "betse.util.os.process.prctest" submodule:
          * Defined a new is_process_command() tester, returning true only
            if the parent process of the active Python interpreter is
            running an external command with the passed basename. This
            function currently requires the optional "psutil" dependency --
            but could theoretically be expanded with platform-specific
            implementations circumventing this requirement.
      * Generalized the "betse.util.os.shell.shellenv" submodule:
        * Refactored the to_str() converter in terms of the
          mappings.to_str_flat() converter.
      * Defined a new "betse.util.py.module.pyimport" submodule:
        * Renamed the prior betse.util.py.pys.add_import_dirname() function
          to register_dir() for brevity and clarity.
        * Defined a new to_str_modules_imported_name() converter, returning
          a human-readable string of the fully-qualified names of all
          previously imported modules.
      * Defined a new "betse.util.py.pyvenv" submodule:
        * Defined a new is_venv() tester, returning true only if the active
          Python interpreter is isolated to a venv.
        * Defined a new get_system_prefix() getter, returning the absolute
          dirname of the top-level directory containing the system-wide
          Python interpreter.
      * Generalized the "betse.util.type.cls.classes" submodule:
        * Revised the die_unless_subclass() docstring to note that all
          classes are considered to be subclasses of themselves within the
          context of this function, complete with a minimal length example
          (MLE) demonstrating this.
      * Generalized the "betse.util.type.iterable.mapping.mappings"
        submodule:
        * Defined a new to_str_flat() converter, flattening the passed
          string-keyed and -valued dictionary into a human-readable string.
      * Refactored the "betse_setup.bupbuild" submodule to defer to the
        new "betse.lib.setuptools.command.supcmdbuild" submodule.
      * Generalized the "betse.lib.setuptools.command.supcmdtest" submodule:
        * Refactored the "test" subclass to inherit the test suite-specific
          "setuptools.command.test.test" superclass rather than the generic
          "setuptools.Command" superclass.
      * Generalized the "betse.util.path.dirs" submodule:
        * Renamed for disambiguity:
          * copy() to copy_dir().
          * copy_into_dir() to copy_dir_into_dir().
        * Defined a new die_if_subdir() function, raising an exception if
          the second passed directory is a subdirectory of the first passed
          directory.
        * Defined a new is_subdir() function, returning true if the second
          passed directory is a subdirectory of the first passed directory.
        * Defined a new remove_dir() function, recursively removing the
          passed directory after logging a warning and waiting several
          seconds for user intervention.
        * Revised docstrings for various existing functions.
      * Generalized the "betse.util.path.files" submodule:
        * Renamed for disambiguity:
          * remove() to remove_file().
          * remove_if_found() to remove_file_if_found().
      * Generalized the "betse.util.path.paths" submodule:
        * Renamed for disambiguity:
          * move() to move_path().
        * Defined a new remove_path() function, either recursively removing
          the passed path if a directory or non-recursively removing this
          path if a file.
      * Generalized the "betse.util.type.obj.objtest" submodule:
        * Defined a new die_unless_is() validator, raising an exception if
          any passed object is not identical to every passed object.
      * Refactored the "betse_setup.bupbuild" submodule to defer to the
        new "betse.lib.setuptools.command.supcmdbuild" submodule.
      * Generalized the "betse_setup.buputil" submodule:
        * Minimized this submodule to the smallest set of requisite
          functions required by the top-level "setup.py" script.
        * Defined a new die_unless_setuptools_version_at_least() validator,
          copied verbatim from the "betsee.beuputil" submodule.
        * Generalized the die_unless_setuptools_version_at_least() function
          to use the general-purpose "distutils.version.LooseVersion" class
          rather than the strict "distutils.version.StrictVersion" class.
      * Debugged the "betse_test.func.sim.test_sim" submodule:
        * Improved the test_cli_sim_compat() functional test to squelch
          (i.e., silence) warnings emitted by matplotlib during this test.
          Specifically, interactive visualizations are now disabled during
          this test by enabling the "betse_cli_sim_compat" fixture to
          overwrite the old simulation configuration required by this test.
    
    (Bituminous arbiter delicately dangles the provocative invocation!)
    
  • v1.1.0
    BETSE 1.1.0 (Nice Nestor) released.
    
    Significant changes include:
    
    * "--headless" option. The "betse" command now accepts a "--headless"
      option, permitting both end users and our test suite alike to
      explicitly enable headless operation. While the codebase did already
      detect most headless environments and thus automatically enable
      headless operation as needed, permitting interested parties to do so
      sanitizes numerous use cases.
    * Backward compatibility guarantee extended to BETSE >= 0.5.0. BETSE now
      guarantees backward compatibility with simulation configurations
      supported by relatively recent versions of BETSE (i.e., BETSE 0.5.0
      and newer).
    * PyYAML -> ruamel.yaml >= 0.15.24 required. BETSE now requires the
      comment- and whitespace-preserving "ruamel.yaml" YAML roundtripper
      rather than the antiquated PyYAML parser. Inadequacies in the Python
      installation ecosystem (e.g., setuptools, wheels) prevent BETSE from
      permissively accepting one of several different YAML implementations
      at installation time. Since "ruamel.yaml" is the superset of all YAML
      implementations, BETSE 1.1.0 officially drops PyYAML in favour of
      "ruamel.yaml".
    * YAML 1.1 -> 1.2. All bundled YAML files have been trivially bumped
      from compliance with YAML 1.1 to 1.2 (i.e., the most recent YAML
      standard), resolving numerous valid complaints from "ruamel.yaml" at
      load time. To preserve backward compatibility with prior
      YAML-formatted simulation configuration files, files compliant with
      YAML 1.1 are implicitly interpreted as compliant with YAML 1.2
      instead.
    * Mandatory dependencies bumped:
      * numpy >= 1.13.0. A recent version of numpy is now required, due to
        our widespread usage of the optional "axis" keyword argument passed
        to the numpy.unique() function first introduced by numpy 1.13.0.
        Doing so resolves a recent spate of CI failures in Windows-ish
        AppVeyor pipelines.
      * py.test >= 3.7.0. A recent version of py.test is now required, which
        introduced a new "package" scope for fixtures. This scope is
        required to efficiently initialize and deinitialize application
        metadata singletons for unit tests.
    * Deprecation warnings resolved:
      * A deprecation from the "betse" script wrapper.
      * A deprecation from the numpy.unique() function on failing to
        explicitly pass the "axis" keyword argument.
    * Numpy optimization detection. To improve detection of optimized Numpy
      installations (i.e., of a "numpy" package linked against a
      multithreaded BLAS implementation), application startup preferentially
      detects whether the active Python interpreter is managed by any of the
      following, in which case Numpy is guaranteed to be optimized:
      * The "conda" package manager.
      * The modern Gentoo Linux scientific stack (i.e., "eselect-ldso").
    * Problematic matplotlib backends blacklisted (i.e., prohibited):
      * Unconditionally blacklisted all Qt 4-specific matplotlib backends
        (e.g., "Qt4Agg", "Qt4cairo"). The Qt Company ceased maintenance of
        Qt 4 in 2015, implying Qt 4 to be insecure, fragile, and largely
        unavailable.
      * Conditionally blacklisted all Qt 5-specific matplotlib backends
        (e.g., "Qt5Agg", "Qt5cairo") under headless environments. When
        headless, these backends reliably cause Qt 5 to silently fail with a
        segmentation fault.
    * Logging improvements:
      * Logfile rotation race conditions resolved. A long-standing issue
        inviting race conditions between multiple processes contending for
        write access to rotational logfiles has now been resolved, thanks to
        intrepid end user Edward Ned Harvey at the Levin Lab. Thanks a
        metric ton, Ed!
      * Logfile closure. Open logfile handles are now guaranteeably closed
        in a platform-portable manner at application shutdown, resolving
        Windows-specific "ResourceWarning: unclosed file" warnings. Namely:
        * The application metadata singleton is now unconditionally
          deinitialized at application shutdown (even in the event of fatal
          exceptions).
        * Our default logging configuration now removes all existing
          handlers from the root logger and close all open file handles
          maintained by those handlers at both initialization and
          deinitialization time.
    * Testing improvements:
      * "${DISPLAY}" squelched. The X.org-specific "${DISPLAY}" environment
        variable is now squelched during testing, resolving functional test
        failures.
      * Windows-specific warnings logged as informational non-warnings, a
        crude workaround to prevent PowerShell from erroneously raising
        non-human-readable exceptions on the first write to standard error.
        (Why!?)
      * "--export-sim-conf-dir" removed. The awkward "--export-sim-conf-dir"
        option previously accepted by our test suite has been obsoleted.
      * Our AppVeyor configuration now:
        * Locally resolves conda/conda#8836, a recent Windows-specific
          Anaconda change significantly breaking backward compatibility with
          most existing AppVeyor configurations -- including ours. To do so,
          the base Anaconda environment is now explicitly activated in an
          early-time manner.
        * Activates its "conda" environment via the "activate" command
          rather than the "conda activate" subcommand, which appears to be
          non-functional.
        * Coerces high-level PowerShell stream objects produced by running
          the "py.test" command into low-level strings. If omitted,
          PowerShell insanely interprets the first write to stderr as a
          non-human-readable exception.
      * Our GitLab-CI Runner configuration now:
        * Caches both "conda" environments and packages to project-local
          directories, which should reduce redundant pipeline overhead.
        * Imports environment variables required for sane "conda" usage and,
          in particular, the recently introduced "conda activate"
          subcommand.
        * Has been streamlined for porting to downstream consumers (e.g.,
          BETSEE):
          * Removed all disabled configuration pertaining to "pip".
            Leveraging "pip" from a Miniconda-based configuration is
            fundamentally wrong.
          * Printed application metadata before running the test suite via
            the new "--headless" option.
    * Documentation improvements:
      * Docstring revisions for numerous subclasses in the
        "betse.science.config.export.visual" submodule for accuracy.
    * API generalizations:
      * Renamed the prior:
        * "betse.metaapp" submodule to "betse.appmeta".
        * "betse.util.app.meta.metaappabc" submodule to
          "betse.util.app.meta.appmetaabc".
        * "betse.util.app.meta.appmetadep" submodule to
          "betse.util.app.meta.appmetamod".
        * "betse.util.app.meta.metaappton" submodule to
          "betse.util.app.meta.appmetaone".
        * "betse.util.io.log.logconfig" submodule to
          "betse.util.io.log.conf.logconf".
        * "betse.util.io.log.logformat" submodule to
          "betse.util.io.log.conf.logconfformat".
        * "betse.util.io.log.loghandle" submodule to
          "betse.util.io.log.conf.logconfhandle".
        * "betse_test.fixture.metaapper" submodule to
          "betse_test.fixture.initter".
      * Generalized the existing "betse.exceptions" submodule:
        * Defines new exception classes, including:
          * "BetseMappingKeyException".
          * "BetseLogRaceException", unique to the aforementioned log
            rotation race condition.
      * Generalized the existing "betse.metadata" submodule:
        * Replaced all references to the obsolete static "SCRIPT_BASENAME"
          global with the dynamic
          betse.util.app.meta.appmetaone.get_app_meta().package_name()
          property, which properly applies to downstream consumers (e.g.,
          BETSEE).
        * Renamed the "GIT_TAG_OLDEST_BACKWARD_COMPATIBILITY" global to
          "GIT_TAG_COMPAT_OLDEST" for brevity.
        * Reverted this global to "v0.5.0", restoring guaranteeable backward
          compatibility with all simulation configurations from BETSE >=
          0.5.0.
      * Generalized the existing "betse.lib.matplotlib.matplotlibs"
        submodule:
        * Defined a new MplConfig.logger() property, yielding Matplotlib's
          root logger object (i.e., "matplotlib").
      * Optimized the existing "betse.lib.numpy.numpys" submodule:
        * Defined a new _is_blas_optimized_conda() tester, deferring to the
          newly defined betse.util.py.pys.is_conda() tester.
        * Optimized the existing is_blas_optimized() tester to
          preferentially call the _is_blas_optimized_conda() tester first,
          which is guaranteed to be both the most optimal and portable
          solution.
      * Streamlined the existing "betse.lib.setuptools.command.supcmdtest"
        submodule:
        * Removed the obsolete "test.export_sim_conf_dir" instance variable.
      * Generalized the existing "betse.lib.yaml.yamls" submodule:
        * Refactored the load() function to accept a new optional
          "yaml_version" parameter, overriding any version directive
          prefacing the passed YAML-formatted file. When passed such a
          parameter with a value other than "1.1" (e.g., "1.2"), this
          function temporarily ignores all non-fatal warnings emitted by
          "ruamel.yaml" specific to the YAML 1.1 specification.
      * Defined a new "betse.lib.yaml.abc.yamlfileabc" submodule:
        * Shifted the prior "betse.lib.yaml.abc.yamlabc.YamlFileABC"
          superclass into this submodule:
          * Defined a new copy() method, encapsulating the lower-level
            load() and save() methods for safe copying YAML-formatted files.
          * Generalized the load() method to accept variadic keyword
            arguments, passed as is to the betse.lib.yaml.yamls.load()
            function.
          * Generalized the save() method to accept two new optional
            parameters:
            * "is_conf_file_overwritable", the overwrite policy for the
              passed target file.
            * "conf_subdir_overwrite_policy", the overwrite policy for
              subdirectories of this file.
        * Defined a new "YamlFileDefaultABC" superclass defining:
          * An abstract conf_default_filename() class property, returning
            the absolute filename of the subclass-specific default YAML file
            (e.g., default simulation configuration).
          * A concrete copy_default() method, copying this file to the
            passed target filename.
      * Removed the "betse.science.config.confio" submodule.
      * Generalized the existing "betse.science.parameters" submodule:
        * Refactored the "Parameters" class:
          * To subclass the newly defined "YamlFileDefaultABC" subclass.
        * Refactored the load() method to override any version directive
          prefacing all YAML-formatted files loaded by this method with
          "1.2", preserving backward compatibility with prior simulation
          configuration files erroneously prefaced by the "%YAML 1.1"
          directive.
        * Replaced all prior calls to the
          betse.science.config.confio.write_default() function with calls to
          the save_default() method.
      * Generalized the existing "betse.science.math.mesh" submodule:
        * Improved the DECMesh.refine_mesh() method to log rather than
          merely print informational messages.
      * Generalized the existing "betse.util.app.meta.metaappabc" submodule:
        * Refactored the "AppMetaABC" superclass:
          * Defined a new deinit() method, deinitializing both this
            application metadata singleton and the current application.
          * Defined the following new properties:
            * module_metadata(), the subclass-specific application metadata
              submodule.
            * module_metadeps(), the subclass-specific application
              dependency metadata submodule.
            * test_package(), the root test package for the current
              application if found or raises an exception otherwise.
            * test_dirname(), the absolute dirname of that package's
              directory if found or raises an exception otherwise.
            * test_data_dirname(), the absolute dirname of that package's
              data subdirectory if found or raises an exception otherwise.
          * Replaced all prior references to the prior abstract
            betse.util.cli.cliabc._module_metadata() property to the new
            module_metadata() property and removed the former.
      * Generalized the existing "betse.util.app.meta.appmetamod" submodule:
        * Defined a new merge_module_metadeps() function:
          * Dynamically creating and returning a new application dependency
            metadata module with arbitrary name iteratively merged from the
            contents of all passed application dependency metadata modules.
          * Copying the "RequirementCommand" class globally defined by the
            first such module into the output module.
      * Generalized the existing "betse.util.app.meta.appmetaone" submodule:
        * Defined a new deinit() function, conditionally encapsulating the
          lower-level betse.util.app.meta.appmetaabc.AppMetaABC.deinit()
          method.
      * Generalized the "betse.util.cli.cliabc" submodule:
        * Refactored the _make_options_top() method into an "_options_top"
          property, preserving orthogonality with the existing
          "betse.util.cli.clicmdabc._subcommander_top" property.
        * Refactored the "_is_option_matplotlib_backend" boolean property
          into an "_matplotlib_backend_name_forced" string property,
          enabling subclasses to force initialization of a desired
          subclass-specific matplotlib backend.
      * Defined a new "betse.util.io.log.conf" subpackage.
      * Defined a new "betse.util.io.log.conf.logconfcls" submodule:
        * Shifted the prior "betse.util.io.log.logconfig.LogConfig" class to
          "LogConf" in this submodule.
      * Generalized the existing "betse.util.io.log.conf.logconf" submodule:
        * Defined a new deinit() function calling a new
          betse.util.io.log.conf.logconfcls.LogConf.deinit() method,
          deinitializing the initialized logging configuration and hence
          closing all open file handles associated with this configuration.
        * Improved the existing init() function to reduce to a noop rather
          than reinitialize a previously initialized logging configuration.
      * Generalized the existing "betse.util.io.log.conf.logconfhandle"
        submodule:
        * Refactored the .LogHandlerFileRotateSafe" subclass:
          * Revised class and method docstrings for clarity, including a
            recommendation that external callers manually pass the
            "--log-file" CLI option when running concurrent BETSE processes.
          * Refactored the _emit_safely() method to:
            * Accept a "self" parameter, a critical bug fix.
            * Sleep for 100ms rather than 50ms.
            * Print additional debug output to standard error documenting
              this method's automatic resolution process.
            * Raise a human-readable exception on exhausting all other
              options, including the same recommendation as documented in
              docstrings.
      * Generalized the existing "betse.util.io.log.logs" submodule:
        * Renamed the get() function to get_logger() for disambiguity.
      * Generalized the existing "betse.util.io.stdouts" submodule:
        * Repaired the output_lines() function, which suffered a critical
          (albeit trivial) defect.
      * Defined a new "betse.util.os.brand.linux" submodule:
        * Defined a new is_mir() tester, returning true only if the active
          Python interpreter is running under the Mir compositor.
        * Defined a new is_wayland() tester, returning true only if the
          active Python interpreter is running under the Wayland compositor.
        * Shifted the existing betse.util.os.is_linux() tester into this
          submodule.
      * Defined a new "betse.util.os.brand.macos" submodule:
        * Shifted the existing betse.util.os.is_macos() tester into this
          submodule.
      * Defined a new "betse.util.os.brand.posix" submodule:
        * Defined a new is_x11() tester, returning true only if the active
          Python interpreter is running under an X11 display server.
        * Shifted the existing betse.util.os.is_posix() tester into this
          submodule.
      * Generalized the existing "betse.util.os.brand.windows" submodule:
        * Defined a new is_version_10_or_newer() tester, returning true if
          the current platform is Windows >= 10.
        * Defined a new get_api_version() getter, returning the current
          low-level Windows API (WinAPI, Win32) version.
        * Shifted the is_windows(), is_windows_cygwin(),
          is_windows_vanilla(), and is_windows_wsl() testers from the
          existing "betse.util.os.brand.os" submodule into this submodule.
      * Generalized the existing "betse.util.os.displays" submodule:
        * Defined a new is_dpi_scaling() tester, returning true if the
          current platform natively supports high-DPI scaling.
        * Refactored the is_headless() tester to defer to the most recent
          call to the newly defined set_headless() function (if any).
        * Defined a new set_headless() setter, enabling callers to
          explicitly force headless operation and hence override the
          implicit detection of headless environments performed by the
          is_headless() tester.
      * Generalized the existing "betse.util.os.kernels" submodule:
        * Defined a new is_version_greater_than_or_equal_to() tester,
          enabling callers to trivially detect minimum kernel versions and
          hence the existence of platform features introduced by those
          versions.
        * Revises the get_version() getter to return the high-level Windows
          kernel version (e.g., "10.0.10240") rather than the low-level
          Windows API version (e.g., "6.2.9200").
      * Generalized the existing "betse.util.os.shell.shellenv" submodule:
        * Defined a new to_str() function, returning a human-readable string
          of all environment variables defined by the host shell
          environment.
      * Generalized the existing "betse.util.py.module.pymodname" submodule:
        * Defined a new make_module() function, enabling callers to
          dynamically generate new in-memory modules containing arbitrary
          module attributes.
      * Generalized the existing "betse.util.py.module.pymodule" submodule:
        * Defining a new is_module() tester, returning true only if the
          passed object is a module.
      * Generalized the existing "betse.util.type.obj.objects" submodule:
        * Refactoring the get_attr() getter to embed the fully-qualified
          name of the passed module when passed a module in raised
          exceptions.
      * Generalized the existing "betse.util.py.pys" submodule:
        * Defined a new is_conda() tester, returning true if the active
          Python interpreter is managed by conda. For debuggability, this
          metadata is now logged when the "info" subcommand is run.
      * Defined a new "betse.util.test.pytest.fixture" subpackage:
        * Defined a new "betse.util.test.pytest.fixture.pytfixture"
          submodule:
          * Defined a new monkeypatch_session() fixture, generalizing the
            standard function-scope "monkeypatch" fixture to session scope.
      * Generalized the existing "betse.util.test.pytest.pytests" submodule:
        * Defined a new output() function, printing the passed objects to
          standard output in a format consistent with that of standard
          "py.test" messages.
      * Generalized the existing "betse.util.type.iterable.iterables"
        submodule:
        * Defined a new to_str() function, synthesizing a human-readable
          prettified string of the passed iterable.
        * Improves the existing to_iterable() converter to behave as
          expected when passed an input generator.
      * Defined a new "betse.util.type.iterable.iteriter" submodule:
        * Defined a new iter_pairs() iterator, creating and returning a new
          iterable of all possible pairs of items in the passed iterable.
        * Defined a new iter_combinations() iterator, creating and returning
          a new iterable of all possible k-combinations of items in the
          passed iterable.
      * Generalized the existing "betse.util.type.iterable.mapping.mappings"
        submodule:
        * Defined a new die_unless_keys_unique() function, raising an
          exception unless no passed dictionaries collide (i.e., contain the
          same key).
        * Defined a new is_keys_unique() tester, returning true only if no
          passed dictionaries collide.
        * Defined a new iter_keys_ascending() iterator, returning an
          iterable of all keys of the passed dictionary in ascending order
          (typically, lexicographic).
        * Removed the unused (and largely useless) format_map() function,
          now superceded by the newly defined
          betse.util.type.iterable.iterables.to_str() function.
      * Defined a new "betse.util.type.iterable.mapping.mapmerge" submodule:
        * Shifted the betse.util.type.iterable.mapping.mappings.merge_maps()
          function into this submodule.
        * Defined a new "MergeCollisionPolicy" enumeration type whose
          members each describe a different type of key collision merger
          policy (i.e., strategy for merging keys shared by one or more
          mappings).
        * Refactored the merge_maps() function to:
          * Merge arbitrarily many dictionaries under any key collision
            policy.
          * Behave as expected when passed a non-sequence of input mappings.
          * Defer to the newly defined
            betse.util.type.iterable.mapping.maptest.die_if_maps_collide()
            validator.
      * Defined a new "betse.util.type.iterable.mapping.maptest" submodule:
        * Shifted all testing and exception handling logic from the
          "betse.util.type.iterable.mapping.mappings" submodule into this
          submodule.
        * Renamed the following functions for orthogonality:
          * die_unless_keys_equal() to die_unless_maps_keys_equal().
          * die_unless_keys_unique() to die_unless_maps_keys_unique().
          * is_key() to has_keys().
          * is_keys_equal() to is_maps_keys_equal().
          * is_keys_unique() to is_maps_keys_unique().
        * Defined a new die_unless_has_keys() validator, raising an
          exception unless the passed mappings contains all passed keys.
        * Replaced the largely useless die_unless_maps_keys_unique()
          validator with a new die_if_maps_collide() validator, raising an
          exception only if no passed mappings collide.
        * Replaced the largely useless is_maps_keys_unique() tester with a
          new is_maps_collide() tester, returning true only if one or more
          passed mappings collide (i.e., contain key-value pairs containing
          the same keys but differing values).
        * Refactored the die_unless_maps_keys_unique() validator to improve
          the granularity of the exception message raised by this function,
          which now iteratively finds the exact set of key collisions in the
          passed dictionaries with the newly defined
          betse.util.type.iterable.iteriter.iter_pairs() iterator.
        * Refactored the has_keys() tester to accept a simple iterable of
          all keys to be tested rather than a variadic positional tuple of
          such keys.
      * Generalized the "betse.util.type.iterable.sequences" submodule:
        * Defined a new die_if_length_less_than() validator, raising an
          exception if the passed sequence contains less than the passed
          number of items.
        * Defined a new to_sequence() converter, converting the passed
          iterable into a sequence as needed.
        * Refactored the die_if_empty() validator to operate similarly to
          all other validators defined by this submodule.
      * Generalizes the "betse.util.type.iterable.mapping.maptest"
        submodule:
        * Refactored the is_maps_collide() tester to call the newly defined
          betse.util.type.iterable.sequences.die_if_length_less_than() and
          betse.util.type.iterable.set.sets.make_union() functions, thereby
          both simplifying and correcting the existing implementation.
      * Defined a new "betse.util.type.iterable.set" subpackage:
        * Shifted the existing "betse.util.type.iterable.sets" submodule to
          "betse.util.type.iterable.set.setcls" for disambiguity.
        * Defined a new "betse.util.type.iterable.set.sets" submodule:
          * Defined a new make_union() function, calculating the union of
            all items in arbitrarily many possibly non-set iterables.
      * Generalized the existing "betse.util.type.text.string.strs"
        submodule:
        * Refactored the get_prefix_preceding_char_or_none() getter:
          * Renamed this getter to get_prefix_or_none().
          * Renamed the "char" parameter accepted by this getter to
            "anchor".
          * Added an optional "is_first" parameter to this getter, enabling
            callers to retrieve both greedy and non-greedy prefixes.
      * Streamlined the existing "betse_setup.buputil" submodule by removing
        extraneous functionality (e.g., die_unless_module(), is_module()).
      * Streamlined the existing "betse_test.conftest" submodule:
        * Removed all functionality pertaining to the ${DISPLAY} environment
          variable from the less robust and reusable pytest_configure()
          function in favour of the
          betse_test.fixture.initter.betse_autouse() fixture.
        * Removed the obsolete "EXPORT_SIM_CONF_DIRNAME" global.
      * Defined a new "betse_test.data" subdirectory embedding the default
        simulation configuration supplied by BETSE 0.5.0, enabling the
        betse_test.func.sim.test_sim.test_cli_sim_compat() functional test
        to fully exercise backward compatibility with this configuration.
      * Rewrote the "betse_test.fixture.initter" submodule:
        * Defined a new autouse package-scoped betse_init_package() fixture,
          intended to be imported by the "betse_test.unit.conftest" plugin
          to guarantee application initialization before unit testing.
        * Renamed the betse_meta_app() fixture to betse_autouse(), which now
          additionally unsets the ${DISPLAY} environment variable if set.
        * Moved the existing betse_test.conftest._init_app() and
          _deinit_app() functions into this submodule as init_app() and
          deinit_app() for importability elsewhere.
      * Generalized the existing "betse_test.fixture.simconf.simconfer"
        submodule:
        * Redefined the betse_sim_conf() fixture in terms of the lower-level
          betse_sim_conf_default() fixture.
        * Refactored the betse_sim_conf_compat() fixture to leverage the
          Git-hosted "betse_test/data/v0.5.0/yaml/sim_config.yaml"
          simulation configuration corresponding to the default
          configuration circa BETSE 0.5.0.
      * Generalized the existing "betse_test.fixture.simconf.simconfclser"
        submodule:
        * Refactored the "SimConfTestABC" superclass to initialize the
          application metadata singleton before saving a simulation
          configuration for the current functional test.
        * Refactored the "SimConfTestInternal" subclass to require
          general-purpose "src_conf_filename" and "trg_conf_filepath"
          filenames be passed on initialization. Previously, this subclass
          only accepted the latter and defaulted the former to the default
          simulation configuration file.
      * Generalized the existing "betse_test.fixture.simconf.simconfwrapper"
        submodule:
        * Refactored the "SimConfigTestWrapper" class:
          * Refactored the __init__() method to accept a high-level
            "Parameters" object rather than a low-level simulation
            configuration filename.
          * Removed a number of extraneous methods and properties (notably,
            the make_default() class method).
      * Generalized the existing "betse_test.func.fixture.clier" submodule:
        * Called the betse.util.app.meta.metaappabc.AppMetaABC.deinit()
          method before running each functional test.
      * Removed the obsolete "betse_test.func.sim.test_sim_export"
        submodule.
      * Generalized the existing "betse_test.func.sim.test_sim" submodule:
        * Removed all @skip decoration from the test_cli_sim_compat() test.
      * Defined a new "betse_test.unit.type.iterable.mapping.test_mapmerge"
        submodule, fully exercising the newly generalized
        betse.util.type.iterable.mapping.mapmerge.merge_maps() function (now
        featuring 667% more obscure Cthulhu mythos references).
      * Defined a new "betse_test.unit.app.meta.test_appmetamod" submodule,
        fully exercising the newly defined
        betse.util.app.meta.appmetamod.merge_module_metadeps() function.
      * Generalized the betse_test.unit.path.test_dirs.test_packages_init()
        unit test to exclude all data-specific directories from
        consideration, including both the "AppMetaABC.data_dirname" and
        "AppMetaABC.test_data_dirname" directories if found.
      * Generalized the existing
        betse_test.unit.type.iterable.test_iterables.test_to_iterable() unit
        test to exercise additional edge cases of that underlying function.
    
  • v1.0.0
    BETSE 1.0.0 (Mighty Maxwell) released.
    
    Significant changes include:
    
    * Discrete exterior calculus (DEC). In the seed phase, BETSE now
      rigorously constructs the Voronoi diagrams and dual triangular meshes
      underlying all cell clusters according to DEC theory. DEC operators
      and methods are available for external use via the newly introduced
      "cells.mesh" object.
    * New "fast" and "full" solver types. BETSE can now work from an
      equivalent circuit model formalism (e.g. Hodgkin-Huxley based model of
      bioelectricity) using the new "fast" solver or from its original
      molecular view of bioelectricity using the "full" solver type. This
      allows users to tailor their computational perspective to the needs of
      their biophysical problem.
    * Expression profile read-in. BETSE can now read in expression levels
      from a user-defined expression configuration file for any
      custom-defined biomolecule, transporter, or channel. This allows
      different levels of a biomolecule, transporter, or channel to be
      specified on all of the user-defined tissue profiles of a BETSE model,
      where expression data can be sourced from experiments or experimental
      databases.
    * Single cell simulation. BETSE can now simulate a single cell, a
      feature requested for fast prototyping of certain simulations.
    * SVG model definition. In addition to the original bitmap method of
      defining cell cluster and tissue profiles, BETSE also allows use of
      Scalable Vector Graphics (SVG) files to define exact locations of
      cells in your cluster, with the fill colors of circles defined by
      these files now assigning the cell centred at that circle to the
      tissue profile associated with that color.
    * Mesh refinement. Optionally run a refinement algorithm on BETSE meshes
      to generate more computationally robust model geometries.
    * Modulator functions. Use a customizable modulator function (e.g.
      gradient along the x-axis) to modulate expression of custom
      biomolecules, transporters, or pumps.
    * Significant bugs resolved, including:
      * Gene regulatory network (GRN) equilibrium guarantees. Reactions and
        transporter rate expressions in user-defined GRNs now converge to
        the appropriate equilibrium constants.
      * Arrowhead size in exported visuals sanitized. Arrowheads in exported
        stream plots and animations are now sized appropriately rather than
        oversized.
      * Cation leak channels.
    * Deprecations and warnings resolved, including:
      * Deprecated usage of the "pytest.config" global. The
        betse_test.conftest.pytest_configure() hook now sets the
        "betse_test.conftest.EXPORT_SIM_CONF_DIRNAME" global to the value of
        the "--export-sim-conf-dirname" option, circumventing
        "pytest.config" entirely.
      * Deprecated usage of the yaml.load() function with no explicit
        "Loader". The betse.lib.yaml.yamls._load_pyyaml() function now
        dynamically calls whichever of the yaml.full_load() or yaml.load()
        functions are available for the current version of PyYAML, thus
        circumventing yaml.load() insecurities under newer PyYAML versions.
    * Simulation configuration improvements, including:
      * Nameable exports. A human-readable name (e.g., "Cell Cluster:
        Transmembrane Voltage") may now be associated with each pipelined
        export, including plots, animations, and CSV-formatted files.
      * Obsolete settings removed, including:
        * A vestigial block of intervention-specific settings.
      * Data descriptor encapsulation. Various settings derived from the
        currently open YAML-formatted simulation configuration file have now
        been refactored from low-level instance variables of the
        "betse.science.parameters.Parameters" class to high-level
        yaml_alias()-based data descriptors, enabling downstream consumers
        (e.g., the BETSEE GUI) to transparently propagate modifications to
        these settings back to this file. These include settings pertaining
        to:
        * Enumeration (i.e., indexation, numbering) of cells in the cell
          cluster.
        * Matplotlib colormap names.
    * Documentation improvements, including:
      * Tutorials. Official user- and developer-specific BETSE tutorials
        have now been added to the repository. A "Tutorials" subsection
        listing this documentation has also been the top-level "README.rst"
        file.
      * Simulation configuration settings, including:
        * Application-specific matplotlib colormaps. Our default
          YAML-formatted simulation configuration file now exhaustively
          lists the names of all available application-specific matplotlib
          colormaps.
    * Test suite improvements, including:
      * "py.test" exit code. The top-level "test" script now correctly
        reports the exact exit code reported by the "py.test" test suite.
      * Additional unit tests, including:
        * The "betse_test.unit.type.iterable.test_iterables" submodule,
          which now exercises the overly intricate and hence fragile
          betse.util.type.iterable.iterables.to_iterable() function.
    * Debuggability improvements, including:
      * Type validation debuggability. Wrapper functions synthesized by the
        @type_check decorator now sport the disambiguous name
        "__{func_name}_type_checked__" rather than the ambiguous name
        "func_type_checked".
    * API generalizations, including:
      * The "betse.science.pipe" subpackage, such that:
        * The existing SimPipeABC.iter_runners_conf() method is now
          constrained to strictly return indexable sequences rather than
          possibly non-indexable iterables, as external callers commonly
          require the former.
        * The new SimPipeABC.iter_runners_metadata_kind() method returns a
          sequence of the types of all runners declared by the current
          pipeline (in sorted lexicographic order).
        * The prior "SimPipeRunnerMetadata.name" instance variable has been
          renamed to "SimPipeRunnerMetadata.kind" for disambiguity with the
          unrelated "name" data descriptor of runner subconfigurations.
      * The "betse.lib.matplotlib.mplcolormap" submodule, which defines:
        * The iter_colormap_names() iterator, yielding the names of all
          currently registered matplotlib colormaps (in sorted lexicographic
          order).
      * The "betse.util.math.geometry.geopoint" submodule, whose is_point()
        function has been generalized to test whether coordinates of each
        passed point are strictly numeric or not.
      * The "betse.util.type.iterable.iterables" submodule, whose:
        * to_iterable() function has been generalized to optionally accept
          an "item_cls" parameter, which when non-None coerces all items of
          the returned iterable to instances of that parameter.
      * The "betse.util.type.iterable.iterget" submodule, whose:
        * Newly defined get_item_first() and get_item_first_or_sentinel()
          functions retrieve the first items from arbitrarily many
          iterables.
        * get_item_str_uniquified() has been generalized to optionally
          implicitly synthesize default string values for non-compliant
          items, as needed for preserving backward compatibility.
      * The "betse.util.type.iterable.itersort" submodule, whose:
        * _sort_iterable() function has been optimized for the common case
          of generators and generator comprehensions.
      * The "betse.util.type.iterable.itertest" submodule, whose:
        * is_items_unique() function has been:
          * Generalized to support iterables not satisfying the
            "collections.abc.Sized" protocol (e.g., generators).
          * Optimized to induce best-case time complexity in the average
            case.
      * The "betse.util.type.iterable.mapping.mappings" submodule, which
        defines:
        * A pair of related die_unless_keys_equal() and is_keys_equal()
          functions, efficiently validating and testing whether the passed
          set of dictionaries all contain the exact same keys.
      * The "betse.util.type.iterable.sequences" submodule, which defines:
        * The get_index() function, enabling callers to retrieve items with
          arbitrary indices from arbitrary sequences in a manner guaranteed
          to raise human-readable exceptions on failure.
      * The "betse.util.type.obj.objects" submodule, whose:
        * get_method() function has been renamed to get_callable().
        * get_method_or_none() function has been renamed to
          get_callable_or_none().
        * "method_name" parameters accepted by both of the aforementioned
          functions have been renamed to "callable_name".
      * The "betse.util.type.text.string.strjoin" submodule, which defines:
        * A new join_iterable_as_conjunction_double_quoted() function
          implicitly coercing all items of the passed iterable to strings.
      * The "betse.util.type.types" submodule, which now defines:
        * The special "MethodWrapperType" type, formerly available only
          under Python >= 3.7 as "types.MethodWrapperType".
        * A "ContainerTypes" type supporting both standard Python containers
          and Numpy arrays, replacing the prior "ContainerType" type not
          supporting Numpy arrays.
        * A "SequenceStandardTypes" tuple of all standard sequence types
          (i.e., "list", "tuple").
        * Significantly fewer obsolete testers and asserters, which have now
          been permanently removed in favour of the @type_check decorator.
  • v0.9.2
    BETSE 0.9.2 (Luckiest Levin) released.
    
    Significant changes include:
    
    * Downstream data dirname issues resolved. Previously, downstream
      consumers (e.g., the BETSEE GUI) were erroneously required to recreate
      rather than share the default simulation configuration provided by the
      BETSE codebase. This has now been resolved, reducing unseemly Don't
      Repeat Yourself (DRY).
    * Gene regulatory network (GRN) pathname issues resolved. Specifically,
      the "gene regulatory network settings/gene regulatory network config"
      setting in YAML-formatted simulation configuration files has now been
      generalized to be relative to the directory containing those files.
    * Resource consumption reduced. Matplotlib-based figures, graphs, plots,
      and animations are now properly destroyed on completion, substantially
      reducing memory usage during long-running simulation exports.
    * Deprecation warnings eliminated. The codebase now complies with all
      upstream deprecations, including breaking NumPy, py.test, and Python
      changes. Notably, NumPy >= 1.16 has deprecated the passing of
      arbitrary iterables to the np.column_stack() function, which now
      requires strict sequences:
          FutureWarning: arrays to stack must be passed as a "sequence" type
          such as list or tuple. Support for non-sequence iterables such as
          generators is deprecated as of NumPy 1.16 and will raise an error
          in the future.
      Since converting non-sequence iterables to sequences is trivial
      (ignoring the obvious edge case of infinite generators, which much
      like the legendary Pokemon of yore appear not to exist in the wild),
      NumPy developers chose poorly when they chose to explicitly break
      rather than implicitly resolve this non-issue. Thanks for generating
      more meaningless boilerplate, NumPy.
    * Significant continuous integration (CI) improvements, including:
      * Conda-forge-centric testing. All CI host environments (i.e.,
        GitLab-CI, AppVeyor) now install all mandatory and optional
        application dependencies from the open-source volunteer
        "conda-forge" channel rather than the closed-source proprietary
        "anaconda" channel. Doing so better mimics real-world installation
        environments and enables us to begin exercising optional
        dependencies (e.g., FFmpeg, NetworkX, PyDot).
      * Early-time logging verbosity increased. To simplify testing
        maintenance, Early-time logging verbosity increased has now been
        increased during tests.
      * CI-specific decorators added. The new
        betse.util.test.pytest.mark.pytskip.skip_if_ci_gitlab() decorator
        skips the decorated test or fixture if GitLab-CI is currently
        hosting these tests.
      * The following previously failing tests have been corrected:
        * The test_packages_init() unit test, which is now conditionally
          skipped under GitLab-CI by the aforementioned decorator. GitLab-CI
          no longer clones this repository correctly, erroneously preserving
          empty subdirectories no longer tracked by git. While usually
          innocuous, empty subdirectories trigger false negatives from this
          unit test. Since this test succeeds both locally and under
          AppVeyor, GitLab-CI's misconfigured git checkout policy
          inexplicably remains the culprit.
        * The test_c_* pair of unit tests, which erupted into incoherent
          flames due to inappropriate assumptions about the internal
          structure of NumPy. NumPy
          1.16.0 unified the prior public "numpy.core.multiarray" and
          "numpy.core.umath" C extensions into a new private
          "numpy.core._multiarray_umath" C extension.
        * The pivotal test_cli_sim_compat() functional test, which has now
          been reenabled in a manner seemingly incompatible with recent
          py.test changes. Since this test safeguards backward compatibility
          with respect to our YAML-based simulation configuration format,
          enabling this test is critical to long-term joy.
    * Installation-time improvements, including:
      * Substantial "setup.py" streamlining. The contents of our topmost
        setuptools-based installation script now reflect those of their
        counterpart in the BETSEE GUI -- which is to say, this script has
        been compacted into a fairly minimal line length.
      * "betse.metadata.PYTHON_VERSION_MINOR_MAX" addition. This integer
        global specifies the maximum minor stable version of the Python 3.x
        mainline, as required by this "setup.py" streamlining.
      * "betse_setup.buputil" streamlining. This submodule collects
        miscellaneous utility functions required only at BETSE installation.
        This submodule has now been reduced in length, reducing our
        maintenance burden.
    * Significant internal API improvements, including:
      * Application API creation. The new "betse.util.app" subpackage now
        provides:
        * The prior "betse.util.meta" subpackage, which has been subsumed
          under "betse.util.app.meta" for maintainability.
        * Application pathname API creation. The new
          "betse.util.app.apppath" submodule enables callers to query the
          absolute pathnames of application-relative paths regardless of
          application installation specifics (e.g., setuptools-based egg,
          frozen application).
        * Application initialization API centralized. The existing
          "betse.util.app.meta.metaappabc.MetaAppABC" superclass now
          centralizes all application initialization logic into a single
          coherent object-oriented API previously distributed throughout the
          codebase as a cacophony of incoherent procedural APIs not reusable
          by downstream consumers. This includes:
          * The "MetaAppABC" constructor, which now guarantees the current
            application to be completely initialized excluding third-party
            dependencies (e.g., NumPy, SciPy), whose initialization must
            necessarily be deferred until later in the application startup
            process. This constructor now entirely obsoletes the prior
            "betse.ignition" API.
          * The MetaAppABC.init_libs() method, which now initializes
            third-party dependencies (e.g., NumPy, SciPy) in a
            user-configurable manner late in the application startup
            process. This method now obsoletes a significant portion of the
            existing "betse.lib.libs" API.
          * The MetaAppABC.init_libs_if_needed() method, which efficiently
            simplifies the aforementioned process on behalf of low-level
            automation (e.g., dark voodoo in the "betse.science.__init__"
            module).
        * Application metadata singleton API creation. The new
          "betse.util.app.meta.metaappton" submodule centralizes all logic
          concerning the application metadata singleton previously residing
          in the "betse.metaapp" submodule.
      * Bitwise API creation. The new "betse.util.type.numeric.bits"
        submodule now provides general-purpose bit and bit field
        functionality, including an is_bit_on() function implementing a
        standard bit field testing routine.
      * Matplotlib Figure API creation. The new
        "betse.lib.matplotlib.mplfigure" submodule defines critical
        functionality for reliably closing matplotlib figures, a prevalent
        "pain point" in most matplotlib-based applications.
      * Testing API creation. The new "betse.util.test" subpackage now
        defines testing-specific APIs, including:
        * The new "betse.util.test.tests" submodule, defining
          general-purpose test suite functionality. This includes the
          is_testing() tester, enabling the codebase itself to query whether
          or not it is currently being tested.
        * The new "betse.util.test.tstci" submodule, defining CI-specific
          functionality. This includes one tester for each well-known CI
          host (e.g., is_ci_gitlab() for GitLab-CI), returning true only
          when the active Python interpreter is exercising tests on that
          host.
        * The new py.test API. The BETSE-specific and hence non-reusable
          "betse_test.util" subpackage has been moved to the BETSE-agnostic
          and hence reusable "betse.util.test.pytest" subpackage, enabling
          reuse by downstream consumers (e.g., BETSEE).
      * Class API generalizations. The "betse.util.type.cls.classes"
        submodule now defines a host of new general-purpose getter
        functions, including:
        * get_name_qualified(), obtaining the fully-qualified name of the
          passed class. The implementation proved highly non-trivial, due to
          common edge cases (e.g., classes with no or poorly defined
          modules).
        * get_module_name_qualified_or_none(), obtaining the fully-qualified
          name of the module defining the passed class if any or "None"
          otherwise.
      * Module API generalizations. A new "betse.util.py.module" subpackage
        has been created, replacing the prior "betse.util.py.pymodule"
        submodule. This subpackage provides the following new submodules:
        * "betse.util.py.module.pymodname", providing lookup facilities both
          to and from fully-qualified module names and their corresponding
          module objects.
        * "betse.util.py.module.pymodule", providing generic module
          handling.
        * "betse.util.py.module.pypackage", providing generic package
          handling -- notably, the get_object_type_package_root() function
          returning the root package transitively defining any arbitrary
          object's class.
      * String API generalizations. The existing "betse.util.type.text.strs"
        submodule now defines a holy trifecta of
        "get_prefix_preceding_char"-prefixed functions, enabling callers to
        obtain the prefix preceding any character in arbitrary strings.
    * Obsolete subdirectories removed, including:
      * The long-broken "doc/examples" subdirectory, whose code snippets
        have all non-working for at least several major application
        revisions. While documentation in and of itself is commendable, bad
        documentation is readily worse than no documentation.
      * The long-unused "betse/data/yamale" subdirectory.
  • v0.9.1
    BETSE 0.9.1 (Luckier Levin) released.
    
    Significant changes include:
    
    * Cell boundary search radius increased, improving simulation stability
      in worst-case spatial layouts for user-defined cell clusters.
    * MetaAppABC API added. The new object-oriented "betse.metaapp"
      submodule replaces the prior procedural "betse.pathtree" submodule,
      enabling inheritance-fueled reuse from downstream consumers (e.g.,
      BETSEE). The MetaAppABC API is intended to eventually encompass all
      general-purpose functionality required.to implement BETSE-like
      applications -- including application initialization, dependency
      resolution and initialization, and a nominal command-line interface
      (CLI).
    * Git API generalized. The new
      betse.util.path.gits.get_package_worktree_dirname_or_none() function
      queries whether a given top-level Python package is in Git-based
      development mode.
    * Numpy API generalized. The new
      betse.lib.numpy.nparray.get_subarray_indices() function efficiently
      yields the indices of all items of one Numpy array residing in
      another.
    * Path API generalized. The new high-level
      betse.util.files.copy_overwritable() function, wrapping the existing
      lower-level betse.util.files.copy() function for the common case of
      silently overwriting arbitrary target files.
    * String API generalized to support substantially enhanced truncation
      operations in the "betse.util.type.text.strs" submodule, including:
      * The new high-level truncate() function, truncating strings to
        caller-defined barriers (e.g., maximum length, terminal substring)
        and then replacing the truncated suffixes with arbitrary strings
        (e.g., ellipses).
      * The new replace_suffix_prefixed() function, prematurely truncating
        strings on impermissible substrings (e.g., newline).
      * The existing remove_suffix_with_prefix() function reduced to a
        one-liner, a substantial optimization preventing this function from
        erroneously raising exceptions in edge cases both common and
        uncommon.
      * The existing
        betse.util.type.text.regexes.die_unless_replace_substrs_line()
        function, now truncating internally raised exception messages for
        readability.
    * Version API generalized. The formerly mostly empty
      "betse.util.type.numeric.versions" submodule has been substantially
      improved, despite the inability of the setuptools-bundled
      "pkg_resources" API to preserve backward compatibility across stable
      releases. Our version API now portably allows versions in any of
      several formats (i.e., string, tuple, or setuptools-specific "Version"
      or "LegacyVersion" objects) to be reliably compared. PEP 440-compliant
      versions (e.g., "5.9.0") and PEP 440-uncompliant versions (e.g.,
      "5.9.0~a1") are explicitly supported.
    * Version API tested. Unit tests fully exercising all edge cases of the
      "betse.util.type.numeric.versions" submodule have been added.
  • v0.9.0
    BETSE 0.9.0 (Lucky Levin) released.
    
    Significant changes include:
    
    * Python >= 3.5 required. In accordance with the looming end-of-life
      (EOL) of Python 3.4, BETSE now strictly requires at least Python 3.5.
    * Single-cell plots added. The following two single-cell plots may now
      be added to both the initialization  and simulation export pipelines:
      * "ion_calcium_er", plotting all calcium (i.e., Ca2+) ion
        concentrations for the endoplasmic reticulum of the single cell
        indexed by the current simulation configuration over all sampled
        time steps.
      * "voltage_membrane_er", plotting all transmembrane voltages across
        the endoplasmic reticulum of the single cell indexed by the current
        simulation configuration over all sampled time steps.
    * Deprecation warnings resolved. Deprecation warnings emitted by
      py.test >= 3.1.0, Python >= 3.6, and recent versions of Numpy have
      been summarily squelched.
    * Simulation callbacks substantially improved, improving UX
      responsiveness in downstream consumers (e.g., BETSEE). Specifically:
      * Seed progress granularized. Progress for the seed phase is now
        reported in a more granular (i.e., fine-grained) manner.
      * Export progress. Progress on exporting CSV files, plots, and
        animations from both the initialization export (i.e., "betse plot
        init") and simulation export (i.e., "betse plot sim") phases is now
        reported in a highly granular manner.
      * Callbacks API generalized. Specifically, in the
        "betse.util.type.call.callbacks" submodule:
        * The new CallbacksBC.progress_stated() callback enables source
          callables to notify sink callbacks of arbitrary human-readable
          strings informing end users of the current state of progress. As
          semantic sugar, the existing CallbacksBC.progressed_next()
          callback has been augmented to accept the same strings.
        * The new CallbacksABC.progressed_last() callback enables source
          callables to safely iterate progress, improving robustness and
          maintainability.
    * Simulation variables streamlined. Specifically:
      * All core simulation pathname variables now reside in the central
        "Parameters" class rather than distributed across both that and the
        "Cells" and "Simulator" classes, reducing logic across the codebase.
      * The obsolete "Parameters.total_time_accelerated" variable has been
        removed.
      * All but one reference to the obsolete "Parameters._run_sim" boolean
        have been removed in lieu of the "SimPhase.kind" enumeration.
      * The obsolete Parameters.set_time_profile() method has been
        refactored into the SimPhase._init_kludge_time() method.
      * The "Parameters.init_tsteps" and "Parameters.sim_tsteps" variables
        are now unconditionally defined rather than only conditionally
        defined when the SimPhase._init_kludge_time() method is called.
    * Matplotlib API sanitized. The antiquated
      "betse.lib.matplotlib.matplotlibs" submodule now complies with the
      modern Matplotlib API in a robust manner. Specifically:
      * Headless Qt blacklisted. The default "Qt5Agg" backend is now
        blacklisted when the current process is headless, preventing
        Matplotlib from silently terminating this process.
      * Visualization API improved. The "betse.science.visual.visabc"
        submodule has been improved to preferentially leverage the
        object-oriented Matplotlib API over the procedural "pyplot" API
        where feasible, reducing unexpected exceptions from backends.
    * Installation sanitized. Specifically:
      * The top-level "MANIFEST.in" file now explicitly includes and
        excludes all installation-time paths as appropriate.
      * The top-level "setup.py" script now conforms to the more succinct
        and hence saner approach of downstream consumers (e.g., BETSEE).
    * Descriptor API added. The new "betse.util.type.descriptor.descs"
      submodule defines general-purpose descriptors, including the
      @classproperty_readonly and @abstractclassproperty_readonly decorators
      implementing concrete and abstract read-only class properties
      respectively.
    * Iterable subpackage added. The new "betse.util.type.iterable"
      subpackage now aggregates all subpackages pertaining to container
      datatypes (e.g., iterables, queues, sequences). Specifically:
      * Queue API added. The new "betse.util.type.iterable.queues" submodule
        now aggregates queue-centric functionality, including the efficient
        popping of multiple items from the head of a queue.
      * Tuple API added. The new "betse.util.type.iterable.tuples" submodule
        now aggregates tuple-centric functionality, including the efficient
        creation of named tuple subclasses.
    * CLI API generalized. The
      "betse.util.cli.clicmdabc.CLISubcommandableABC" abstract base class
      now helpfully provides a sane implementation of the abstract
      _help_epilog() property, simplifying subclass implementation.
    * Class decorator API generalized. The new
      @betse.util.type.decorator.abstractclassmethod decorator trivially
      enables definition of abstract class methods.
    * Enumeration API generalized. The new
      betse.util.type.enums.get_member_from_value() function expands the
      functionality provided by the existing
      betse.util.type.enums.get_member_from_name() function to enumeration
      member values.
    * Objects API generalized. The "betse.util.type.obj.objects" submodule
      has been improved to:
      * Enable callers to pass both classes and tuples of classes to
        relevant submodule functions (e.g., die_if_instance()).
      * Provide additional general-purpose getters for dynamically
        retrieving arbitrary object attributes.
    * Threading API generalized. The "betse.util.py.pythread" submodule now
      provides quasi-portable functionality for validating whether the
      active Python interpreter leverages a Global Interpreter Lock (GIL).
    * Weak reference API generalized. The betse.util.py.pyref.refer_weak()
      function now transparently creates weak references to bound methods,
      which require special handling to avoid subtle race conditions.
    * Module API shifted. The prior "betse.util.type.modules" submodule has
      now been renamed to "betse.util.py.pymodule" for orthogonality.
    * Continuous integration (CI) test suite improved. Specifically:
      * Default simulation test expanded. The "betse_cli_sim_default"
        functional test now exercise all simulation subcommands (i.e., seed,
        initialization, and simulation) rather than merely the seed and
        initialization subcommands, reducing the likelihood of edge-case
        computational instabilities.
    * Reference documentation improved. Specifically:
      * Project badges (i.e., flat images synopsizing project health) have
        been externalized from our front-facing "README.rst" document into
        corresponding GitLab-aware project settings, improving both badge
        visibility and aesthetics.
      * The betse.util.py.pyref.proxy_weak() function docstring has been
        significantly revised in accordance with the actual behaviour of the
        underlying weakref.proxy() function.
  • v0.8.4
    BETSE 0.8.4 (Kindlier Kaufmann) released.
    
    Significant changes include:
    
    * Default time step for the cutting event reverted to 0.0 s (i.e., the
      initial time step). While this and prior releases technically permit
      the cutting event to occur at subsequent time steps, doing so
      currently results in fatal exceptions during the "betse plot sim"
      phase and hence is highly discouraged. This issue will be permanently
      resolved in the next stable release of BETSE - to be released shortly.
  • v0.8.3
    BETSE 0.8.3 (Kindly Kaufmann) released.
    
    Significant changes include:
    
    * Dill >= 0.2.8 fundamentally broke backward compatibility by renaming
      the public "dill.dill" submodule to "dill._dill". This stable release
      restores compatibility with dill >= 0.2.3, including dill >= 0.2.8.
    * Mapping API marginally optimized. The
      betse.util.type.mapping.mappings.is_keys() function has been renamed
      for generality to is_key() and has now been optimized for the common
      edge case of testing key containment for a single key.
  • v0.8.2
    BETSE 0.8.2 (Kindest Kaufmann) released.
    
    Significant changes include:
    
    * Segmentation fault handling. Developer-friendly tracebacks are now
      printed to standard error on fatal segmentation faults (i.e.,
      low-level memory access violations by the active Python process).
    * Mapping API generalized. The "betse.util.type.mapping.mappings" API
      has been marginally improved with a bevy of convenience functions
      pertaining to efficient dictionary key removal.
  • v0.8.1
    BETSE 0.8.1 (Kinder Kaufmann) released.
    
    This corrective re-release of the BETSE 0.8.0 bump amends a minor
    (albeit significant) oversight in our installation routine for "bare"
    Python environments (i.e., having no current NumPy installation). In
    short, there's largely nothing to see here.
  • v0.8.0
    BETSE 0.8.0 (Kind Kaufmann) released.
    
    Significant changes include:
    
    * Official Anaconda release. This is the first major release of BETSE to
      officially support our new conda-forge-hosted Anaconda package at:
            https://anaconda.org/conda-forge/betse
    * Installation instructions simplified. Installation instructions in our
      front-facing "README.rst" documentation have been substantially
      simplified to reflect our official Anaconda release.
    * Fast simulation solver added. As an efficient alternative to the usual
      full simulation solver, the newly developed fast solver implements a
      less space- and time-intensive formalism for simulating a subset of
      bioelectric phenomena. Specifically, the fast solver leverages the
      well-known equivalent circuit model to simulate core bioelectricity
      optionally coupled to a gene regulatory network (GRN). As a crude
      heuristic, cursory inspection shows the fast solver to be
      approximately 500—2000% faster than the full solver. Bioelectric
      phenomena supported by the fast solver includes:
      * Transmembrane potential (Vmem).
      * Voltage-sensitive gap junctions.
      * Intracellular currents and fields.
      All other bioelectric phenomena should be assumed to be unsupported.
    * Microtubule density maps and initial-condition alignment maps. These
      maps are user-defined image mask files permitting any simulation to
      preconfigure various properties pertaining to microtubules for that
      simulation's cell cluster.
    * Morris-Lecar ion channels. Ion channels based on the Morris-Lecar
      formalism (including a so-called "slow" Morris-Lecar channel) have now
      been added.
    * Biomolecule degradation activation and inhibition. Degradation of
      arbitrary biomolecules in gene regulatory networks (GRN) may now be
      configured via customary activation and inhibition relations.
    * Surgical interventions generalized. Cell clusters may now be
      surgically cut at any arbitrary time step of a simulation. Previously,
      surgical cuts were only supported at the first time step.
    * "sim-grn" dynamic cutting support. The "betse sim-grn" subcommand
      simulating a gene regulatory network (GRN) isolated from bioelectric
      phenomena now supports all standard surgical interventions.
    * Extracellular matrix (ECM) handling finalized. Main
      electrophysiological properties of our standard planarian model have
      now been successfully matched to experimental observation (e.g., as
      compiled by several prominent planarian theses), validating our
      handling of the extracellular matrix (ECM). These properties include:
      * Transepithelial potential (TEP) level.
      * Transepithelial potential (TEP) under an applied exogenous field.
      * Current magnitude and direction.
    * Lloyd's Voronoi mesh optimization. The pseudo-random Voronoi mesh
      underlying each cell cluster has now been optimized using Lloyd's
      algorithm, improving simulation accuracy and substantially reducing
      the likelihood of mesh errors inducing computational instabilities.
    * Realistic cell polarizability algorithm. An improved algorithm for
      simulating the polarizability of cells has now been implemented.
    * Microtubule Gaussian-noise distribution. Microtubules may now be
      distributed according to a proper Gaussian-noise distribution.
    * Numerous locomotion issues resolved, including:
      * Mass conservation issues in motor protein transport.
      * Gap junction-isolated profiles.
      * Microtubule transport.
      * Laplacians, including:
        * Cell-grid Laplacians.
        * Voronoi grid Laplacians.
    * Comma-separated value (CSV) file exports pipelined. CSV files are now
      exported via our standard pipeline infrastructure much like all other
      exports (e.g., plots, animations), enabling the "plot init" and
      "plot sim" subcommands to trivially support the fast solver.
    * Seed exports generalized. All exports previously created via only the
      "betse plot seed" subcommand are now general-purpose exports created
      via all plotting subcommands (e.g., both the "betse plot init" and
      "betse plot sim" subcommands). These exports includes:
      * "cluster_mask" for the all-cells image mask defining the cell
        cluster shape.
      * "diffusion_extra" for final all-cells extracellular diffusion
        weights (logarithm-scaled). Ignored if extracellular spaces are
        disabled.
      * "gj_connectivity" for the all-cells gap junction connectivity network.
      * "gj_permeability" for final all-cells gap junction relative
        permeabilities.
      * "tissue_cuts" for all-cells tissue and cut profiles.
    * Simulation configuration file documentation improved. To simplify
      usage, the configuration file now documents all simulation features
      required by each type of export -- which usually means the full solver.
    * Simulation configuration creation generalized. Simulation
      configurations created by the "betse config" subcommand now ignore all
      existing files in target subdirectories (e.g., "geo/"), permitting
      users to create multiple configurations in the same directory.
    * Simulation runner callback API. The new
      "betse.science.phase.phasecallbacks" class hierarchy provides a
      general-purpose mechanism for interested callers (notably, the BETSEE
      GUI) to register low-level callbacks with instances of the high-level
      "SimRunner" class responsible for running simulation subcommands and
      hence phases. Currently, these callbacks include methods to receive
      periodic updates on simulation progress. The three principal
      simulation subcommands (i.e., seed, initialization, and simulation)
      now inform callers of incremental progress with respect to work
      performed.
    * Simulation runner API generalized. The SimRunner.__init__() method now
      accepts a "Parameters" object rather than a simulation configuration
      filename, enabling callers (notably, the BETSEE GUI) to reconfigure
      simulation parameters in-memory without writing changes back to disk.
    * Simulation phase API sanitized. The "Simulator.dyna" and
      "SimPhase.dyna" tissue handlers are now synonyms rather than
      duplicates of one another, improving sanity throughout the codebase.
      Although the former has been temporarily preserved, all code requiring
      a tissue handler should now use the canonical "phase.dyna" object.
    * Script API removed. The "betse.script" subpackage has been removed.
      This API had begun to unsafely bit-rot, had remained unused by end
      users for several years, and could no longer be reasonably maintained.
      It is dead.
    * REPL API disabled. The "betse.cli.repl" API has been moved to
      "betse.util.cli.repl" and temporarily disabled until further notice.
      This API had also begun to unsafely bit-rot, but could yield tangible
      benefit at some future date. This API has been preserved in cold
      storage until it can be resuscitated by a future development effort.
      It isn't dead; it's merely sleeping for eternity.
    * Simulation phase requirements API generalized. The existing
      "betse.science.phase.require" subpackage has been refactored to
      leverage immutable sets, permitting two or more lower-level simulation
      phase requirements to be readily composed into a high-level simulation
      phase requirement.
    * KDTree -> cKDTree optimization. For efficiency, all prior usage of the
      pure-Python "KDTree" class has been refactored to leverage the C-based
      "cKDTree" class instead. The latter is a drop-in replacement for the
      former commonly providing speedups in kd-tree queries of up to 4000%.
      Doing so also permits all kd-tree instances to be trivially pickled.
    * Numpy array validation API. The new "betse.lib.numpy.nptest" submodule
      now provides optimized routines for testing and validating Numpy
      arrays -- notably, whether a given array contains one or more
      Not-a-Number (NaN) values or not.
    * Numpy-based image loading API improved. The existing
      "betse.lib.pil.pilnumpy" submodule deserializing arbitrary image files
      into Numpy arrays has now resolved a critical defect pertaining to
      signed versus unsigned data types, reducing the likelihood of
      computational errors on the resulting Numpy arrays.
    * Simulation phase enumerations isolated. For maintainability, the central
      "betse.science.phase.phasecls.SimPhaseKind" enumeration has been shifted
      into the newly created "betse.science.phase.phaseenum" submodule.
    * @log_time_seconds decorator. All simulation subcommand methods (e.g.,
      betse.science.simrunner.SimRunner.seed()) are now decorated by the new
      @log_time_seconds decorator defined by the new
      "betse.util.type.decorator.decprof" submodule, logging wall clock time
      in fractional seconds consumed by each such subcommand.
    * @abstractproperty decorator de-deprecated. Python >= 3.3 deprecated
      the @abc.abstractproperty decorator, for unwise and frankly
      incomprehensible reasons. This release locally reverts this
      deprecation by restoring the @abstractproperty decorator in perpetuity
      under the rubric of the "betse.util.type.decorators.deccls" submodule.
    * @type_check decorator generalized. The @type_check decorator widely used
      throughout the codebase to perform type checking of callable parameters
      now supports tuple annotations containing both class objects and
      fully-qualified classnames, finally finalizing this decorator.
    * Matplotlib >= 2.2.0 compatibility. Matplotlib 2.2.0, the most recently
      released version of matplotlib as of this writing, accidentally broke
      backward compatibility in a horrifying manner. The long-standing
      public "matplotlib.verbose" API was removed in favour of the standard
      "logging" API -- a dramatic upheaval so terrifying it even broke
      PyCharm. This release permanently resolves the breakage on our end by
      dynamically detecting the current version of matplotlib at runtime
      such that:
      * For matplotlib >= 2.2.0, matplotlib logging is configured via the
        standard "logging" API.
      * For matplotlib < 2.2.0, matplotlib logging is configured via the
        non-standard "matplotlib.verbose" API. Since this API is now deprecated
        and expected to be properly removed in six months, this API is only
        safely accessible under older versions of matplotlib.
    * Test suite expanded. Continuous integration (CI) now exercises most
      simulation features with comprehensive tests, including:
      * Fast simulation solver.
      * The "betse sim-grn" subcommand simulating a gene regulatory network
        (GRN) isolated from bioelectric phenomena. Exercised features include:
        * Piggybacking onto an uninitialized, unsimulated cell cluster.
        * Piggybacking onto an initialized, unsimulated cell cluster.
        * Piggybacking onto an initialized, simulated cell cluster.
        * Restarting from the last time step of a prior GRN run.
    * Project logo adopted. The official logo for this release of BETSE is
      an aesthetic flat icon bundled with Maxim Kulikov's Noun
      Project-hosted "Cows" collection, kindly released under the permissive
      BSD-compatible CC BY 3.0 license.
    
  • v0.7.0
    BETSE 0.7.0 (Jamboree Jackson) released.
    
    Significant changes include:
    
    * Dynamic ion channels significantly rewritten. Backward compatibility-breaking
      changes include:
      * *OBSOLETE YAML CONFIGURATION SECTION REMOVED.* Users are encouraged to
        switch to the existing gene regulatory network (GRN) formalism, which
        provides more reliable dynamic channels support. See the "channels"
        subsection of the "general network" section in the default YAML file.
      * Pump- and channel-specific electroosmosis removed. Users are encouraged to
        switch to the existing gene regulatory network (GRN) formalism, which
        provides more reliable electroosmosis support.
      * Configuration changed from conductivity to membrane diffusion constants,
        improving consistency with the remainder of the BETSE codebase.
      * Endoplasmic reticulum (ER) calcium dynamics removed entirely.
      * All existing CaV channels renamed for clarity. (Requested by Cassandra.)
      * Multiple new CaV channels added. (Requested by Cassandra.) These include:
        * N-type CaV 2.2 channel.
      * Channel API generalized for external use outside of BETSE (e.g., Jupyter).
    * Z-offset support in modulator functions. (Requested by Micah Brodskey.)
    * Simulation time updates solved with the backward (implicit) Euler method.
    * Gap junctions modelled with the Goldman-Hodgkin-Katz (GHK) flux equation.
    * Negative concentrations causing "non-conservative" instabilities detected
      during simulation, triggering human-readable fatal exceptions.
    * Positive concentrations updated properly via dynamic dictionaries.
    * "show cells: False" plot output aesthetically improved. (Caveat: this option
      now assumes convert rather than concave cell cluster shapes.)
    * Voronoi grid construction slightly improved.
    * Setuptools >= 38.0.0 compatibility resolved, permitting BETSE to be portably
      installed under all setuptools versions. Setuptools >= 38.0.0 broke backward
      compatibility by prohibiting unordered iterables (e.g., sets) in prominent
      "setup.py" parameters that previously accepted such iterables. *sigh*
    * Image I/O API created. The new "betse.lib.pil" subpackage aggregates all
      functionality specific to Pillow, the PIL-compatible fork serving as this
      application's low-level image processing framework.
    * Expression alias API sanitized, raising human-readable exceptions on erroneous
      access to expression alias values.
    * Directory API sanitized, raising human-readable exceptions from recursive
      directory functions.
    * Object API sanitized, permitting object attributes and methods to be
      dynamically accessed in a "safe" sentinel-based manner.
    * YAML API generalized, enabling all YAML (sub)configurations to be loaded and
      unloaded in a general-purpose manner.
  • v0.6.1
    BETSE 0.6.1 (Illuminous Ito) released.
    
    Significant changes include:
    
    * Trivial woes in the prior release resolved, including:
      * Permission issues during "pip3"-based installation.
      * Rendering issues during reStructuredText (reST) to HTML conversion
        on PyPI.
    * Release instructions improved to avert these woes in the future.
  • v0.6.0
    BETSE 0.6.0 (Illustrious Ito) released.
    
    Significant changes include:
    
    * Core bioelectric features significantly improved, including:
      * Cell polarizability.
      * Charge balance in gene regulatory networks.
      * Electroosmotic flow, leveraging a new electric field formalism
        operating on free charge.
      * Extracellular currents.
      * Extracellular fields, now "...100% consistent with Maxwell's
        Equations to produce long-range electric fields in conjunction with
        (and balancing) ion currents resulting from Nernst-Planck
        electrodiffusive transport."
      * Fluid flow.
      * Flux transfer between the environment and cell cluster.
      * Microtubule alignment.
      * Modulator functions.
      * pH (i.e., hydrogen cations).
      * Voltage-gated calcium channels (e.g., CaV).
      * Voltage-gated potassium channels (e.g., Kv).
    * Gene regulatory network (GRN) features added, including:
      * Piggybacking, permitting GRNs to be efficiently simulated over
        previously simulated simulations without inefficiently resimulating
        underlying physics.
      * Network optimizer, permitting gene regulatory networks to be
        efficiently optimized in isolation.
      * Substances may now be transmembrane components subject to
        electrophoretic or electroosmotic forces acting from the
        extracellular space.
      * Substances may now leverage electrophoretic mobility instead of
        calculating Einstein's coefficient, intended for larger
        macromolecules exhibiting low diffusion but significant mobility
        (in which case the Einstein coefficient is an unsuitable estimate of
        mobility).
      * Substance smoothing reduced significantly (i.e., from 1:2 to 1:100).
    * "betse sim-brn" subcommand removed, obsoleted in entirety by the
      "betse sim-grn" subcommand simulating gene regulatory networks.
    * Two-dimensional Cartesian geometry primitives added, including:
      * Cell cluster (and hence Voronoi diagram) boundaries resected via the
        well-known Sutherland-Hodgman polygon clipping algorithm.
      * Point-line intersection (i.e., intersection of two lines).
      * Point-vector spatiality (i.e., whether arbitrary points reside to the
        right or left of arbitrary vectors).
    * Matplotlib backend detection significantly improved. Specifically, the
      Qt 5-based "Qt5Agg" backend is now BETSE's preferred backend under all
      recent releases of matplotlib (i.e., matplotlib >= 2.0.0). Under older
      releases of matplotlib, the obsolete Tcl/Tk-based "TkAgg" backend
      remains our preferred backend for stability.
    * Transparency automatically enabled in all animation images and video
      for all file formats supporting transparency (e.g., PNG).
    * Large-scale refactoring of simulation features for downstream use by
      BETSEE (the Qt 5-based BETSE GUI), including:
      * Spatial settings (e.g., cell lattice type, computational grid size,
        physical world size).
      * Temporal settings (e.g., time step, sampling rate).
      * Cut profiles.
      * Ion profiles.
      * Tissue profiles.
    * Object-YAML mapping (OYM) API generalized into the
      "betse.lib.yaml" subpackage, providing an elegant pure-Python solution
      (driven by data descriptors) to transparently mapping between
      in-memory high-level Python objects and on-disk low-level YAML files.
    * Backward compatibility API generalized into the new
      "betse.science.config.confcompat" and
      "betse.science.simulate.simcompat" submodules.
    * CLI API generalized into the new "betse.util.cli" subpackage,
      eliminating excess boilerplate in downstream CLI applications.
    * Current working directory (CWD) API generalized into the new
      "betse.util.os.shell.shelldir" submodule.
    * Enumeration API generalized into the new "betse.util.type.enums"
      submodule.
    * Exception handling API generalized into the new
      ""betse.util.io.ioexceptions" submodule.
    * Float API generalized, providing both validation and conversion of
      floating point numbers in either decimal or scientific notation.
    * Pathname API generalized into the new "betse.util.path.pathnames"
      submodule.
    * Textual APIs (e.g., raw string, regular expression, version specifier)
      generalized into the new "betse.util.type.text" subpackage.
    * Matplotlib colormap API generalized into the new
      "betse.lib.matplotlib.mplcolormap" subpackage.
    * Recursive file and directory mtime (modification time) discovery,
      providing efficient inspection and comparison of filesystem contents.
    * Sane default dictionary implementation now provided by the new
      "betse.util.type.mapping.mapcls.DefaultDict" class.
    * Matplotlib >= 1.5.0 now required.
    * Matplotlib >= 2.0.0 now supported.
    * SciPy >= 1.0.0 now supported. Specifically, the third-party image
      processing framework Pillow is now leveraged in lieu of the
      now-deprecated scipy.misc.imread() function for low-level image I/O.
    * Nominal "ruamel.yaml" compatibility. While we have yet to officially
      flip the switch on this alternate Python YAML implementation, BETSE
      now (in theory) supports roundtripped I/O via "ruamel.yaml".
    * Python 3.6 officially supported.
    * Python 3.6 support exercised with Windows-based AppVeyor CI.
    * New functional tests exercising:
      * Backward compatibility with all simulation configurations and
        pickled files produced by BETSE >= 0.5.0.
      * Our default simulation configuration.
  • v0.5.2
    BETSE 0.5.2 (Happiest Hodgkin) released.
    
    This interim point release is both a 0.6.0 release candidate and now the
    oldest version for which backward compatibility is intended to be
    preserved, superceding the recent 0.5.1 release in that respect. Since
    this point release is principally required to validate backward
    compatibility by functional tests locally referencing the corresponding
    Git tag (i.e., "v0.5.2"), no release notes are provided. See the
    following 0.6.0 release for proper release notes.
    
    For similar reasons, no PyPI tarball or third-party packages are
    intended to be produced for this (possibly unstable) point release.
  • v0.5.1
    BETSE 0.5.1 (Happier Hodgkin) released.
    
    This interim point release is both a 0.6.0 release candidate and the
    oldest version for which backward compatibility is intended to be
    preserved. Since this point release is principally required to validate
    backward compatibility by functional tests locally referencing the
    corresponding Git tag (i.e., "v0.5.1"), no release notes are provided.
    See the following 0.6.0 release for proper release notes.
    
    For similar reasons, no PyPI tarball or third-party packages are
    intended to be produced for this (possibly unstable) point release.
  • v0.5.0
    BETSE 0.5.0 (Happy Hodgkin) released.
  • v0.4.1
    BETSE 0.4.1 (Gladder Galvani) released.
  • v0.4.0
    BETSE 0.4.0 (Glad Galvani).
  • v0.3.0
    d7687e75 · BETSE 0.3.0 stabilized. ·
    BETSE 0.3.0 official release.