diff --git a/.gitignore b/.gitignore index 2760637..c33d9cb 100644 --- a/.gitignore +++ b/.gitignore @@ -146,6 +146,8 @@ dmypy.json # Test outputs tests/output/* +tests/*/procdata/* +tests/*/results/* # pixi environments .pixi diff --git a/pixi.lock b/pixi.lock index 8ebebdf..0461c8e 100644 --- a/pixi.lock +++ b/pixi.lock @@ -31,7 +31,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -103,7 +103,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl @@ -281,7 +281,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/ncurses-6.5-he02047a_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/openssl-3.4.0-hb9d3cd8_0.conda - conda: https://conda.anaconda.org/conda-forge/linux-64/optype-0.7.3-py312h7900ff3_2.conda @@ -374,7 +374,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -522,7 +522,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/nbformat-5.10.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/ncurses-6.5-h7bae524_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/nest-asyncio-1.6.0-pyhd8ed1ab_1.conda - - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_0.conda + - conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/openssl-3.4.0-h39f12f2_0.conda - conda: https://conda.anaconda.org/conda-forge/osx-arm64/optype-0.7.3-py312h81bd7bf_2.conda @@ -617,7 +617,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -760,7 +760,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -888,7 +888,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -1054,7 +1054,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/linux-64/zstd-1.5.6-ha6fb4c9_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -1195,7 +1195,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/osx-arm64/zstd-1.5.6-hb46c0d2_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl - pypi: https://files.pythonhosted.org/packages/e7/05/c19819d5e3d95294a6f5947fb9b9629efb316b96de511b418c53d245aae6/cycler-0.12.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/46/d1/e73b6ad76f0b1fb7f23c35c6d95dbc506a9c8804f43dda8cb5b0fa6331fd/dill-0.3.9-py3-none-any.whl @@ -1276,7 +1276,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/9c/3e/a2f4cee0dca934b1d2c4b6a7821040ce4452b9b2e4347c9be6cb10eaa835/aiohttp-3.11.10-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl @@ -1360,7 +1360,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/c9/0b/d326251888bb86ff7cb00b171e1cf3b0f0ed695622857f84a98bbc5f254b/aiohttp-3.11.10-cp310-cp310-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/fe/ba/e2081de779ca30d473f21f5b30e0e737c438205440784c7dfc81efc2b029/async_timeout-5.0.1-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl @@ -1459,7 +1459,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/7c/b8/df6d76a149cbd969a58da478baec0be617287c496c842ddf21fe6bce07b3/aiohttp-3.11.10-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/85/fc/7fa5d17daf77306840a4e84668a48ddff09e6bc09ba4e37e85ffc8e4faa3/contourpy-1.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -1543,7 +1543,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ab/70/0ddb3a61b835068eb0badbe8016b4b65b966bad5f8af0f2d63998ff4cfa4/aiohttp-3.11.10-cp311-cp311-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/67/71/1e6e95aee21a500415f5d2dbf037bf4567529b6a4e986594d7026ec5ae90/contourpy-1.3.1-cp311-cp311-macosx_11_0_arm64.whl @@ -1641,7 +1641,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/a8/e9/1ac90733e36e7848693aece522936a13bf17eeb617da662f94adfafc1c25/aiohttp-3.11.10-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/ba/99/6794142b90b853a9155316c8f470d2e4821fe6f086b03e372aca848227dd/contourpy-1.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl @@ -1725,7 +1725,7 @@ environments: - conda: https://conda.anaconda.org/conda-forge/noarch/tzdata-2024b-hc8b5060_0.conda - pypi: https://files.pythonhosted.org/packages/b9/74/fbb6559de3607b3300b9be3cc64e97548d55678e44623db17820dbd20002/aiohappyeyeballs-2.4.4-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/8a/36/a64b583771fc673062a7a1374728a6241d49e2eda5a9041fbf248e18c804/aiohttp-3.11.10-cp312-cp312-macosx_11_0_arm64.whl - - pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl + - pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6a/21/5b6702a7f963e95456c0de2d495f67bf5fd62840ac655dc451586d23d39a/attrs-24.2.0-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/00/2e/d53fa4befbf2cfa713304affc7ca780ce4fc1fd8710527771b58311a3229/click-8.1.7-py3-none-any.whl - pypi: https://files.pythonhosted.org/packages/6b/6a/7833cfae2c1e63d1d8875a50fd23371394f540ce809d7383550681a1fa64/contourpy-1.3.1-cp312-cp312-macosx_11_0_arm64.whl @@ -1912,13 +1912,13 @@ packages: - brotli ; platform_python_implementation == 'CPython' and extra == 'speedups' - brotlicffi ; platform_python_implementation != 'CPython' and extra == 'speedups' requires_python: '>=3.9' -- pypi: https://files.pythonhosted.org/packages/76/ac/a7305707cb852b7e16ff80eaf5692309bde30e2b1100a1fcacdc8f731d97/aiosignal-1.3.1-py3-none-any.whl +- pypi: https://files.pythonhosted.org/packages/ec/6a/bc7e17a3e87a2985d3e8f4da4cd0f481060eb78fb08596c42be62c90a4d9/aiosignal-1.3.2-py2.py3-none-any.whl name: aiosignal - version: 1.3.1 - sha256: f8376fb07dd1e86a584e4fcdec80b36b7f81aac666ebc724e2c090300dd83b17 + version: 1.3.2 + sha256: 45cde58e409a301715980c2b01d0c28bdde3770d8290b5eb2173759d9acb31a5 requires_dist: - frozenlist>=1.1.0 - requires_python: '>=3.7' + requires_python: '>=3.9' - conda: https://conda.anaconda.org/conda-forge/noarch/annotated-types-0.7.0-pyhd8ed1ab_1.conda sha256: e0ea1ba78fbb64f17062601edda82097fcf815012cf52bb704150a2668110d48 md5: 2934f256a8acfe48f6ebb4fce6cde29c @@ -5187,18 +5187,18 @@ packages: - pytest>=7.2 ; extra == 'test' - pytest-cov>=4.0 ; extra == 'test' requires_python: '>=3.10' -- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_0.conda - sha256: 85ee07342ab055dc081f3de8292c5e7195e43e046db9c5750f242f928f6bb8f2 - md5: dfe0528d0f1c16c1f7c528ea5536ab30 +- conda: https://conda.anaconda.org/conda-forge/noarch/nodeenv-1.9.1-pyhd8ed1ab_1.conda + sha256: 3636eec0e60466a00069b47ce94b6d88b01419b6577d8e393da44bb5bc8d3468 + md5: 7ba3f09fceae6a120d664217e58fe686 depends: - - python 2.7|>=3.7 + - python >=3.9 - setuptools license: BSD-3-Clause license_family: BSD purls: - pkg:pypi/nodeenv?source=hash-mapping - size: 34489 - timestamp: 1717585382642 + size: 34574 + timestamp: 1734112236147 - conda: https://conda.anaconda.org/conda-forge/noarch/notebook-shim-0.2.4-pyhd8ed1ab_1.conda sha256: 7b920e46b9f7a2d2aa6434222e5c8d739021dbc5cc75f32d124a8191d86f9056 md5: e7f89ea5f7ea9401642758ff50a2d9c1 @@ -7117,8 +7117,8 @@ packages: timestamp: 1728642457661 - pypi: . name: readii - version: 1.21.0 - sha256: 712416b55c52a31c85e7ae84be7842a9ec9df227d3b1de0018aa5d1ff0a15ad4 + version: 1.22.0 + sha256: 17cfade190918fb8a7edbe1067b2a0e53170ee5b065416cdfeffa35fe641d037 requires_dist: - simpleitk>=2.3.1 - matplotlib>=3.9.2,<4 diff --git a/src/readii/io/loaders/__init__.py b/src/readii/io/loaders/__init__.py new file mode 100644 index 0000000..5e9ff27 --- /dev/null +++ b/src/readii/io/loaders/__init__.py @@ -0,0 +1,12 @@ +"""Module for loading different data types for the READII pipeline.""" + +from .features import loadFeatureFilesFromImageTypes +from .general import loadFileToDataFrame, loadImageDatasetConfig +from .images import getImageTypesFromDirectory + +__all__ = [ + "loadFeatureFilesFromImageTypes", + "loadFileToDataFrame", + "loadImageDatasetConfig", + "getImageTypesFromDirectory" +] \ No newline at end of file diff --git a/src/readii/io/loaders/features.py b/src/readii/io/loaders/features.py new file mode 100644 index 0000000..a499798 --- /dev/null +++ b/src/readii/io/loaders/features.py @@ -0,0 +1,85 @@ +import os +import pandas as pd + +from typing import Optional, Dict + +from readii.io.loaders.general import loadFileToDataFrame + +from readii.utils import logger + + +def loadFeatureFilesFromImageTypes(extracted_feature_dir:str, + image_types:list, + drop_labels:Optional[bool]=True, + labels_to_drop:Optional[list]=None)->Dict[str,pd.DataFrame]: + """Function to load in all the extracted imaging feature sets from a directory and return them as a dictionary of dataframes. + + Parameters + ---------- + extracted_feature_dir : str + Path to the directory containing the extracted feature csv files + image_types : list, optional + List of image types to load in. The default is ['original']. + drop_labels : bool, optional + Whether to drop the labels from the dataframes. Use when loading labelled data from data_setup_for_modeling.ipynb. The default is True. + labels_to_drop : list, optional + List of labels to drop from the dataframes. The default is ["patient_ID","survival_time_in_years","survival_event_binary"] based on code + in data_setup_for_modeling.ipynb. + + Returns + ------- + feature_sets : dict + Dictionary of dataframes containing the extracted radiomics features. + """ + # Set default labels to drop if not specified + if labels_to_drop is None: + labels_to_drop = ["patient_ID","survival_time_in_years","survival_event_binary"] + + # Initialize dictionary to store the feature sets + feature_sets = {} + + # Check if the passed in extracted feature directory exists + if not os.path.isdir(extracted_feature_dir): + raise FileNotFoundError(f"Extracted feature directory {extracted_feature_dir} does not exist.") + + feature_file_list = os.listdir(extracted_feature_dir) + + # Loop through all the files in the directory + for image_type in image_types: + try: + # Extract the image type feature csv file from the feature directory + matching_files = [file for file in feature_file_list if (image_type in file) and (file.endswith(".csv"))] + if matching_files: + image_type_feature_file = matching_files[0] + # Remove the image type file from the list of feature files + feature_file_list.remove(image_type_feature_file) + except IndexError as e: + logger.warning(f"No {image_type} feature csv files found in {extracted_feature_dir}") + # Skip to the next image type + continue + + + # Get the full path to the feature file + feature_file_path = os.path.join(extracted_feature_dir, image_type_feature_file) + + # Load the feature data into a pandas dataframe + raw_feature_data = loadFileToDataFrame(feature_file_path) + + try: + # Drop the labels from the dataframe if specified + if drop_labels: + # Data is now only extracted features + raw_feature_data.drop(labels_to_drop, axis=1, inplace=True) + except KeyError as e: + logger.warning(f"{feature_file_path} does not have the labels {labels_to_drop} to drop.") + # Skip to the next image type + continue + + # Save the dataframe to the feature_sets dictionary + feature_sets[image_type] = raw_feature_data + + # After processing all image types, check if any feature sets were loaded + if not feature_sets: + raise ValueError(f"No valid feature sets were loaded from {extracted_feature_dir}") + + return feature_sets \ No newline at end of file diff --git a/src/readii/io/loaders/general.py b/src/readii/io/loaders/general.py new file mode 100644 index 0000000..643b9a6 --- /dev/null +++ b/src/readii/io/loaders/general.py @@ -0,0 +1,99 @@ +from pathlib import Path + +import pandas as pd +import yaml + + +class ConfigError(Exception): + """Base class for errors in the config module.""" + + pass + +class DataFrameLoadError(Exception): + """Custom exception for DataFrame loading errors.""" + + pass + +def loadImageDatasetConfig(dataset_name: str, config_dir_path: str | Path) -> dict: + """Load the configuration file for a given dataset. + + Expects the configuration file to be named .yaml. + + Parameters + ---------- + dataset_name : str + Name of the dataset to load the configuration file for. + config_dir_path : str or pathlib.Path + Path to the directory containing the configuration files. + + Returns + ------- + dict + Dictionary containing the configuration settings for the dataset. + + Examples + -------- + >>> config = loadImageDatasetConfig("NSCLC_Radiogenomics", "config") + """ + config_dir_path = Path(config_dir_path) + config_file_path = config_dir_path / f"{dataset_name}.yaml" + + if not config_file_path.exists(): + msg = f"Config file {config_file_path} does not exist." + raise FileNotFoundError(msg) + + try: + with config_file_path.open("r") as f: + config = yaml.safe_load(f) + except yaml.YAMLError as ye: + raise ConfigError("Invalid YAML in config file") from ye + + if not config: + raise ConfigError("Config file is empty or invalid") + + return config + + + +def loadFileToDataFrame(file_path: str | Path) -> pd.DataFrame: + """Load data from a csv or xlsx file into a pandas dataframe. + + Parameters + ---------- + file_path : str or pathlib.Path + Path to the data file. + + Returns + ------- + pd.DataFrame + Dataframe containing the data from the file. + """ + file_path = Path(file_path) + if not file_path: + raise ValueError("File is empty") + + if not file_path.exists(): + msg = f"File {file_path} does not exist" + raise FileNotFoundError(msg) + + # Get the file extension + file_extension = file_path.suffix + + try: + if file_extension == '.xlsx': + df = pd.read_excel(file_path) + elif file_extension == '.csv': + df = pd.read_csv(file_path) + else: + msg = f"Unsupported file format {file_extension}. Please provide a .csv or .xlsx file." + raise ValueError(msg) + + except pd.errors.EmptyDataError as e: + raise DataFrameLoadError("File is empty") from e + + except (pd.errors.ParserError, ValueError) as e: + raise DataFrameLoadError("Error parsing file") from e + + if df.empty: + raise DataFrameLoadError("Dataframe is empty") + return df \ No newline at end of file diff --git a/src/readii/io/loaders/images.py b/src/readii/io/loaders/images.py new file mode 100644 index 0000000..abf631e --- /dev/null +++ b/src/readii/io/loaders/images.py @@ -0,0 +1,52 @@ +from pathlib import Path +from typing import Union + +def getImageTypesFromDirectory(raw_data_dir:Union[Path|str], + feature_file_prefix:str = "", + feature_file_suffix:str = ".csv"): + """ Function to get a list of image types from a directory containing image feature files. + + Parameters + ---------- + raw_data_dir : str + Path to the directory containing the image feature files. + feature_file_prefix : str, optional + Prefix to remove from the feature file name. The default is "". + feature_file_suffix : str, optional + Suffix to remove from the feature file name. The default is ".csv". + + Returns + ------- + list + List of image types from the image feature files. + """ + # Check if raw_data_dir is a string or a Path object, convert to Path object if it is a string + if isinstance(raw_data_dir, str): + raw_data_dir = Path(raw_data_dir) + + # Check if the directory exists + if not raw_data_dir.exists(): + raise FileNotFoundError(f"Directory {raw_data_dir} does not exist.") + + # Check if the directory is a directory + if not raw_data_dir.is_dir(): + raise NotADirectoryError(f"Path {raw_data_dir} is not a directory.") + + # Check that directory contains files with the specified prefix and suffix + if not any(raw_data_dir.glob(f"{feature_file_prefix}*{feature_file_suffix}")): + raise FileNotFoundError(f"No files with prefix {feature_file_prefix} and suffix {feature_file_suffix} found in directory {raw_data_dir}.") + + # Initialize an empty list to store the image types + image_types = [] + + # Get list of file banes with the specified prefix and suffix in the directory + for file in raw_data_dir.glob(f"{feature_file_prefix}*{feature_file_suffix}"): + file_name = file.name + + # Remove the prefix and suffix from the file name + image_type = file_name.removeprefix(feature_file_prefix).removesuffix(feature_file_suffix) + + # Add the image type to the list + image_types.append(image_type) + + return image_types \ No newline at end of file diff --git a/tests/4D-Lung/4D-Lung.yaml b/tests/4D-Lung/4D-Lung.yaml new file mode 100644 index 0000000..b0fb8c1 --- /dev/null +++ b/tests/4D-Lung/4D-Lung.yaml @@ -0,0 +1,20 @@ +# Config file for 4D-Lung for READII +dataset_name: 4D-Lung + +### CLINICAL VARIABLE INFORMATION ### +# Event values should be in the order [Alive_value, Dead_value] +outcome_variables: + time_label: + event_label: + convert_to_years: False + event_value_mapping: + +exclusion_variables: + +train_test_split: + split: False + split_variable: + impute: + + +image_types: ["original", "shuffled_full","shuffled_roi","shuffled_non_roi","randomized_sampled_full","randomized_sampled_roi","randomized_sampled_non_roi"] diff --git a/tests/NSCLC_Radiogenomics/NSCLC_Radiogenomics.yaml b/tests/NSCLC_Radiogenomics/NSCLC_Radiogenomics.yaml new file mode 100644 index 0000000..a4018a0 --- /dev/null +++ b/tests/NSCLC_Radiogenomics/NSCLC_Radiogenomics.yaml @@ -0,0 +1,20 @@ +# Config file for NSCLC_Radiogenomics for READII +dataset_name: NSCLC_Radiogenomics + +### CLINICAL VARIABLE INFORMATION ### +# Event values should be in the order [Alive_value, Dead_value] +outcome_variables: + time_label: "" + event_label: "Survival Status" + convert_to_years: False + event_value_mapping: {'Alive': 0, 'Dead': 1} + +exclusion_variables: + +train_test_split: + split: False + split_variable: + impute: + + +image_types: ["original", "shuffled_full","shuffled_roi","shuffled_non_roi","randomized_sampled_full","randomized_sampled_roi","randomized_sampled_non_roi"] diff --git a/tests/io/loaders/test_general.py b/tests/io/loaders/test_general.py new file mode 100644 index 0000000..d255c0c --- /dev/null +++ b/tests/io/loaders/test_general.py @@ -0,0 +1,29 @@ +from readii.io.loaders.general import loadImageDatasetConfig +import pytest + +@pytest.fixture +def nsclcConfigDirPath(): + return "tests/NSCLC_Radiogenomics" + +@pytest.fixture +def lung4DConfigDirPath(): + return "tests/4D-Lung" + +@pytest.fixture +def expected_image_types(): + return ["original", "shuffled_full","shuffled_roi","shuffled_non_roi","randomized_sampled_full","randomized_sampled_roi","randomized_sampled_non_roi"] + + +def test_NSCLC_loadImageDatasetConfig(nsclcConfigDirPath, expected_image_types): + config = loadImageDatasetConfig("NSCLC_Radiogenomics", nsclcConfigDirPath) + assert config["dataset_name"] == "NSCLC_Radiogenomics" + assert config["image_types"] == expected_image_types + assert config["outcome_variables"]["event_label"] == "Survival Status" + assert config["outcome_variables"]["event_value_mapping"] == {'Alive': 0, 'Dead': 1} + +def test_lung4D_loadImageDatasetConfig(lung4DConfigDirPath, expected_image_types): + config = loadImageDatasetConfig("4D-Lung", lung4DConfigDirPath) + assert config["dataset_name"] == "4D-Lung" + assert config["image_types"] == expected_image_types + assert config["outcome_variables"]["event_label"] is None + assert config["outcome_variables"]["event_value_mapping"] is None \ No newline at end of file diff --git a/tests/output/ct_to_seg_match_list_4D-Lung.csv b/tests/output/ct_to_seg_match_list_4D-Lung.csv new file mode 100644 index 0000000..4260bb3 --- /dev/null +++ b/tests/output/ct_to_seg_match_list_4D-Lung.csv @@ -0,0 +1,2 @@ +patient_ID,study_CT,study_description_CT,series_CT,series_description_CT,subseries_CT,modality_CT,instances_CT,instance_uid_CT,reference_ct_CT,reference_rs_CT,reference_pl_CT,reference_frame_CT,folder_CT,orientation_CT,orientation_type_CT,MR_repetition_time_CT,MR_echo_time_CT,MR_scan_sequence_CT,MR_magnetic_field_strength_CT,MR_imaged_nucleus_CT,file_path_CT,series_seg,subseries_seg,modality_seg,instances_seg,instance_uid_seg,reference_ct_seg,reference_rs_seg,reference_pl_seg,reference_frame_seg,folder_seg,orientation_seg,orientation_type_seg,MR_repetition_time_seg,MR_echo_time_seg,MR_scan_sequence_seg,MR_magnetic_field_strength_seg,MR_imaged_nucleus_seg,file_path_seg,edge_type +113_HM10395,1.3.6.1.4.1.14519.5.2.1.6834.5010.324605948863389564556891313296,p4,1.3.6.1.4.1.14519.5.2.1.6834.5010.339023390306606021995936229543,"P4^P113^S303^I10349, Gated, 40.0%B",default,CT,99,1.3.6.1.4.1.14519.5.2.1.6834.5010.249506064276270740866733345688,,,,1.3.6.1.4.1.14519.5.2.1.6834.5010.107174034240688216982546597713,4D-Lung/113_HM10395/11-26-1999-NA-p4-13296/1.000000-P4P113S303I10349 Gated 40.0B-29543,"[1, 0, 0, 0, 1, 0]",,,,,,,4D-Lung/113_HM10395/11-26-1999-NA-p4-13296/1.000000-P4P113S303I10349 Gated 40.0B-29543/1-81.dcm,2.25.186899387610254289948150314209581209847.35,default,RTSTRUCT,1,1.3.6.1.4.1.14519.5.2.1.6834.5010.815153834456695039602326691312,1.3.6.1.4.1.14519.5.2.1.6834.5010.339023390306606021995936229543,,,1.3.6.1.4.1.14519.5.2.1.6834.5010.107174034240688216982546597713,4D-Lung/113_HM10395/11-26-1999-NA-p4-13296/1.000000-P4P113S303I10349 Gated 40.0B-47.35/1-1.dcm,,,,,,,,4D-Lung/113_HM10395/11-26-1999-NA-p4-13296/1.000000-P4P113S303I10349 Gated 40.0B-47.35/1-1.dcm,2 diff --git a/tests/test_feature_extraction.py b/tests/test_feature_extraction.py index 9f63ae3..650c6a5 100644 --- a/tests/test_feature_extraction.py +++ b/tests/test_feature_extraction.py @@ -13,6 +13,8 @@ import collections import pandas as pd import os +import shutil +from pathlib import Path @pytest.fixture def nsclcCTImage(): @@ -44,7 +46,21 @@ def pyradiomicsParamFilePath(): @pytest.fixture def nsclcMetadataPath(): - return "tests/output/ct_to_seg_match_list_NSCLC_Radiogenomics.csv" + oldpath = Path("tests/output/ct_to_seg_match_list_NSCLC_Radiogenomics.csv") + newpath = Path("tests/NSCLC_Radiogenomics/procdata/ct_to_seg_match_list_NSCLC_Radiogenomics.csv") + newpath.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(oldpath, newpath) + yield newpath.as_posix() + newpath.unlink() + +@pytest.fixture +def lung4DMetadataPath(): + oldpath = Path("tests/output/ct_to_seg_match_list_4D-Lung.csv") + newpath = Path("tests/4D-Lung/procdata/ct_to_seg_match_list_4D-Lung.csv") + newpath.parent.mkdir(parents=True, exist_ok=True) + shutil.copy(oldpath, newpath) + yield newpath.as_posix() + newpath.unlink() def test_singleRadiomicFeatureExtraction_SEG(nsclcCTImage, nsclcSEGImage, pyradiomicsParamFilePath): @@ -108,11 +124,21 @@ def test_radiomicFeatureExtraction(nsclcMetadataPath): "Volume feature is incorrect" -def test_radiomicFeatureExtraction_output(nsclcMetadataPath): - """Test output creation from radiomic feature extraction""" +def test_NSCLC_radiomicFeatureExtraction_output(nsclcMetadataPath): + """Test output creation from radiomic feature extraction for SEG dataset""" actual = radiomicFeatureExtraction(nsclcMetadataPath, imageDirPath = "tests/", roiNames = None, - outputDirPath = "tests/output/") - expected_path = "tests/output/features/radiomicfeatures_original_NSCLC_Radiogenomics.csv" + outputDirPath = "tests/NSCLC_Radiogenomics/results/") + expected_path = "tests/NSCLC_Radiogenomics/results/features/radiomicfeatures_original_NSCLC_Radiogenomics.csv" + assert os.path.exists(expected_path) + + +def test_4DLung_radiomicFeatureExtraction_output(lung4DMetadataPath): + """Test output creation from radiomic feature extraction for RTSTRUCT dataset""" + actual = radiomicFeatureExtraction(lung4DMetadataPath, + imageDirPath = "tests/", + roiNames = "Tumor_c40", + outputDirPath = "tests/4D-Lung/results/") + expected_path = "tests/4D-Lung/results/features/radiomicfeatures_original_4D-Lung.csv" assert os.path.exists(expected_path) \ No newline at end of file diff --git a/tests/test_metadata.py b/tests/test_metadata.py index 7b1c505..59947bf 100644 --- a/tests/test_metadata.py +++ b/tests/test_metadata.py @@ -1,5 +1,5 @@ import pytest -import os +from pathlib import Path from readii.metadata import ( matchCTtoSegmentation, @@ -49,12 +49,21 @@ def test_matchCTtoRTSTRUCT(lung4DSummaryFilePath): "Incorrect segmentation type has been found" -def test_matchCTtoSegmentation_output(nsclcSummaryFilePath): +@pytest.mark.parametrize( + "summary_file_path, modality, output_file_path", + [ + ("nsclcSummaryFilePath","SEG","tests/NSCLC_Radiogenomics/procdata/ct_to_seg_match_list_NSCLC_Radiogenomics.csv") + ] +) +def test_matchCTtoSegmentation_output(summary_file_path, modality, output_file_path, request): """Test saving output of summary file""" - actual = matchCTtoSegmentation(nsclcSummaryFilePath, - segType = "SEG", - outputFilePath = "tests/output/ct_to_seg_match_list_NSCLC_Radiogenomics.csv") - assert os.path.exists("tests/output/ct_to_seg_match_list_NSCLC_Radiogenomics.csv") == True, \ + summary_file_path = request.getfixturevalue(summary_file_path) + + matchCTtoSegmentation(summary_file_path, + segType = modality, + outputFilePath = output_file_path) + + assert Path(output_file_path).exists(), \ "Output does not exist, double check output file is named correctly." @@ -71,13 +80,21 @@ def test_getCTWithRTTRUCT(lung4DEdgesSummaryFilePath): assert actual['modality_seg'][0] == 'RTSTRUCT', \ "Incorrect segmentation type has been found" - -def test_getCTtoSegmentation_output(lung4DEdgesSummaryFilePath): +@pytest.mark.parametrize( + "summary_file_path, modality, output_file_path", + [ + ("lung4DEdgesSummaryFilePath","RTSTRUCT","tests/4D-Lung/procdata/ct_to_seg_match_list_4D-Lung.csv") + ] +) +def test_getCTtoSegmentation_output(summary_file_path, modality, output_file_path, request): """Test saving output of summary file""" - actual = getCTWithSegmentation(lung4DEdgesSummaryFilePath, - segType = "RTSTRUCT", - outputFilePath = "tests/output/ct_to_seg_match_list_4D-Lung.csv") - assert os.path.exists("tests/output/ct_to_seg_match_list_4D-Lung.csv") == True, \ + summary_file_path = request.getfixturevalue(summary_file_path) + + getCTWithSegmentation(summary_file_path, + segType = modality, + outputFilePath = output_file_path) + + assert Path(output_file_path).exists(), \ "Output does not exist, double check output file is named correctly."