From 31e85c2f15ba7483a52a017dfc23845b14dd71e6 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 15:35:05 +0100 Subject: [PATCH 01/19] moving the jvm start functions to its own directory --- pixi.lock | 15 ++++++++++++++- pyproject.toml | 1 + src/pythermogis/__init__.py | 12 +----------- src/pythermogis/jvm/__init__.py | 0 .../{thermogis_classes => jvm}/jvm_start.py | 0 .../thermogis_classes/potential_properties.py | 2 +- .../thermogis_classes/utc_properties.py | 2 +- 7 files changed, 18 insertions(+), 14 deletions(-) create mode 100644 src/pythermogis/jvm/__init__.py rename src/pythermogis/{thermogis_classes => jvm}/jvm_start.py (100%) diff --git a/pixi.lock b/pixi.lock index 61f5e03..156e292 100644 --- a/pixi.lock +++ b/pixi.lock @@ -74,6 +74,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.6.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/install-jdk-1.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.1-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.functools-4.1.0-pyhd8ed1ab_0.conda @@ -321,6 +322,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/importlib-metadata-8.6.1-pyha770c72_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/importlib_resources-6.5.2-pyhd8ed1ab_0.conda - conda: https://conda.anaconda.org/conda-forge/noarch/iniconfig-2.0.0-pyhd8ed1ab_1.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/install-jdk-1.1.0-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.2.1-h57928b3_1083.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.classes-3.4.0-pyhd8ed1ab_2.conda - conda: https://conda.anaconda.org/conda-forge/noarch/jaraco.context-6.0.1-pyhd8ed1ab_0.conda @@ -1989,6 +1991,17 @@ packages: - pkg:pypi/iniconfig?source=hash-mapping size: 11474 timestamp: 1733223232820 +- conda: https://conda.anaconda.org/conda-forge/noarch/install-jdk-1.1.0-pyhd8ed1ab_1.conda + sha256: 3bfea87bc5ab5c310c64f4c03249f2eea98b20764f5160be0089f02c9144de97 + md5: 247673a294ba3bd0efd5c201db70f908 + depends: + - python >=3.9,<4.0 + license: MIT + license_family: MIT + purls: + - pkg:pypi/install-jdk?source=hash-mapping + size: 19322 + timestamp: 1735255158126 - conda: https://conda.anaconda.org/conda-forge/win-64/intel-openmp-2024.2.1-h57928b3_1083.conda sha256: 0fd2b0b84c854029041b0ede8f4c2369242ee92acc0092f8407b1fe9238a8209 md5: 2d89243bfb53652c182a7c73182cce4f @@ -4921,7 +4934,7 @@ packages: - pypi: ./ name: pythermogis version: 1.2.4 - sha256: 41970125f848a057eda9f00cac0c2046df6c0b149f67081432922484a4320b9d + sha256: eae3996f5fe84ef20311f65a80e622778548d56fc71970248db30c9c4090c0cc requires_dist: - jpype1>=1.5.2,<2 - xarray==2024.9.0.* diff --git a/pyproject.toml b/pyproject.toml index 4054d06..61a6da9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -75,6 +75,7 @@ pre-commit = ">=4.3.0,<5" python-dotenv = ">=1.2.1,<2" numba = ">=0.63.1,<0.64" ruff = ">=0.14.10,<0.15" +install-jdk = ">=1.1.0,<2" [tool.ruff] line-length = 88 diff --git a/src/pythermogis/__init__.py b/src/pythermogis/__init__.py index 6d77ee8..8b13789 100644 --- a/src/pythermogis/__init__.py +++ b/src/pythermogis/__init__.py @@ -1,11 +1 @@ -from pythermogis.thermogis_classes.jvm_start import * -from pythermogis.thermogis_classes.doublet import * -from pythermogis.thermogis_classes.utc_properties import * -from pythermogis.transmissivity.calculate_thick_perm_trans import * -from pythermogis.tables.utc_properties_table import * -from pythermogis.postprocessing.pos import * -from pythermogis.doublet_simulation.deterministic_doublet import * -from pythermogis.doublet_simulation.stochastic_doublet import * -from pythermogis.plotting.plot_exceedance import plot_exceedance -from pythermogis.dask_utils.auto_chunk import auto_chunk_dataset -from pythermogis.dask_utils.assess_optimal_chunk_size import assess_optimal_chunk_size + diff --git a/src/pythermogis/jvm/__init__.py b/src/pythermogis/jvm/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/src/pythermogis/thermogis_classes/jvm_start.py b/src/pythermogis/jvm/jvm_start.py similarity index 100% rename from src/pythermogis/thermogis_classes/jvm_start.py rename to src/pythermogis/jvm/jvm_start.py diff --git a/src/pythermogis/thermogis_classes/potential_properties.py b/src/pythermogis/thermogis_classes/potential_properties.py index db3afee..c14363a 100644 --- a/src/pythermogis/thermogis_classes/potential_properties.py +++ b/src/pythermogis/thermogis_classes/potential_properties.py @@ -1,6 +1,6 @@ from jpype import JClass -from pythermogis.thermogis_classes.jvm_start import start_jvm +from jvm.jvm_start import start_jvm def instantiate_potential_properties_builder() -> JClass: diff --git a/src/pythermogis/thermogis_classes/utc_properties.py b/src/pythermogis/thermogis_classes/utc_properties.py index 9a641d2..85123ba 100644 --- a/src/pythermogis/thermogis_classes/utc_properties.py +++ b/src/pythermogis/thermogis_classes/utc_properties.py @@ -3,7 +3,7 @@ import typing as t import xml.etree.ElementTree as ET from jpype import JClass -from pythermogis.thermogis_classes.jvm_start import start_jvm +from jvm.jvm_start import start_jvm def instantiate_utc_properties_from_xml(xml_file: str | Path) -> JClass: -- GitLab From a4d656ab65e08554e4695ab90c0faada7e891822 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 15:46:29 +0100 Subject: [PATCH 02/19] Playing with installing JVM into the package --- .gitignore | 1 + .gitlab-ci.yml | 3 --- src/pythermogis/__init__.py | 12 +++++++++++- src/pythermogis/constants.py | 2 ++ src/pythermogis/jvm/jvm_start.py | 17 ++++++++++++++--- tests/java/test_java_installation.py | 8 ++++++-- 6 files changed, 34 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index 3790500..c5ddeb5 100644 --- a/.gitignore +++ b/.gitignore @@ -10,3 +10,4 @@ dist tests/resources/test_output +/src/pythermogis/jvm/JVM17 \ No newline at end of file diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index dd6a776..0997d6d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,9 +12,6 @@ Run tests: - export TZ=Europe/Amsterdam - ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - apt-get update - - apt-get install -y build-essential gcc tk openjdk-17-jdk - - export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64 - - export PATH=$JAVA_HOME/bin:$PATH - pixi install - pixi run pytest -rx tests/ - rm -rf /var/lib/apt/lists/* diff --git a/src/pythermogis/__init__.py b/src/pythermogis/__init__.py index 8b13789..54e8577 100644 --- a/src/pythermogis/__init__.py +++ b/src/pythermogis/__init__.py @@ -1 +1,11 @@ - +from pythermogis.jvm.jvm_start import * +from pythermogis.thermogis_classes.doublet import * +from pythermogis.thermogis_classes.utc_properties import * +from pythermogis.transmissivity.calculate_thick_perm_trans import * +from pythermogis.tables.utc_properties_table import * +from pythermogis.postprocessing.pos import * +from pythermogis.doublet_simulation.deterministic_doublet import * +from pythermogis.doublet_simulation.stochastic_doublet import * +from pythermogis.plotting.plot_exceedance import plot_exceedance +from pythermogis.dask_utils.auto_chunk import auto_chunk_dataset +from pythermogis.dask_utils.assess_optimal_chunk_size import assess_optimal_chunk_size diff --git a/src/pythermogis/constants.py b/src/pythermogis/constants.py index 1b0c72f..e7f5ad6 100644 --- a/src/pythermogis/constants.py +++ b/src/pythermogis/constants.py @@ -3,3 +3,5 @@ from pathlib import Path THERMOGIS_JAR_PATH = ( Path(__file__).parent / "thermogis_jar" / "thermogis-1.7.0-shaded.jar" ) + +JVM17_PATH = Path(__file__).parent / "jvm" / "JVM17" \ No newline at end of file diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index cabbdb7..06e2e3a 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -1,9 +1,10 @@ import os import jpype import faulthandler - +import jdk from dotenv import load_dotenv -from pythermogis.constants import THERMOGIS_JAR_PATH +from pythermogis.constants import THERMOGIS_JAR_PATH, JVM17_PATH + load_dotenv() def get_thermogis_jar_path() -> str: @@ -15,6 +16,16 @@ def get_thermogis_jar_path() -> str: return str(THERMOGIS_JAR_PATH) +def install_jvm(): + """ + If no JVM17 installed, use the jdk package to install JVM17 + :return: + """ + if not JVM17_PATH.exists(): + # Installs a Corretto build of Java 17 JDK. Defualt vendor is Adoptium + jdk.install("17", vendor="Corretto", path=JVM17_PATH) + + def start_jvm(): """ To use the JPype package a java .jar file has to be instantiated with a java virtual machine (jvm) @@ -27,7 +38,7 @@ def start_jvm(): faulthandler.disable() # automatically looks up the java version in JAVA_HOME - jpype.startJVM(classpath=[get_thermogis_jar_path()]) + jpype.startJVM(JVM17_PATH, classpath=[get_thermogis_jar_path()]) def close_jvm(): """ diff --git a/tests/java/test_java_installation.py b/tests/java/test_java_installation.py index 1dea75f..233af23 100644 --- a/tests/java/test_java_installation.py +++ b/tests/java/test_java_installation.py @@ -1,4 +1,5 @@ -from pythermogis import print_java_path, print_thermogis_jar_path, start_jvm +from pythermogis import print_java_path, print_thermogis_jar_path, start_jvm, \ + install_jvm def test_JVM_start(): @@ -6,4 +7,7 @@ def test_JVM_start(): def test_JVM_JAR_print(): print_java_path() - print_thermogis_jar_path() \ No newline at end of file + print_thermogis_jar_path() + +def test_JVM_install(): + install_jvm() \ No newline at end of file -- GitLab From 5725a63bc93a6b050e8a3d49fc599964777c4c98 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 16:05:33 +0100 Subject: [PATCH 03/19] Playing with installing JVM into the package --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0997d6d..2043acf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -12,6 +12,7 @@ Run tests: - export TZ=Europe/Amsterdam - ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone - apt-get update + - apt-get install -y build-essential gcc tk - pixi install - pixi run pytest -rx tests/ - rm -rf /var/lib/apt/lists/* -- GitLab From 8b493e5e3a938476cb90d38bbb92a4e74a21e718 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 16:25:40 +0100 Subject: [PATCH 04/19] Playing with installing JVM into the package --- pyproject.toml | 5 +++-- src/pythermogis/jvm/jvm_start.py | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 61a6da9..329d605 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,8 @@ dependencies = [ "build>=1.2.2.post1,<2", "pygridsio>=1.0,<2.0", "python-dotenv>=1.2.1,<2", - "dask>=2025.5.1,<2026" + "dask>=2025.5.1,<2026", + "install-jdk==1.1.0" ] @@ -75,7 +76,7 @@ pre-commit = ">=4.3.0,<5" python-dotenv = ">=1.2.1,<2" numba = ">=0.63.1,<0.64" ruff = ">=0.14.10,<0.15" -install-jdk = ">=1.1.0,<2" +install-jdk = "==1.1.0" [tool.ruff] line-length = 88 diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 06e2e3a..5486705 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -5,8 +5,6 @@ import jdk from dotenv import load_dotenv from pythermogis.constants import THERMOGIS_JAR_PATH, JVM17_PATH -load_dotenv() - def get_thermogis_jar_path() -> str: """ From within thermogis, find the thermogis-jar, return the path to the ThermoGIS Jar @@ -15,15 +13,24 @@ def get_thermogis_jar_path() -> str: raise FileNotFoundError(f"Jar file not found at {THERMOGIS_JAR_PATH}.") return str(THERMOGIS_JAR_PATH) +def get_jvm17_path() -> str: + jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] + if len(jdk_dirs) == 0: + print(f"JVM17 not installed at: {JVM17_PATH}. Installing automatically.\nThis will take some time but will be only run once.") + install_jvm() + jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] + + jdk_dll = jdk_dirs[0] / "bin" / "server" / "jvm.dll" + return str(jdk_dll) + def install_jvm(): """ If no JVM17 installed, use the jdk package to install JVM17 :return: """ - if not JVM17_PATH.exists(): - # Installs a Corretto build of Java 17 JDK. Defualt vendor is Adoptium - jdk.install("17", vendor="Corretto", path=JVM17_PATH) + # Installs a Corretto build of Java 17 JDK. Defualt vendor is Adoptium + jdk.install("17", vendor="Corretto", path=JVM17_PATH) def start_jvm(): @@ -38,7 +45,7 @@ def start_jvm(): faulthandler.disable() # automatically looks up the java version in JAVA_HOME - jpype.startJVM(JVM17_PATH, classpath=[get_thermogis_jar_path()]) + jpype.startJVM(get_jvm17_path(), classpath=[get_thermogis_jar_path()]) def close_jvm(): """ -- GitLab From d50ef4599a18152845e7b8d64f6055f1f4649cf1 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 16:27:36 +0100 Subject: [PATCH 05/19] Playing with installing JVM into the package --- tests/java/test_java_installation.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/tests/java/test_java_installation.py b/tests/java/test_java_installation.py index 233af23..ee532a9 100644 --- a/tests/java/test_java_installation.py +++ b/tests/java/test_java_installation.py @@ -7,7 +7,4 @@ def test_JVM_start(): def test_JVM_JAR_print(): print_java_path() - print_thermogis_jar_path() - -def test_JVM_install(): - install_jvm() \ No newline at end of file + print_thermogis_jar_path() \ No newline at end of file -- GitLab From 00e629aa82e453dc448bd9e62486a48884f3d7fa Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 16:29:17 +0100 Subject: [PATCH 06/19] Playing with installing JVM into the package --- src/pythermogis/jvm/jvm_start.py | 15 +++++---------- tests/java/test_java_installation.py | 3 +-- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 5486705..9de2b0a 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -14,12 +14,16 @@ def get_thermogis_jar_path() -> str: return str(THERMOGIS_JAR_PATH) def get_jvm17_path() -> str: + # Automatically detect if there is a JVM installed at JVM17_PATH jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] + if len(jdk_dirs) == 0: + # if not, then install one and update the jdk_dirs path print(f"JVM17 not installed at: {JVM17_PATH}. Installing automatically.\nThis will take some time but will be only run once.") install_jvm() jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] + # point to the installed jvm.dll for use by JPYPE jdk_dll = jdk_dirs[0] / "bin" / "server" / "jvm.dll" return str(jdk_dll) @@ -47,21 +51,12 @@ def start_jvm(): # automatically looks up the java version in JAVA_HOME jpype.startJVM(get_jvm17_path(), classpath=[get_thermogis_jar_path()]) -def close_jvm(): - """ - To use the JPype package a java .jar file has to be instantiated with a java virtual machine (jvm) - This method ensures a clean shutdown of the jvm - :return: - """ - if jpype.isJVMStarted(): - jpype.shutdownJVM() - def print_java_path(): """ This method prints the path to the JVM being used :return: """ - print(os.getenv("JAVA_HOME")) + print(get_jvm17_path) def print_thermogis_jar_path(): """ diff --git a/tests/java/test_java_installation.py b/tests/java/test_java_installation.py index ee532a9..1dea75f 100644 --- a/tests/java/test_java_installation.py +++ b/tests/java/test_java_installation.py @@ -1,5 +1,4 @@ -from pythermogis import print_java_path, print_thermogis_jar_path, start_jvm, \ - install_jvm +from pythermogis import print_java_path, print_thermogis_jar_path, start_jvm def test_JVM_start(): -- GitLab From b6fc42acf74f52f1cea5cd6c31b9ee103a7f5638 Mon Sep 17 00:00:00 2001 From: bretth Date: Fri, 23 Jan 2026 16:33:19 +0100 Subject: [PATCH 07/19] Playing with installing JVM into the package --- src/pythermogis/thermogis_classes/utc_properties.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pythermogis/thermogis_classes/utc_properties.py b/src/pythermogis/thermogis_classes/utc_properties.py index 85123ba..50308d4 100644 --- a/src/pythermogis/thermogis_classes/utc_properties.py +++ b/src/pythermogis/thermogis_classes/utc_properties.py @@ -1,9 +1,10 @@ -from pathlib import Path import typing as t import xml.etree.ElementTree as ET +from pathlib import Path + from jpype import JClass -from jvm.jvm_start import start_jvm +from pythermogis import start_jvm def instantiate_utc_properties_from_xml(xml_file: str | Path) -> JClass: -- GitLab From 08d66522eda1f68be2ebb15252e070fbcfc3c258 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 10:32:15 +0100 Subject: [PATCH 08/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/constants.py | 3 +- src/pythermogis/jvm/jvm_start.py | 85 +++++++++---------- .../thermogis_classes/potential_properties.py | 2 +- tests/java/test_java_installation.py | 10 ++- 4 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/pythermogis/constants.py b/src/pythermogis/constants.py index e7f5ad6..42f1303 100644 --- a/src/pythermogis/constants.py +++ b/src/pythermogis/constants.py @@ -4,4 +4,5 @@ THERMOGIS_JAR_PATH = ( Path(__file__).parent / "thermogis_jar" / "thermogis-1.7.0-shaded.jar" ) -JVM17_PATH = Path(__file__).parent / "jvm" / "JVM17" \ No newline at end of file +JVM17_PATH = Path(__file__).parent / "jvm" / "JVM17" +JVM17_DLL_PATH = JVM17_PATH / "jdk17" / "bin" / "server" / "jvm.dll" \ No newline at end of file diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 9de2b0a..0b448e1 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -1,66 +1,59 @@ -import os -import jpype import faulthandler -import jdk -from dotenv import load_dotenv -from pythermogis.constants import THERMOGIS_JAR_PATH, JVM17_PATH - -def get_thermogis_jar_path() -> str: - """ - From within thermogis, find the thermogis-jar, return the path to the ThermoGIS Jar - """ - if not THERMOGIS_JAR_PATH.exists(): - raise FileNotFoundError(f"Jar file not found at {THERMOGIS_JAR_PATH}.") - return str(THERMOGIS_JAR_PATH) -def get_jvm17_path() -> str: - # Automatically detect if there is a JVM installed at JVM17_PATH - jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] - - if len(jdk_dirs) == 0: - # if not, then install one and update the jdk_dirs path - print(f"JVM17 not installed at: {JVM17_PATH}. Installing automatically.\nThis will take some time but will be only run once.") - install_jvm() - jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()] +import jdk +import jpype - # point to the installed jvm.dll for use by JPYPE - jdk_dll = jdk_dirs[0] / "bin" / "server" / "jvm.dll" - return str(jdk_dll) +from pythermogis.constants import JVM17_DLL_PATH, JVM17_PATH, THERMOGIS_JAR_PATH def install_jvm(): """ - If no JVM17 installed, use the jdk package to install JVM17 + Installs a Corretto build of Java 17 JDK, renames it from jdk17_XX_XX to jdk17 + and checks that the executable exists. + :return: """ - # Installs a Corretto build of Java 17 JDK. Defualt vendor is Adoptium + print("Installing Java Virtual Machine, this can take some time but will only be " + "run once.") + # Installs a Corretto build of Java 17 JDK jdk.install("17", vendor="Corretto", path=JVM17_PATH) + # search for the path of the installed JDK, it can be different depending on the + # version number + jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()][0] + + # rename to the standard path to be used throughout pythermogis + jdk_dirs.rename(JVM17_PATH / "jdk17") + + if not JVM17_DLL_PATH.exists(): + raise FileExistsError( + f"Java virtual machine executable not found at :{JVM17_DLL_PATH}" + ) + def start_jvm(): """ - To use the JPype package a java .jar file has to be instantiated with a java virtual machine (jvm) + To use the JPype package a java .jar file has to be instantiated with a java virtual + machine (jvm). This method ensures a clean startup of the jvm packaged with this repo :return: """ - if not jpype.isJVMStarted(): - # when running pytest with jpype a "Windows fatal exception" is thrown which in reality has no affect on the outcome or performance. - # the current workaround from the jpype package is to disable the pytest faulthandler. (This will not prevent python or java errors in the test). - faulthandler.disable() + if jpype.isJVMStarted(): + return - # automatically looks up the java version in JAVA_HOME - jpype.startJVM(get_jvm17_path(), classpath=[get_thermogis_jar_path()]) + # when running pytest with jpype a "Windows fatal exception" is thrown which in + # reality has no affect on the outcome or performance. + # the current workaround from the jpype package is to disable the pytest + # faulthandler. (This will not prevent python or java errors in the test). + faulthandler.disable() -def print_java_path(): - """ - This method prints the path to the JVM being used - :return: - """ - print(get_jvm17_path) + if not JVM17_DLL_PATH.exists(): + # If the JVM has not been installed (ie. JVM17_DLL_PATH does not exist, then + # install using the install-jdk package + install_jvm() -def print_thermogis_jar_path(): - """ - This method prints the path to the Thermogis Jar being used - :return: - """ - print(get_thermogis_jar_path()) + if not THERMOGIS_JAR_PATH.exists(): + raise FileNotFoundError(f"Jar file not found at {THERMOGIS_JAR_PATH}.") + + # starts the java virtual machine and loads the thermogis classes + jpype.startJVM(str(JVM17_DLL_PATH), classpath=[str(THERMOGIS_JAR_PATH)]) diff --git a/src/pythermogis/thermogis_classes/potential_properties.py b/src/pythermogis/thermogis_classes/potential_properties.py index c14363a..5f514dd 100644 --- a/src/pythermogis/thermogis_classes/potential_properties.py +++ b/src/pythermogis/thermogis_classes/potential_properties.py @@ -1,6 +1,6 @@ from jpype import JClass -from jvm.jvm_start import start_jvm +from pythermogis import start_jvm def instantiate_potential_properties_builder() -> JClass: diff --git a/tests/java/test_java_installation.py b/tests/java/test_java_installation.py index 1dea75f..30e0b35 100644 --- a/tests/java/test_java_installation.py +++ b/tests/java/test_java_installation.py @@ -1,9 +1,13 @@ -from pythermogis import print_java_path, print_thermogis_jar_path, start_jvm +from pythermogis import ( + start_jvm, + JVM17_DLL_PATH, + THERMOGIS_JAR_PATH, +) def test_JVM_start(): start_jvm() def test_JVM_JAR_print(): - print_java_path() - print_thermogis_jar_path() \ No newline at end of file + print(JVM17_DLL_PATH) + print(THERMOGIS_JAR_PATH) \ No newline at end of file -- GitLab From f4ec99ba6b3ea804de0b9bf41954fb7ac5450cb0 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:01:14 +0100 Subject: [PATCH 09/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 0b448e1..054b217 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -20,6 +20,7 @@ def install_jvm(): # search for the path of the installed JDK, it can be different depending on the # version number + print(JVM17_PATH.glob("*") ) jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()][0] # rename to the standard path to be used throughout pythermogis -- GitLab From b3b15843e7267111adbe07a98465ad752aa72e49 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:06:02 +0100 Subject: [PATCH 10/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 054b217..bdfa0ae 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -20,7 +20,7 @@ def install_jvm(): # search for the path of the installed JDK, it can be different depending on the # version number - print(JVM17_PATH.glob("*") ) + print(list(JVM17_PATH.glob("*"))) jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()][0] # rename to the standard path to be used throughout pythermogis -- GitLab From 41915567aba2165b8102c0f5ca01536f80ba3245 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:27:20 +0100 Subject: [PATCH 11/19] Cleaning up how the java virtual machine is installed via the code --- .gitlab-ci.yml | 2 +- pixi.lock | 3 ++- src/pythermogis/jvm/jvm_start.py | 13 ++++++++++--- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 2043acf..9d3094b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ Run tests: - apt-get update - apt-get install -y build-essential gcc tk - pixi install - - pixi run pytest -rx tests/ + - pixi run pytest -rx tests/java/test_java_installation.py - rm -rf /var/lib/apt/lists/* only: - main diff --git a/pixi.lock b/pixi.lock index 156e292..d771c6c 100644 --- a/pixi.lock +++ b/pixi.lock @@ -4934,7 +4934,7 @@ packages: - pypi: ./ name: pythermogis version: 1.2.4 - sha256: eae3996f5fe84ef20311f65a80e622778548d56fc71970248db30c9c4090c0cc + sha256: 4406d3c4da3a9e6ee46a39b7ce7b61063e676db495638f1f9d992ac174589913 requires_dist: - jpype1>=1.5.2,<2 - xarray==2024.9.0.* @@ -4944,6 +4944,7 @@ packages: - pygridsio>=1.0,<2.0 - python-dotenv>=1.2.1,<2 - dask>=2025.5.1,<2026 + - install-jdk==1.1.0 requires_python: '>=3.11' editable: true - conda: https://conda.anaconda.org/conda-forge/linux-64/python-3.13.3-hf636f53_101_cp313.conda diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index bdfa0ae..6895ceb 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -2,6 +2,7 @@ import faulthandler import jdk import jpype +import shutil from pythermogis.constants import JVM17_DLL_PATH, JVM17_PATH, THERMOGIS_JAR_PATH @@ -13,15 +14,21 @@ def install_jvm(): :return: """ - print("Installing Java Virtual Machine, this can take some time but will only be " - "run once.") + print( + "Installing Java Virtual Machine, this can take some time but will only be " + "run once." + ) + # quick check to delete the contents of path first + shutil.rmtree(JVM17_PATH) + JVM17_PATH.mkdir(parents=True, exist_ok=True) + # Installs a Corretto build of Java 17 JDK jdk.install("17", vendor="Corretto", path=JVM17_PATH) # search for the path of the installed JDK, it can be different depending on the # version number print(list(JVM17_PATH.glob("*"))) - jdk_dirs = [p for p in JVM17_PATH.glob("jdk17*") if p.is_dir()][0] + jdk_dirs = [p for p in JVM17_PATH.glob("*") if p.is_dir()][0] # rename to the standard path to be used throughout pythermogis jdk_dirs.rename(JVM17_PATH / "jdk17") -- GitLab From db16e44a6d551d9557092cce3488ae21be530ccc Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:32:26 +0100 Subject: [PATCH 12/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 6895ceb..1067ea9 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -18,8 +18,12 @@ def install_jvm(): "Installing Java Virtual Machine, this can take some time but will only be " "run once." ) - # quick check to delete the contents of path first - shutil.rmtree(JVM17_PATH) + + # delete path first to ensure fresh installation + if JVM17_PATH.exists(): + shutil.rmtree(JVM17_PATH) + + # create path JVM17_PATH.mkdir(parents=True, exist_ok=True) # Installs a Corretto build of Java 17 JDK -- GitLab From 001ff8e81530e7daf4020b39bd6bc68937ec1e59 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:34:56 +0100 Subject: [PATCH 13/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 1067ea9..a1c9c70 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -33,9 +33,11 @@ def install_jvm(): # version number print(list(JVM17_PATH.glob("*"))) jdk_dirs = [p for p in JVM17_PATH.glob("*") if p.is_dir()][0] - + print(jdk_dirs) # rename to the standard path to be used throughout pythermogis jdk_dirs.rename(JVM17_PATH / "jdk17") + print(jdk_dirs) + print(list(jdk_dirs.glob("*"))) if not JVM17_DLL_PATH.exists(): raise FileExistsError( -- GitLab From 6a90dcceb18eb2a7ffad7ca217f2f8b60962862e Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:42:32 +0100 Subject: [PATCH 14/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index a1c9c70..fca11e1 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -34,8 +34,10 @@ def install_jvm(): print(list(JVM17_PATH.glob("*"))) jdk_dirs = [p for p in JVM17_PATH.glob("*") if p.is_dir()][0] print(jdk_dirs) + # rename to the standard path to be used throughout pythermogis - jdk_dirs.rename(JVM17_PATH / "jdk17") + shutil.move(jdk_dirs, JVM17_PATH / "jdk17") + print(jdk_dirs) print(list(jdk_dirs.glob("*"))) -- GitLab From 3987831cd0b15fc6306a456846e553ee7c3c2b1d Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:43:09 +0100 Subject: [PATCH 15/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/jvm/jvm_start.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index fca11e1..66455fd 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -38,8 +38,7 @@ def install_jvm(): # rename to the standard path to be used throughout pythermogis shutil.move(jdk_dirs, JVM17_PATH / "jdk17") - print(jdk_dirs) - print(list(jdk_dirs.glob("*"))) + print(list(JVM17_PATH.glob("*"))) if not JVM17_DLL_PATH.exists(): raise FileExistsError( -- GitLab From 2cbf6f451c54a10bb89346e0cf8549f9909ee3f7 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 11:59:35 +0100 Subject: [PATCH 16/19] Cleaning up how the java virtual machine is installed via the code --- src/pythermogis/constants.py | 12 +++++++++++- src/pythermogis/jvm/jvm_start.py | 5 +---- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/src/pythermogis/constants.py b/src/pythermogis/constants.py index 42f1303..34cb3e9 100644 --- a/src/pythermogis/constants.py +++ b/src/pythermogis/constants.py @@ -1,8 +1,18 @@ from pathlib import Path +import platform THERMOGIS_JAR_PATH = ( Path(__file__).parent / "thermogis_jar" / "thermogis-1.7.0-shaded.jar" ) JVM17_PATH = Path(__file__).parent / "jvm" / "JVM17" -JVM17_DLL_PATH = JVM17_PATH / "jdk17" / "bin" / "server" / "jvm.dll" \ No newline at end of file + +os_name = platform.system() +if os_name == "Linux": + JVM17_DLL_PATH = JVM17_PATH / "jdk17" / "lib" / "server" / "libjvm.so" +elif os_name == "Darwin": # mac + JVM17_DLL_PATH = JVM17_PATH / "jdk17" / "lib" / "server" / "libjvm.dylib" +elif os_name == "Windows": + JVM17_DLL_PATH = JVM17_PATH / "jdk17" / "bin" / "server" / "jvm.dll" +else: + raise SyntaxError(f"Operating System not supported: {os_name}") diff --git a/src/pythermogis/jvm/jvm_start.py b/src/pythermogis/jvm/jvm_start.py index 66455fd..6425214 100644 --- a/src/pythermogis/jvm/jvm_start.py +++ b/src/pythermogis/jvm/jvm_start.py @@ -31,17 +31,14 @@ def install_jvm(): # search for the path of the installed JDK, it can be different depending on the # version number - print(list(JVM17_PATH.glob("*"))) jdk_dirs = [p for p in JVM17_PATH.glob("*") if p.is_dir()][0] - print(jdk_dirs) # rename to the standard path to be used throughout pythermogis shutil.move(jdk_dirs, JVM17_PATH / "jdk17") - print(list(JVM17_PATH.glob("*"))) - if not JVM17_DLL_PATH.exists(): raise FileExistsError( + f"Installation of JVM unsuccessful." f"Java virtual machine executable not found at :{JVM17_DLL_PATH}" ) -- GitLab From 697d67b0a336a3b1ffc16354dd1be18ea1920ed9 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 13:09:37 +0100 Subject: [PATCH 17/19] fixing the pipeline --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9d3094b..2043acf 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,7 +14,7 @@ Run tests: - apt-get update - apt-get install -y build-essential gcc tk - pixi install - - pixi run pytest -rx tests/java/test_java_installation.py + - pixi run pytest -rx tests/ - rm -rf /var/lib/apt/lists/* only: - main -- GitLab From ea93c435da573733f6798f3cd53a47d486edc6a2 Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 13:21:23 +0100 Subject: [PATCH 18/19] improving the installation guide --- README.md | 34 +++++++++------------------------- docs/install/install.md | 37 +++++++++++++++++-------------------- 2 files changed, 26 insertions(+), 45 deletions(-) diff --git a/README.md b/README.md index f771aa8..a282306 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Read the full documenation [here](https://pythermogis-15909e.ci.tno.nl/). -If you wish to build the documentation locally, follow the installation steps and run: +If you wish to build the documentation locally, follow the installation from source step and run: ```bash pixi run mkdocs serve @@ -15,33 +15,18 @@ pixi run mkdocs serve # Installation pythermogis has been designed to be used as a python package you import into your own python projects. -It works by creating a python API access to the ThermoGIS techno-economic application, which is written in Java. -Because of this dependency you need to Install a Java 17 VM. +It works by creating a python API access to the Core ThermoGIS techno-economic application, which is written in Java. -### 1. Install Java 17 +The ThermoGIS techno-economic Core application is packaged within pythermogis, this is the reason the package is quite large (~150mb). +Additionally the first time you run a simulation with pythermogis, a Java 17 Virtual machine (JVM) will be automatically installed (using the package [install-jdk](https://pypi.org/project/install-jdk/)). -This package requires a Java 17 VM (we recommend using [Amazon Corretto 17](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html)). +The Java 17 virtual machine is an additional ~350mb so there should be at least 500mb of space on any machine you install pythermogis on (and preferably more). -*(You can find the JAR in this repository's resources folder: /resources/thermogis_jar)* +Installation of the JVM can take some time (0.5 - 2 minutes) depending on the speed of your internet connection, but will only be done once per pythermogis installation. -### 2. Ensure JAVA_HOME is set +pythermogis has been tested on Windows and Linux operating systems. -When installing the Java 17 Virtual Machine (JVM), a global environment variable _should_ have been set: `JAVA_HOME`. This stores the path to the JVM that was installed in step 1 and enables pythermogis to read the core Java code. - -If, for some reason, this was not done during installation you can either set it yourself or create a ``.env`` file in your project root folder. - -This `.env` file should contain the following variable: - -- `JAVA_HOME`: Path to the Java 17 installation - *(e.g., on Windows: `C:\Program Files\Amazon Corretto\jdk17.0.0_0`)* - - -Example `.env` contents (The specific path could be different depending on your OS, or file architecture): -``` -JAVA_HOME = C:\Program Files \Amazon Corretto\jdk17.0.0_0 -``` - -### 3. Import pythermogis into your own python projects +### 1. Import pythermogis into your own python projects You can use pip to install the package directly from the gitlab project: ``` @@ -58,7 +43,7 @@ If you are using uv as your dependency manager: uv add pythermogis --default-index https://ci.tno.nl/gitlab/api/v4/projects/18271/packages/pypi/simple ``` -### Installation from source +### 2. Installation from source Clone and install from source with Pixi: @@ -67,7 +52,6 @@ git clone git@ci.tno.nl:ags_public/pythermogis.git cd pythermogis pixi install ``` -(Make sure you have followed step 1 and 2: installing a Java 17 VM) --- diff --git a/docs/install/install.md b/docs/install/install.md index 128cefc..8c293fc 100644 --- a/docs/install/install.md +++ b/docs/install/install.md @@ -1,33 +1,31 @@ # Installation +**pythermogis** is a Python package that provides API access to the [ThermoGIS](https://www.thermogis.nl/en) doublet simulations and economic calculations, ThermoGIS is developed and maintained by the [Geological Survey of the Netherlands](https://www.geologischedienst.nl/en/) which is part of [TNO](https://www.tno.nl/en/), additionally, pythermogis was also partially developed by and for the [GoForward](https://go-forward-project.eu/) project. -pythermogis has been designed to be used as a python package you import into your own python projects. -It works by creating a python API access to the ThermoGIS techno-economic application, which is written in Java. -Because of this dependency you need to Install a Java 17 VM. - -### 1. Install Java 17 +Read the full documenation [here](https://pythermogis-15909e.ci.tno.nl/). -This package requires a Java 17 VM (we recommend using [Amazon Corretto 17](https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/downloads-list.html)). +If you wish to build the documentation locally, follow the installation from source step and run: -*(You can find the JAR in this repository's resources folder: /resources/thermogis_jar)* +```bash +pixi run mkdocs serve +``` -### 2. Ensure JAVA_HOME is set +--- -When installing the Java 17 Virtual Machine (JVM), a global environment variable _should_ have been set: `JAVA_HOME`. This stores the path to the JVM that was installed in step 1 and enables pythermogis to read the core Java code. +# Installation -If, for some reason, this was not done during installation you can either set it yourself or create a ``.env`` file in your project root folder. +pythermogis has been designed to be used as a python package you import into your own python projects. +It works by creating a python API access to the Core ThermoGIS techno-economic application, which is written in Java. -This `.env` file should contain the following variable: +The ThermoGIS techno-economic Core application is packaged within pythermogis, this is the reason the package is quite large (~150mb). +Additionally the first time you run a simulation with pythermogis, a Java 17 Virtual machine (JVM) will be automatically installed (using the package [install-jdk](https://pypi.org/project/install-jdk/)). -- `JAVA_HOME`: Path to the Java 17 installation - *(e.g., on Windows: `C:\Program Files\Amazon Corretto\jdk17.0.0_0`)* +The Java 17 virtual machine is an additional ~350mb so there should be at least 500mb of space on any machine you install pythermogis on (and preferably more). +Installation of the JVM can take some time (0.5 - 2 minutes) depending on the speed of your internet connection, but will only be done once per pythermogis installation. -Example `.env` contents (The specific path could be different depending on your OS, or file architecture): -``` -JAVA_HOME = C:\Program Files \Amazon Corretto\jdk17.0.0_0 -``` +pythermogis has been tested on Windows and Linux operating systems. -### 3. Import pythermogis into your own python projects +### 1. Import pythermogis into your own python projects You can use pip to install the package directly from the gitlab project: ``` @@ -44,7 +42,7 @@ If you are using uv as your dependency manager: uv add pythermogis --default-index https://ci.tno.nl/gitlab/api/v4/projects/18271/packages/pypi/simple ``` -### Installation from source +### 2. Installation from source Clone and install from source with Pixi: @@ -53,6 +51,5 @@ git clone git@ci.tno.nl:ags_public/pythermogis.git cd pythermogis pixi install ``` -(Make sure you have followed step 1 and 2: installing a Java 17 VM) --- -- GitLab From 85632ee8415c545e7744352359f9794ebddc372e Mon Sep 17 00:00:00 2001 From: bretth Date: Mon, 26 Jan 2026 13:23:51 +0100 Subject: [PATCH 19/19] updating version number and changelog.md --- docs/changelog.md | 3 +++ pyproject.toml | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/changelog.md b/docs/changelog.md index 56cfc08..6bd4abb 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -1,5 +1,8 @@ # Change log +## v1.2.5 (26-1-2026) +A java 17 virtual machine is now automatically installed the first time a pythermogis simulation is run. This uses the [install-jdk](https://pypi.org/project/install-jdk/) python project. + ## v1.2.4 (23-1-2026) The ThermoGIS Jar is now packaged within pythermogis, this reduces the number of installation steps from users (no longer having to set a THERMOGIS_JAR environment variable) and means that multiple installations of pythermogis on the same system won't break each-other (previously two or more pythermogis installations would use the same Jar, which could cause version conflicts). diff --git a/pyproject.toml b/pyproject.toml index 329d605..90e1552 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "pythermogis" -version = "1.2.4" +version = "1.2.5" description = "This repository is used as a python API for the ThermoGIS Doublet simulations" authors = [ { name = "Hen Brett", email = "hen.brett@tno.nl" }, -- GitLab