py-pilecore 0.5.1__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of py-pilecore might be problematic. Click here for more details.

Files changed (49) hide show
  1. {py_pilecore-0.5.1/src/py_pilecore.egg-info → py_pilecore-0.7.0}/PKG-INFO +17 -20
  2. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/README.md +2 -2
  3. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/pyproject.toml +21 -20
  4. {py_pilecore-0.5.1 → py_pilecore-0.7.0/src/py_pilecore.egg-info}/PKG-INFO +17 -20
  5. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/py_pilecore.egg-info/SOURCES.txt +12 -1
  6. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/py_pilecore.egg-info/requires.txt +14 -16
  7. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/_version.py +1 -1
  8. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/input/grouper_properties.py +10 -3
  9. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/input/soil_properties.py +11 -1
  10. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/__init__.py +2 -0
  11. py_pilecore-0.7.0/src/pypilecore/results/cases_multi_cpt_results.py +244 -0
  12. py_pilecore-0.7.0/src/pypilecore/results/result_definitions.py +195 -0
  13. py_pilecore-0.7.0/src/pypilecore/viewers/__init__.py +9 -0
  14. py_pilecore-0.7.0/src/pypilecore/viewers/interactive_figures/__init__.py +15 -0
  15. py_pilecore-0.7.0/src/pypilecore/viewers/interactive_figures/figure_cpt_group_results_versus_ptls.py +193 -0
  16. py_pilecore-0.7.0/src/pypilecore/viewers/interactive_figures/figure_cpt_results_plan_view.py +268 -0
  17. py_pilecore-0.7.0/src/pypilecore/viewers/interactive_figures/figure_cpt_results_versus_ptls.py +176 -0
  18. py_pilecore-0.7.0/src/pypilecore/viewers/interactive_figures/utils.py +47 -0
  19. py_pilecore-0.7.0/src/pypilecore/viewers/viewer_cpt_group_results.py +75 -0
  20. py_pilecore-0.7.0/src/pypilecore/viewers/viewer_cpt_results.py +87 -0
  21. py_pilecore-0.7.0/src/pypilecore/viewers/viewer_cpt_results_plan_view.py +101 -0
  22. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/LICENSE +0 -0
  23. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/setup.cfg +0 -0
  24. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/py_pilecore.egg-info/dependency_links.txt +0 -0
  25. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/py_pilecore.egg-info/top_level.txt +0 -0
  26. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/__init__.py +0 -0
  27. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/api.py +0 -0
  28. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/__init__.py +0 -0
  29. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/__init__.py +0 -0
  30. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/__init__.py +0 -0
  31. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/components/__init__.py +0 -0
  32. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/components/common.py +0 -0
  33. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/components/rectangle.py +0 -0
  34. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/components/round.py +0 -0
  35. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/main.py +0 -0
  36. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/geometry/materials.py +0 -0
  37. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/main.py +0 -0
  38. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/common/piles/type.py +0 -0
  39. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/exceptions.py +0 -0
  40. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/input/__init__.py +0 -0
  41. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/input/multi_cpt.py +0 -0
  42. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/plot_utils.py +0 -0
  43. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/grouper_result.py +0 -0
  44. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/load_settlement.py +0 -0
  45. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/multi_cpt_results.py +0 -0
  46. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/post_processing.py +0 -0
  47. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/single_cpt_results.py +0 -0
  48. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/results/soil_properties.py +0 -0
  49. {py_pilecore-0.5.1 → py_pilecore-0.7.0}/src/pypilecore/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-pilecore
3
- Version: 0.5.1
3
+ Version: 0.7.0
4
4
  Summary: Public python SDK for the CEMS PileCore web-API.
5
5
  License: MIT License
6
6
 
@@ -37,10 +37,14 @@ Requires-Dist: matplotlib<4,>=3.8
37
37
  Requires-Dist: tqdm[notebook]<5,>4
38
38
  Requires-Dist: natsort<9,>8
39
39
  Requires-Dist: shapely<3,>=2
40
- Requires-Dist: scipy<2,>=1
40
+ Requires-Dist: scipy<2,>=1.13
41
+ Requires-Dist: ipywidgets<9,>=8
42
+ Requires-Dist: dash<3,>=2.17
43
+ Requires-Dist: plotly-geo<2,>=1.0.0
41
44
  Provides-Extra: test
42
45
  Requires-Dist: coveralls; extra == "test"
43
46
  Requires-Dist: pytest; extra == "test"
47
+ Requires-Dist: openapi-core; extra == "test"
44
48
  Provides-Extra: docs
45
49
  Requires-Dist: Sphinx==6.1.3; extra == "docs"
46
50
  Requires-Dist: sphinx-autodoc-typehints==1.22; extra == "docs"
@@ -48,23 +52,16 @@ Requires-Dist: ipython==8.11.0; extra == "docs"
48
52
  Requires-Dist: asteroid-sphinx-theme==0.0.3; extra == "docs"
49
53
  Requires-Dist: sphinx_rtd_theme==1.2.0; extra == "docs"
50
54
  Provides-Extra: lint
51
- Requires-Dist: mypy==1.6.1; extra == "lint"
52
- Requires-Dist: mypy-extensions==1.0.0; extra == "lint"
53
- Requires-Dist: tomli==2.0.1; extra == "lint"
54
- Requires-Dist: typing_extensions==4.7.1; extra == "lint"
55
- Requires-Dist: black[jupyter]==23.10.1; extra == "lint"
56
- Requires-Dist: click==8.1.3; extra == "lint"
57
- Requires-Dist: packaging==23.2; extra == "lint"
58
- Requires-Dist: pathspec==0.11.1; extra == "lint"
59
- Requires-Dist: platformdirs==3.5.1; extra == "lint"
60
- Requires-Dist: tomli==2.0.1; extra == "lint"
61
- Requires-Dist: isort==5.12.0; extra == "lint"
55
+ Requires-Dist: ansible-lint==6.22.1; extra == "lint"
56
+ Requires-Dist: black==23.11.0; extra == "lint"
57
+ Requires-Dist: cfn-lint==0.83.3; extra == "lint"
58
+ Requires-Dist: cpplint==1.6.1; extra == "lint"
62
59
  Requires-Dist: flake8==6.0.0; extra == "lint"
63
- Requires-Dist: mccabe==0.7.0; extra == "lint"
64
- Requires-Dist: pycodestyle==2.10.0; extra == "lint"
65
- Requires-Dist: pyflakes==3.0.1; extra == "lint"
66
- Requires-Dist: pandas-stubs<3,>2; extra == "lint"
67
- Requires-Dist: types-tqdm<5,>4; extra == "lint"
60
+ Requires-Dist: isort==5.12.0; extra == "lint"
61
+ Requires-Dist: mypy==1.7.1; extra == "lint"
62
+ Requires-Dist: sqlfluff==2.3.5; extra == "lint"
63
+ Requires-Dist: yamllint==1.33.0; extra == "lint"
64
+ Requires-Dist: yq==3.2.3; extra == "lint"
68
65
 
69
66
  # py-pilecore
70
67
  Public python SDK for the CEMS PileCore web-API
@@ -100,7 +97,7 @@ Go to `personal-access-tokens` and create a new user token.
100
97
 
101
98
  ## Environment
102
99
 
103
- We recommend developing in Python3.10 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
100
+ We recommend developing in Python3.11 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
104
101
 
105
102
  Example using `virtualenv` and `pip` to install the dependencies in a new environment .env on Linux:
106
103
 
@@ -152,7 +149,7 @@ coverage run -m pytest
152
149
 
153
150
  ## Requirements
154
151
 
155
- Requirements are autogenerated by the `pip-compile` command with python 3.10
152
+ Requirements are autogenerated by the `pip-compile` command with python 3.11
156
153
 
157
154
  Install pip-tools with:
158
155
 
@@ -32,7 +32,7 @@ Go to `personal-access-tokens` and create a new user token.
32
32
 
33
33
  ## Environment
34
34
 
35
- We recommend developing in Python3.10 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
35
+ We recommend developing in Python3.11 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
36
36
 
37
37
  Example using `virtualenv` and `pip` to install the dependencies in a new environment .env on Linux:
38
38
 
@@ -84,7 +84,7 @@ coverage run -m pytest
84
84
 
85
85
  ## Requirements
86
86
 
87
- Requirements are autogenerated by the `pip-compile` command with python 3.10
87
+ Requirements are autogenerated by the `pip-compile` command with python 3.11
88
88
 
89
89
  Install pip-tools with:
90
90
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "py-pilecore"
7
- version = "0.5.1"
7
+ version = "0.7.0"
8
8
  description = "Public python SDK for the CEMS PileCore web-API."
9
9
  requires-python = ">=3.9"
10
10
  dependencies = [
@@ -16,7 +16,10 @@ dependencies = [
16
16
  "tqdm[notebook]>4,<5",
17
17
  "natsort>8,<9",
18
18
  "shapely>=2,<3",
19
- "scipy>=1, <2",
19
+ "scipy>=1.13, <2",
20
+ "ipywidgets>=8, <9",
21
+ "dash>=2.17, <3",
22
+ "plotly-geo>=1.0.0, <2",
20
23
  ]
21
24
  license = { file = "LICENSE" }
22
25
  readme = "README.md"
@@ -26,7 +29,7 @@ keywords = ["API", "PileCore", "CEMS", "CRUX"]
26
29
  repository = "https://github.com/cemsbv/py-pilecore"
27
30
 
28
31
  [project.optional-dependencies]
29
- test = ["coveralls", "pytest"]
32
+ test = ["coveralls", "pytest", "openapi-core"]
30
33
  docs = [
31
34
  "Sphinx==6.1.3",
32
35
  "sphinx-autodoc-typehints==1.22",
@@ -34,26 +37,21 @@ docs = [
34
37
  "asteroid-sphinx-theme==0.0.3",
35
38
  "sphinx_rtd_theme==1.2.0",
36
39
  ]
37
- # lint dependencies from github super-linter v5
40
+ # lint dependencies from github super-linter
38
41
  # See https://github.com/super-linter/super-linter/tree/main/dependencies/python
42
+ # Get a file with the latest requirements by running bash: `./get-super-linter-requirements.sh`
43
+ # ignoring because redundant: snakemake, snakefmt, pylint
39
44
  lint = [
40
- "mypy==1.6.1",
41
- "mypy-extensions==1.0.0",
42
- "tomli==2.0.1",
43
- "typing_extensions==4.7.1",
44
- "black[jupyter]==23.10.1",
45
- "click==8.1.3",
46
- "packaging==23.2",
47
- "pathspec==0.11.1",
48
- "platformdirs==3.5.1",
49
- "tomli==2.0.1,",
50
- "isort==5.12.0",
45
+ "ansible-lint==6.22.1",
46
+ "black==23.11.0",
47
+ "cfn-lint==0.83.3",
48
+ "cpplint==1.6.1",
51
49
  "flake8==6.0.0",
52
- "mccabe==0.7.0",
53
- "pycodestyle==2.10.0",
54
- "pyflakes==3.0.1",
55
- 'pandas-stubs>2,<3',
56
- 'types-tqdm>4,<5',
50
+ "isort==5.12.0",
51
+ "mypy==1.7.1",
52
+ "sqlfluff==2.3.5",
53
+ "yamllint==1.33.0",
54
+ "yq==3.2.3",
57
55
  ]
58
56
 
59
57
  [tool.isort]
@@ -95,5 +93,8 @@ module = [
95
93
  "scipy.*",
96
94
  "numpy.*",
97
95
  "pandas.*",
96
+ "IPython.*",
97
+ "plotly.*",
98
+ "ipywidgets.*",
98
99
  ]
99
100
  ignore_missing_imports = true
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: py-pilecore
3
- Version: 0.5.1
3
+ Version: 0.7.0
4
4
  Summary: Public python SDK for the CEMS PileCore web-API.
5
5
  License: MIT License
6
6
 
@@ -37,10 +37,14 @@ Requires-Dist: matplotlib<4,>=3.8
37
37
  Requires-Dist: tqdm[notebook]<5,>4
38
38
  Requires-Dist: natsort<9,>8
39
39
  Requires-Dist: shapely<3,>=2
40
- Requires-Dist: scipy<2,>=1
40
+ Requires-Dist: scipy<2,>=1.13
41
+ Requires-Dist: ipywidgets<9,>=8
42
+ Requires-Dist: dash<3,>=2.17
43
+ Requires-Dist: plotly-geo<2,>=1.0.0
41
44
  Provides-Extra: test
42
45
  Requires-Dist: coveralls; extra == "test"
43
46
  Requires-Dist: pytest; extra == "test"
47
+ Requires-Dist: openapi-core; extra == "test"
44
48
  Provides-Extra: docs
45
49
  Requires-Dist: Sphinx==6.1.3; extra == "docs"
46
50
  Requires-Dist: sphinx-autodoc-typehints==1.22; extra == "docs"
@@ -48,23 +52,16 @@ Requires-Dist: ipython==8.11.0; extra == "docs"
48
52
  Requires-Dist: asteroid-sphinx-theme==0.0.3; extra == "docs"
49
53
  Requires-Dist: sphinx_rtd_theme==1.2.0; extra == "docs"
50
54
  Provides-Extra: lint
51
- Requires-Dist: mypy==1.6.1; extra == "lint"
52
- Requires-Dist: mypy-extensions==1.0.0; extra == "lint"
53
- Requires-Dist: tomli==2.0.1; extra == "lint"
54
- Requires-Dist: typing_extensions==4.7.1; extra == "lint"
55
- Requires-Dist: black[jupyter]==23.10.1; extra == "lint"
56
- Requires-Dist: click==8.1.3; extra == "lint"
57
- Requires-Dist: packaging==23.2; extra == "lint"
58
- Requires-Dist: pathspec==0.11.1; extra == "lint"
59
- Requires-Dist: platformdirs==3.5.1; extra == "lint"
60
- Requires-Dist: tomli==2.0.1; extra == "lint"
61
- Requires-Dist: isort==5.12.0; extra == "lint"
55
+ Requires-Dist: ansible-lint==6.22.1; extra == "lint"
56
+ Requires-Dist: black==23.11.0; extra == "lint"
57
+ Requires-Dist: cfn-lint==0.83.3; extra == "lint"
58
+ Requires-Dist: cpplint==1.6.1; extra == "lint"
62
59
  Requires-Dist: flake8==6.0.0; extra == "lint"
63
- Requires-Dist: mccabe==0.7.0; extra == "lint"
64
- Requires-Dist: pycodestyle==2.10.0; extra == "lint"
65
- Requires-Dist: pyflakes==3.0.1; extra == "lint"
66
- Requires-Dist: pandas-stubs<3,>2; extra == "lint"
67
- Requires-Dist: types-tqdm<5,>4; extra == "lint"
60
+ Requires-Dist: isort==5.12.0; extra == "lint"
61
+ Requires-Dist: mypy==1.7.1; extra == "lint"
62
+ Requires-Dist: sqlfluff==2.3.5; extra == "lint"
63
+ Requires-Dist: yamllint==1.33.0; extra == "lint"
64
+ Requires-Dist: yq==3.2.3; extra == "lint"
68
65
 
69
66
  # py-pilecore
70
67
  Public python SDK for the CEMS PileCore web-API
@@ -100,7 +97,7 @@ Go to `personal-access-tokens` and create a new user token.
100
97
 
101
98
  ## Environment
102
99
 
103
- We recommend developing in Python3.10 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
100
+ We recommend developing in Python3.11 with a clean virtual environment (using `virtualenv` or `conda`), installing the requirements from the requirements.txt file:
104
101
 
105
102
  Example using `virtualenv` and `pip` to install the dependencies in a new environment .env on Linux:
106
103
 
@@ -152,7 +149,7 @@ coverage run -m pytest
152
149
 
153
150
  ## Requirements
154
151
 
155
- Requirements are autogenerated by the `pip-compile` command with python 3.10
152
+ Requirements are autogenerated by the `pip-compile` command with python 3.11
156
153
 
157
154
  Install pip-tools with:
158
155
 
@@ -28,9 +28,20 @@ src/pypilecore/input/grouper_properties.py
28
28
  src/pypilecore/input/multi_cpt.py
29
29
  src/pypilecore/input/soil_properties.py
30
30
  src/pypilecore/results/__init__.py
31
+ src/pypilecore/results/cases_multi_cpt_results.py
31
32
  src/pypilecore/results/grouper_result.py
32
33
  src/pypilecore/results/load_settlement.py
33
34
  src/pypilecore/results/multi_cpt_results.py
34
35
  src/pypilecore/results/post_processing.py
36
+ src/pypilecore/results/result_definitions.py
35
37
  src/pypilecore/results/single_cpt_results.py
36
- src/pypilecore/results/soil_properties.py
38
+ src/pypilecore/results/soil_properties.py
39
+ src/pypilecore/viewers/__init__.py
40
+ src/pypilecore/viewers/viewer_cpt_group_results.py
41
+ src/pypilecore/viewers/viewer_cpt_results.py
42
+ src/pypilecore/viewers/viewer_cpt_results_plan_view.py
43
+ src/pypilecore/viewers/interactive_figures/__init__.py
44
+ src/pypilecore/viewers/interactive_figures/figure_cpt_group_results_versus_ptls.py
45
+ src/pypilecore/viewers/interactive_figures/figure_cpt_results_plan_view.py
46
+ src/pypilecore/viewers/interactive_figures/figure_cpt_results_versus_ptls.py
47
+ src/pypilecore/viewers/interactive_figures/utils.py
@@ -6,7 +6,10 @@ matplotlib<4,>=3.8
6
6
  tqdm[notebook]<5,>4
7
7
  natsort<9,>8
8
8
  shapely<3,>=2
9
- scipy<2,>=1
9
+ scipy<2,>=1.13
10
+ ipywidgets<9,>=8
11
+ dash<3,>=2.17
12
+ plotly-geo<2,>=1.0.0
10
13
 
11
14
  [docs]
12
15
  Sphinx==6.1.3
@@ -16,23 +19,18 @@ asteroid-sphinx-theme==0.0.3
16
19
  sphinx_rtd_theme==1.2.0
17
20
 
18
21
  [lint]
19
- mypy==1.6.1
20
- mypy-extensions==1.0.0
21
- tomli==2.0.1
22
- typing_extensions==4.7.1
23
- black[jupyter]==23.10.1
24
- click==8.1.3
25
- packaging==23.2
26
- pathspec==0.11.1
27
- platformdirs==3.5.1
28
- isort==5.12.0
22
+ ansible-lint==6.22.1
23
+ black==23.11.0
24
+ cfn-lint==0.83.3
25
+ cpplint==1.6.1
29
26
  flake8==6.0.0
30
- mccabe==0.7.0
31
- pycodestyle==2.10.0
32
- pyflakes==3.0.1
33
- pandas-stubs<3,>2
34
- types-tqdm<5,>4
27
+ isort==5.12.0
28
+ mypy==1.7.1
29
+ sqlfluff==2.3.5
30
+ yamllint==1.33.0
31
+ yq==3.2.3
35
32
 
36
33
  [test]
37
34
  coveralls
38
35
  pytest
36
+ openapi-core
@@ -4,4 +4,4 @@ try:
4
4
  __version__ = version("py-pilecore")
5
5
  # during CI
6
6
  except PackageNotFoundError:
7
- __version__ = "0.5.1"
7
+ __version__ = "0.7.0"
@@ -74,7 +74,8 @@ def create_grouper_payload(
74
74
  Parameters
75
75
  ----------
76
76
  cpt_results_dict:
77
- Dictionary with key as CPT name and value a SingleCPTBearingResults class
77
+ Dictionary with key as CPT name and value a SingleCPTBearingResults class.
78
+ Should contain at least 2 entries.
78
79
  pile_load_uls
79
80
  ULS load in kN. Used to determine if a grouping configuration is valid.
80
81
  stiff_construction
@@ -131,12 +132,12 @@ def create_grouper_payload(
131
132
  ValueError:
132
133
  - if NaN values are present in negative friction, bottom or shaft bearing_capacity
133
134
 
134
-
135
135
  - if x or y coordinate is None
136
136
 
137
-
138
137
  - if pile tip levels don't macht for all SingleCPTBearingResults
139
138
 
139
+ - if less than 2 valid CPTs are provided
140
+
140
141
 
141
142
  Returns
142
143
  -------
@@ -212,6 +213,12 @@ def create_grouper_payload(
212
213
  },
213
214
  }
214
215
  )
216
+
217
+ if not len(cpt_objects) >= 2:
218
+ raise ValueError(
219
+ "The PileCore grouper requires at least 2 CPTs with valid bearing capacity."
220
+ )
221
+
215
222
  payload["cpt_objects"] = cpt_objects
216
223
 
217
224
  # validate pile tip levels
@@ -158,9 +158,19 @@ def create_soil_properties_payload(
158
158
  groundwater_level_nap=groundwater_level_nap
159
159
  if groundwater_level_nap is not None
160
160
  else cpt.delivered_vertical_position_offset - 1,
161
- coordinates=dict(x=cpt.delivered_location.x, y=cpt.delivered_location.y),
162
161
  )
163
162
 
163
+ # Optionally add coordinates
164
+ if (
165
+ cpt.delivered_location is not None
166
+ and cpt.delivered_location.x is not None
167
+ and cpt.delivered_location.y is not None
168
+ ):
169
+ soil_properties["coordinates"] = {
170
+ "x": cpt.delivered_location.x,
171
+ "y": cpt.delivered_location.y,
172
+ }
173
+
164
174
  # Optionally add cpt-specific friction-range parameters
165
175
  if (
166
176
  individual_negative_friction_range_nap is not None
@@ -1,9 +1,11 @@
1
+ from pypilecore.results.cases_multi_cpt_results import CasesMultiCPTBearingResults
1
2
  from pypilecore.results.grouper_result import GrouperResults
2
3
  from pypilecore.results.multi_cpt_results import MultiCPTBearingResults
3
4
  from pypilecore.results.single_cpt_results import SingleCPTBearingResults
4
5
  from pypilecore.results.soil_properties import SoilProperties
5
6
 
6
7
  __all__ = [
8
+ "CasesMultiCPTBearingResults",
7
9
  "MultiCPTBearingResults",
8
10
  "SingleCPTBearingResults",
9
11
  "SoilProperties",
@@ -0,0 +1,244 @@
1
+ from __future__ import annotations # noqa: F404
2
+
3
+ from typing import Dict, Hashable, List
4
+
5
+ import pandas as pd
6
+ from natsort import natsorted
7
+ from pygef.common import Location
8
+
9
+ from pypilecore.results.multi_cpt_results import MultiCPTBearingResults
10
+ from pypilecore.results.result_definitions import (
11
+ CPTGroupResultDefinitions,
12
+ CPTResultDefinitions,
13
+ )
14
+
15
+
16
+ class CasesMultiCPTBearingResults:
17
+ """
18
+ Container class for the results of multiple cases of MultiCPTBearingResults.
19
+ It expects that all MultiCPTBearingResults objects have the same pile tip levels and same test ids.
20
+ """
21
+
22
+ def __init__(
23
+ self,
24
+ results_per_case: Dict[Hashable, MultiCPTBearingResults],
25
+ cpt_locations: Dict[str, Location],
26
+ ) -> None:
27
+ """
28
+ Initialize the class with the results of multiple cases of MultiCPTBearingResults.
29
+
30
+ Parameters
31
+ ----------
32
+ results_per_case : Dict[Hashable, MultiCPTBearingResults]
33
+ A dictionary with the results of multiple cases of MultiCPTBearingResults.
34
+ The keys of the dictionary are the case names.
35
+ All MultiCPTBearingResults objects must have the same pile tip levels and same test ids.
36
+ cpt_locations : Dict[str, Location]
37
+ The mapping between `test_id` (key) and the `location` (value) of the cpt.
38
+ The keys must contain all the `test_id` (s) used in the MultiCPTBearingResults objects.
39
+
40
+ Raises
41
+ ------
42
+ TypeError
43
+ If `results_per_case` is not of the expected type.
44
+ If `cpt_locations` is not of the expected type.
45
+ ValueError
46
+ If `results_per_case` is an empty dictionary.
47
+ If not all MultiCPTBearingResults objects have the same pile tip levels and test ids.
48
+ If not all the `test_id` (s) used in the MultiCPTBearingResults objects are in the keys of `cpt_locations`.
49
+ """
50
+ # Validate results cases
51
+ _validate_results_per_case(results_per_case)
52
+
53
+ # Initialize private variables
54
+ self._cases = natsorted(list(results_per_case.keys()))
55
+ self._multicpt_bearing_results = [results_per_case[c] for c in self.cases]
56
+ self._test_ids = natsorted(
57
+ results_per_case[list(results_per_case.keys())[0]].cpt_results.test_ids
58
+ )
59
+ self._pile_tip_levels_nap = sorted(
60
+ list(
61
+ results_per_case[list(results_per_case.keys())[0]]
62
+ .cpt_results.to_pandas()
63
+ .pile_tip_level_nap.unique()
64
+ ),
65
+ reverse=True,
66
+ )
67
+ self._set_cpt_locations(cpt_locations)
68
+
69
+ # Create cpt_results_dataframe and cpt_group_results_dataframe
70
+ self._set_cpt_results_dataframe(results_per_case)
71
+ self._set_cpt_group_results_dataframe(results_per_case)
72
+
73
+ def _set_cpt_results_dataframe(
74
+ self, results_per_case: Dict[Hashable, MultiCPTBearingResults]
75
+ ) -> None:
76
+ """Private method to create and set the property `cpt_results_dataframe`."""
77
+ records = []
78
+ for case_name, case_results in results_per_case.items():
79
+ for result_definition in CPTResultDefinitions:
80
+ df = case_results.cpt_results.get_results_per_cpt(
81
+ column_name=result_definition.name
82
+ )
83
+ for idx_row, row in df.iterrows():
84
+ for test_id, result in row.items():
85
+ records.append(
86
+ dict(
87
+ case_name=case_name,
88
+ result_name=result_definition.name,
89
+ test_id=test_id,
90
+ x=self.cpt_locations[test_id].x,
91
+ y=self.cpt_locations[test_id].y,
92
+ pile_tip_level_nap=idx_row,
93
+ result=result,
94
+ result_unit=result_definition.value.unit,
95
+ )
96
+ )
97
+ self._cpt_results_dataframe = pd.DataFrame.from_records(records)
98
+
99
+ def _set_cpt_group_results_dataframe(
100
+ self, result_cases: Dict[Hashable, MultiCPTBearingResults]
101
+ ) -> None:
102
+ """Private method to create and set the property `cpt_group_results_dataframe`."""
103
+ records = []
104
+ for case_name, case_results in result_cases.items():
105
+ df = case_results.group_results_table.to_pandas()
106
+ for result_definition in CPTGroupResultDefinitions:
107
+ for _, row in df.iterrows():
108
+ records.append(
109
+ dict(
110
+ case_name=case_name,
111
+ result_name=result_definition.name,
112
+ pile_tip_level_nap=row["pile_tip_level_nap"],
113
+ result=row[result_definition.value.name],
114
+ result_unit=result_definition.value.unit,
115
+ )
116
+ )
117
+ self._cpt_group_results_dataframe = pd.DataFrame.from_records(records)
118
+
119
+ def _set_cpt_locations(self, value: Dict[str, Location]) -> None:
120
+ """Private setter for `cpt_locations`."""
121
+ # Check data types
122
+ if not isinstance(value, dict):
123
+ raise TypeError(
124
+ f"Expected type 'List[CPTData]' for 'cpt_locations', but got {type(value)}"
125
+ )
126
+
127
+ if not all(isinstance(k, str) for k in value.keys()):
128
+ raise TypeError(
129
+ f"Expected type 'str' for keys of 'cpt_locations', but got {(type(k) for k in value.keys())}"
130
+ )
131
+
132
+ if not all(isinstance(v, Location) for v in value.values()):
133
+ raise TypeError(
134
+ f"Expected type 'Location' for values of 'cpt_locations', but got {(type(v) for v in value.values())}"
135
+ )
136
+
137
+ # Check that all the `test_id`s used in the MultiCPTBearingResults objects are in the keys.
138
+ if not all(test_id in value.keys() for test_id in self.test_ids):
139
+ missing_test_ids = [
140
+ test_id for test_id in self.test_ids if test_id not in value.keys()
141
+ ]
142
+ raise ValueError(
143
+ "Not all `test_id`s used in the MultiCPTBearingResults objects are in the keys of `cpt_locations`. "
144
+ + f"The following `test_id`s are missing: {missing_test_ids}"
145
+ )
146
+
147
+ self._cpt_locations = value
148
+
149
+ @property
150
+ def cases(self) -> List[Hashable]:
151
+ """The case names."""
152
+ return self._cases
153
+
154
+ @property
155
+ def multicpt_bearing_results(self) -> List[MultiCPTBearingResults]:
156
+ """The MultiCPTBearingResults objects."""
157
+ return self._multicpt_bearing_results
158
+
159
+ @property
160
+ def test_ids(self) -> List[str]:
161
+ """The test ids of all MultiCPTBearingResults objects."""
162
+ return self._test_ids
163
+
164
+ @property
165
+ def pile_tip_levels_nap(self) -> List[float]:
166
+ """The pile tip levels NAP of all MultiCPTBearingResults objects."""
167
+ return self._pile_tip_levels_nap
168
+
169
+ @property
170
+ def cpt_locations(self) -> Dict[str, Location]:
171
+ """The mapping between `test_id` (key) and the `location` (value) of the cpt."""
172
+ return self._cpt_locations
173
+
174
+ @property
175
+ def cpt_results_dataframe(self) -> pd.DataFrame:
176
+ """
177
+ The dataframe with all the CPT results.
178
+ Available columns: case_name, result_name, test_id, x, y, pile_tip_level_nap, result, result_unit.
179
+ """
180
+ return self._cpt_results_dataframe
181
+
182
+ @property
183
+ def cpt_group_results_dataframe(self) -> pd.DataFrame:
184
+ """
185
+ The dataframe with CPT group results.
186
+ Available columns: case_name, result_name, pile_tip_level_nap, result, result_unit.
187
+ """
188
+ return self._cpt_group_results_dataframe
189
+
190
+
191
+ def _validate_results_per_case(
192
+ results_per_case: Dict[Hashable, MultiCPTBearingResults]
193
+ ) -> None:
194
+ """
195
+ Private method to validate the results_per_case dictionary.
196
+
197
+ Parameters
198
+ ----------
199
+ results_per_case : Dict[Hashable, MultiCPTBearingResults]
200
+ A dictionary with the results of multiple cases of MultiCPTBearingResults.
201
+ The keys of the dictionary are the case names.
202
+ All MultiCPTBearingResults objects must have the same pile tip levels and same test ids.
203
+
204
+ Raises
205
+ ------
206
+ TypeError
207
+ If `results_per_case` is not of the expected type.
208
+ ValueError
209
+ If `results_per_case` is an empty dictionary.
210
+ If not all MultiCPTBearingResults objects have the same pile tip levels and test ids.
211
+ """
212
+ if not isinstance(results_per_case, dict):
213
+ raise TypeError(
214
+ f"Expected type 'Dict[Hashable, MultiCPTBearingResults]' for 'results_per_case', but got {type(results_per_case)}"
215
+ )
216
+
217
+ if len(results_per_case) == 0:
218
+ raise ValueError("Empty dictionary 'results_per_case' is not allowed.")
219
+
220
+ for val in results_per_case.values():
221
+ if not isinstance(val, MultiCPTBearingResults):
222
+ raise TypeError(
223
+ f"Expected type 'MultiCPTBearingResults' for items in 'results_per_case', but got {type(val)}"
224
+ )
225
+
226
+ test_ids = results_per_case[list(results_per_case.keys())[0]].cpt_results.test_ids
227
+ pile_tip_levels_nap = list(
228
+ results_per_case[list(results_per_case.keys())[0]]
229
+ .cpt_results.to_pandas()
230
+ .pile_tip_level_nap.unique()
231
+ )
232
+ for results in results_per_case.values():
233
+ if results.cpt_results.test_ids != test_ids:
234
+ raise ValueError(
235
+ "All MultiCPTBearingResults objects must have the same test ids."
236
+ )
237
+
238
+ if (
239
+ list(results.cpt_results.to_pandas().pile_tip_level_nap.unique())
240
+ != pile_tip_levels_nap
241
+ ):
242
+ raise ValueError(
243
+ "All MultiCPTBearingResults objects must have the same pile tip levels."
244
+ )