py-pilecore 0.5.1__py3-none-any.whl → 0.7.0__py3-none-any.whl

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.

@@ -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,7 +37,10 @@ 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: docs
42
45
  Requires-Dist: Sphinx ==6.1.3 ; extra == 'docs'
43
46
  Requires-Dist: sphinx-autodoc-typehints ==1.22 ; extra == 'docs'
@@ -45,25 +48,20 @@ Requires-Dist: ipython ==8.11.0 ; extra == 'docs'
45
48
  Requires-Dist: asteroid-sphinx-theme ==0.0.3 ; extra == 'docs'
46
49
  Requires-Dist: sphinx-rtd-theme ==1.2.0 ; extra == 'docs'
47
50
  Provides-Extra: lint
48
- Requires-Dist: mypy ==1.6.1 ; extra == 'lint'
49
- Requires-Dist: mypy-extensions ==1.0.0 ; extra == 'lint'
50
- Requires-Dist: tomli ==2.0.1 ; extra == 'lint'
51
- Requires-Dist: typing-extensions ==4.7.1 ; extra == 'lint'
52
- Requires-Dist: black[jupyter] ==23.10.1 ; extra == 'lint'
53
- Requires-Dist: click ==8.1.3 ; extra == 'lint'
54
- Requires-Dist: packaging ==23.2 ; extra == 'lint'
55
- Requires-Dist: pathspec ==0.11.1 ; extra == 'lint'
56
- Requires-Dist: platformdirs ==3.5.1 ; extra == 'lint'
57
- Requires-Dist: isort ==5.12.0 ; extra == 'lint'
51
+ Requires-Dist: ansible-lint ==6.22.1 ; extra == 'lint'
52
+ Requires-Dist: black ==23.11.0 ; extra == 'lint'
53
+ Requires-Dist: cfn-lint ==0.83.3 ; extra == 'lint'
54
+ Requires-Dist: cpplint ==1.6.1 ; extra == 'lint'
58
55
  Requires-Dist: flake8 ==6.0.0 ; extra == 'lint'
59
- Requires-Dist: mccabe ==0.7.0 ; extra == 'lint'
60
- Requires-Dist: pycodestyle ==2.10.0 ; extra == 'lint'
61
- Requires-Dist: pyflakes ==3.0.1 ; extra == 'lint'
62
- Requires-Dist: pandas-stubs <3,>2 ; extra == 'lint'
63
- Requires-Dist: types-tqdm <5,>4 ; extra == 'lint'
56
+ Requires-Dist: isort ==5.12.0 ; extra == 'lint'
57
+ Requires-Dist: mypy ==1.7.1 ; extra == 'lint'
58
+ Requires-Dist: sqlfluff ==2.3.5 ; extra == 'lint'
59
+ Requires-Dist: yamllint ==1.33.0 ; extra == 'lint'
60
+ Requires-Dist: yq ==3.2.3 ; extra == 'lint'
64
61
  Provides-Extra: test
65
62
  Requires-Dist: coveralls ; extra == 'test'
66
63
  Requires-Dist: pytest ; extra == 'test'
64
+ Requires-Dist: openapi-core ; extra == 'test'
67
65
 
68
66
  # py-pilecore
69
67
  Public python SDK for the CEMS PileCore web-API
@@ -99,7 +97,7 @@ Go to `personal-access-tokens` and create a new user token.
99
97
 
100
98
  ## Environment
101
99
 
102
- 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:
103
101
 
104
102
  Example using `virtualenv` and `pip` to install the dependencies in a new environment .env on Linux:
105
103
 
@@ -151,7 +149,7 @@ coverage run -m pytest
151
149
 
152
150
  ## Requirements
153
151
 
154
- 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
155
153
 
156
154
  Install pip-tools with:
157
155
 
@@ -1,5 +1,5 @@
1
1
  pypilecore/__init__.py,sha256=oJvwYShj_7FyNVlUgQda4tTdYyLIi5H1asdiS_uYt9M,162
2
- pypilecore/_version.py,sha256=qHUIQ-gDL6kMjSnoprXjr-A8s8rwQzYqD2YFXvLDtHs,175
2
+ pypilecore/_version.py,sha256=MCrXa9Xoh2jGlyzUGX0O346XcUwgg1UzXaK6GJAguWs,175
3
3
  pypilecore/api.py,sha256=QwwHXR6HYtrF-gCHQWLvMHZnTxf5fjTlWI2cGfYSkUc,7165
4
4
  pypilecore/exceptions.py,sha256=-MZOfsxyHLCI0k1-wZFfVsMxc1lya5buuhLks5rxlCo,89
5
5
  pypilecore/plot_utils.py,sha256=rK5_067-4-x7LzZgt_t6ahcGrZInxNrqHqsy0RzCnq8,954
@@ -16,18 +16,29 @@ pypilecore/common/piles/geometry/components/common.py,sha256=scYoF-4aE0Wknx9GgSO
16
16
  pypilecore/common/piles/geometry/components/rectangle.py,sha256=591KyIejyjNAMnKg8yThFjbrPXAVHQdf08vaiQYHZdk,18411
17
17
  pypilecore/common/piles/geometry/components/round.py,sha256=MX2_qGmxr1dTtodblFfkNGkoDYqd6xgXHJ57xFuz_Z0,14735
18
18
  pypilecore/input/__init__.py,sha256=Gyqsp6zqc8AYnIp17SfqbBNjDaUkRgAam8x2r0XibwM,492
19
- pypilecore/input/grouper_properties.py,sha256=qOc-SNYSPdOcZZ9DsRE-sBNVOKHbUD044EWRsWDu_kc,10893
19
+ pypilecore/input/grouper_properties.py,sha256=4Rhea8pnrbWqIIiplHdPS-EioDRurCcLe6thHkGkBEM,11146
20
20
  pypilecore/input/multi_cpt.py,sha256=V7A_MAYeJoMkGOQu1oFGJfJ3dkuBdhDSfeLvgiCLmqs,14196
21
- pypilecore/input/soil_properties.py,sha256=VZHGGmns768XPLjMTVwQDpy3f0LDFG0AwbKVfm3xKWc,7993
22
- pypilecore/results/__init__.py,sha256=ggTI2QzILhX_oNx1YMOih6IVCkBFg8I5-Jyn9Sw3_h0,389
21
+ pypilecore/input/soil_properties.py,sha256=ms2zxRPK_0zJAgei4QTJhC71Y7ivUguqoRTDUzuqyl8,8277
22
+ pypilecore/results/__init__.py,sha256=J6CHQ7BJRnUJxrKFe25br-BUCMrBATqmvRkjtaMkmkw,507
23
+ pypilecore/results/cases_multi_cpt_results.py,sha256=Svy26fEMuSLPzD0hdq3-aQD-6TK0oyAERkVQZFPcXrE,9948
23
24
  pypilecore/results/grouper_result.py,sha256=HcjLbnD3wt28CtIACD1OSoyJRmfu5x8Qv2BdDMpvgyY,30952
24
25
  pypilecore/results/load_settlement.py,sha256=EbfTrSvH_g96KE-x8ZjmO8D0mt5KFaQ_-AR8u4blLsU,9752
25
26
  pypilecore/results/multi_cpt_results.py,sha256=dCV2VTRuReCt8J1MAfjqgboq2nNJ7r2OPPJ9DqTp4Io,30943
26
27
  pypilecore/results/post_processing.py,sha256=UWXcdff5dhPFDwzKbVIayEIp3HX6pxW8oQR3Z7AHPn0,22262
28
+ pypilecore/results/result_definitions.py,sha256=Nb6AaJ6n5bVeC5awB1h-HO43_pknFVAZm-g5Zr8fpBU,8027
27
29
  pypilecore/results/single_cpt_results.py,sha256=37zzsAO60JQX44cbqHoZgkdGdGIC_HvxM9em-oldo7o,17459
28
30
  pypilecore/results/soil_properties.py,sha256=UfPdB3L1fCjp7iDr7b0iUs_RDBi8WhSPngF8rtfxqdo,20744
29
- py_pilecore-0.5.1.dist-info/LICENSE,sha256=3OCAZXffN0Bettjeya8uF_ZYegyvvCfH1WUt6CrHb_0,1061
30
- py_pilecore-0.5.1.dist-info/METADATA,sha256=OfOdXssrUV1zAUbyIVrqUhTY8O3wl9G9zaPDZPB8Z6o,5832
31
- py_pilecore-0.5.1.dist-info/WHEEL,sha256=cVxcB9AmuTcXqmwrtPhNK88dr7IR_b6qagTj0UvIEbY,91
32
- py_pilecore-0.5.1.dist-info/top_level.txt,sha256=7BKIWZuSkbQtJ0ho5P1JvcaEbHzqADCcBuOduZmIaiI,11
33
- py_pilecore-0.5.1.dist-info/RECORD,,
31
+ pypilecore/viewers/__init__.py,sha256=GjPAj7O_L5QsK2fhewi7yd5fZnbYeCvauDAD37I20Rg,330
32
+ pypilecore/viewers/viewer_cpt_group_results.py,sha256=iVwvm4JZeJ9v3r9Q5uWBAYJ7RQaYkQF0WOX0uUFMTgo,2530
33
+ pypilecore/viewers/viewer_cpt_results.py,sha256=EN9Qq8gGdvIz9rTuazmtVwLyI6NqcuzHv1gz2S3sgng,2956
34
+ pypilecore/viewers/viewer_cpt_results_plan_view.py,sha256=J1KOyUiG0tJJdpTAdEKYM-7aBhp9Kh4l-ceZnoOfqsA,3647
35
+ pypilecore/viewers/interactive_figures/__init__.py,sha256=u6fkLqDB35J2bdGvUewzRC8UEQUFF6AoXxR-_v8AX0A,481
36
+ pypilecore/viewers/interactive_figures/figure_cpt_group_results_versus_ptls.py,sha256=RzNOYQmP_yT8oYeIMW9aYNl7aAKU-uFQfygxP9AwDsU,6471
37
+ pypilecore/viewers/interactive_figures/figure_cpt_results_plan_view.py,sha256=y1no2w0zN0yUpkNB_-WAFwQfa-IS70hJMhc-c0pOeMs,9268
38
+ pypilecore/viewers/interactive_figures/figure_cpt_results_versus_ptls.py,sha256=6huCKcQ4bsBE-LNY-ZPa13IWuye0ENxPK4wT1dcCFRs,5964
39
+ pypilecore/viewers/interactive_figures/utils.py,sha256=Wl5hNsTdgh6wPm_sVGg1bfKamHzGnVNpuepgOg-oOFY,1582
40
+ py_pilecore-0.7.0.dist-info/LICENSE,sha256=3OCAZXffN0Bettjeya8uF_ZYegyvvCfH1WUt6CrHb_0,1061
41
+ py_pilecore-0.7.0.dist-info/METADATA,sha256=aBHbPcfhifQUyeFmdyn5cg5C6H3ZSnCbe17THb9VBzI,5653
42
+ py_pilecore-0.7.0.dist-info/WHEEL,sha256=GV9aMThwP_4oNCtvEC2ec3qUYutgWeAzklro_0m4WJQ,91
43
+ py_pilecore-0.7.0.dist-info/top_level.txt,sha256=7BKIWZuSkbQtJ0ho5P1JvcaEbHzqADCcBuOduZmIaiI,11
44
+ py_pilecore-0.7.0.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (74.1.2)
2
+ Generator: setuptools (75.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5
 
pypilecore/_version.py CHANGED
@@ -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
+ )
@@ -0,0 +1,195 @@
1
+ from __future__ import annotations # noqa: F404
2
+
3
+ from dataclasses import dataclass
4
+ from enum import Enum
5
+ from typing import List
6
+
7
+ from natsort import natsorted
8
+
9
+
10
+ @dataclass
11
+ class ResultDefinition:
12
+ """
13
+ Dataclass containing the name, units and html representation of a result.
14
+ """
15
+
16
+ name: str
17
+ """The name of the result."""
18
+ unit: str
19
+ """The unit of the result."""
20
+ html: str
21
+ """The html representation of the result"""
22
+
23
+ def __post_init__(self) -> None:
24
+ """
25
+ Method to validate the input types of the dataclass.
26
+
27
+ Raises
28
+ ------
29
+ ValueError
30
+ If the input types are not correct.
31
+ """
32
+ if not isinstance(self.name, str):
33
+ raise TypeError(
34
+ f"Expected type 'str' for 'name', but got {type(self.name)}"
35
+ )
36
+ if not isinstance(self.unit, str):
37
+ raise TypeError(
38
+ f"Expected type 'str' for 'unit', but got {type(self.unit)}"
39
+ )
40
+
41
+ if not isinstance(self.html, str):
42
+ raise TypeError(
43
+ f"Expected type 'str' for 'html', but got {type(self.html)}"
44
+ )
45
+
46
+
47
+ class CPTResultDefinitions(Enum):
48
+ """
49
+ Enumeration of available CPT result definitions.
50
+ """
51
+
52
+ F_nk_cal = ResultDefinition(name="F_nk_cal", unit="kN", html="F<sub>nk;cal</sub>")
53
+ F_nk_k = ResultDefinition(name="F_nk_k", unit="kN", html="F<sub>nk;k</sub>")
54
+ F_nk_d = ResultDefinition(name="F_nk_d", unit="kN", html="F<sub>nk;d</sub>")
55
+ R_b_cal = ResultDefinition(name="R_b_cal", unit="kN", html="R<sub>b;cal</sub>")
56
+ R_b_k = ResultDefinition(name="R_b_k", unit="kN", html="R<sub>b;k</sub>")
57
+ R_b_d = ResultDefinition(name="R_b_d", unit="kN", html="R<sub>b;d</sub>")
58
+ R_s_cal = ResultDefinition(name="R_s_cal", unit="kN", html="R<sub>s;cal</sub>")
59
+ R_s_k = ResultDefinition(name="R_s_k", unit="kN", html="R<sub>s;k</sub>")
60
+ R_s_d = ResultDefinition(name="R_s_d", unit="kN", html="R<sub>s;d</sub>")
61
+ R_c_cal = ResultDefinition(name="R_c_cal", unit="kN", html="R<sub>c;cal</sub>")
62
+ R_c_k = ResultDefinition(name="R_c_k", unit="kN", html="R<sub>c;k</sub>")
63
+ R_c_d = ResultDefinition(name="R_c_d", unit="kN", html="R<sub>c;d</sub>")
64
+ R_c_d_net = ResultDefinition(
65
+ name="R_c_d_net",
66
+ unit="kN",
67
+ html="R<sub>c;d;net</sub>",
68
+ )
69
+ F_c_k = ResultDefinition(name="F_c_k", unit="kN", html="F<sub>c;k</sub>")
70
+ F_c_k_tot = ResultDefinition(
71
+ name="F_c_k_tot",
72
+ unit="kN",
73
+ html="F<sub>c;k;tot</sub>",
74
+ )
75
+ negative_friction_range_nap_top = ResultDefinition(
76
+ name="negative_friction_range_nap_top",
77
+ unit="m NAP",
78
+ html="Top of negative friction",
79
+ )
80
+ negative_friction_range_nap_btm = ResultDefinition(
81
+ name="negative_friction_range_nap_btm",
82
+ unit="m NAP",
83
+ html="Bottom of negative friction",
84
+ )
85
+ positive_friction_range_nap_top = ResultDefinition(
86
+ name="positive_friction_range_nap_top",
87
+ unit="m NAP",
88
+ html="Top of positive friction",
89
+ )
90
+ positive_friction_range_nap_btm = ResultDefinition(
91
+ name="positive_friction_range_nap_btm",
92
+ unit="m NAP",
93
+ html="Bottom of positive friction",
94
+ )
95
+ q_b_max = ResultDefinition(name="q_b_max", unit="MPa", html="q<sub>b;max</sub>")
96
+ q_s_max_mean = ResultDefinition(
97
+ name="q_s_max_mean",
98
+ unit="MPa",
99
+ html="q<sub>s;max</sub>",
100
+ )
101
+ qc1 = ResultDefinition(name="qc1", unit="MPa", html="q<sub>c1</sub>")
102
+ qc2 = ResultDefinition(name="qc2", unit="MPa", html="q<sub>c2</sub>")
103
+ qc3 = ResultDefinition(name="qc3", unit="MPa", html="q<sub>c3</sub>")
104
+ s_b = ResultDefinition(name="s_b", unit="mm", html="s<sub>b</sub>")
105
+ s_el = ResultDefinition(name="s_el", unit="mm", html="s<sub>el</sub>")
106
+ k_v_b = ResultDefinition(name="k_v_b", unit="MN/m", html="k<sub>v;b</sub>")
107
+ k_v_1 = ResultDefinition(name="k_v_1", unit="MN/m", html="k<sub>v;1</sub>")
108
+
109
+ @classmethod
110
+ def get(cls, name: str) -> CPTResultDefinitions:
111
+ """Returns the result definition the given name."""
112
+ try:
113
+ return cls[name]
114
+ except KeyError:
115
+ raise ValueError(
116
+ f"Result with name '{name}' not found in 'CPTResultDefinitions'."
117
+ )
118
+
119
+ @classmethod
120
+ def natsorted_names(cls) -> List[str]:
121
+ """Returns the names of the enum in natsorted order."""
122
+ return natsorted([r.name for r in cls])
123
+
124
+
125
+ class CPTGroupResultDefinitions(Enum):
126
+ R_s_k = ResultDefinition(name="R_s_k", unit="kN", html="R<sub>s;k</sub>")
127
+ R_b_k = ResultDefinition(name="R_b_k", unit="kN", html="R<sub>b;k</sub>")
128
+ R_c_k = ResultDefinition(name="R_c_k", unit="kN", html="R<sub>c;k</sub>")
129
+ R_s_d = ResultDefinition(name="R_s_d", unit="kN", html="R<sub>s;d</sub>")
130
+ R_b_d = ResultDefinition(name="R_b_d", unit="kN", html="R<sub>b;d</sub>")
131
+ R_c_d = ResultDefinition(name="R_c_d", unit="kN", html="R<sub>c;d</sub>")
132
+ F_nk_cal_mean = ResultDefinition(
133
+ name="F_nk_cal_mean", unit="kN", html="F<sub>nk;cal;mean</sub>"
134
+ )
135
+ F_nk_k = ResultDefinition(name="F_nk_k", unit="kN", html="F<sub>nk;k</sub>")
136
+ F_nk_d = ResultDefinition(name="F_nk_d", unit="kN", html="F<sub>nk;d</sub>")
137
+ R_c_d_net = ResultDefinition(
138
+ name="R_c_d_net",
139
+ unit="kN",
140
+ html="R<sub>c;d;net</sub>",
141
+ )
142
+ F_c_k = ResultDefinition(name="F_c_k", unit="kN", html="F<sub>c;k</sub>")
143
+ F_c_k_tot = ResultDefinition(
144
+ name="F_c_k_tot",
145
+ unit="kN",
146
+ html="F<sub>c;k;tot</sub>",
147
+ )
148
+ s_b = ResultDefinition(name="s_b", unit="mm", html="s<sub>b</sub>")
149
+ s_e = ResultDefinition(name="s_e", unit="mm", html="s<sub>e</sub>")
150
+ s_e_mean = ResultDefinition(name="s_e_mean", unit="mm", html="s<sub>e;mean</sub>")
151
+ R_b_mob_ratio = ResultDefinition(
152
+ name="R_b_mob_ratio", unit="-", html="R<sub>b;mob;ratio</sub>"
153
+ )
154
+ R_s_mob_ratio = ResultDefinition(
155
+ name="R_s_mob_ratio", unit="-", html="R<sub>s;mob;ratio</sub>"
156
+ )
157
+ k_v_b = ResultDefinition(name="k_v_b", unit="MN/m", html="k<sub>v;b</sub>")
158
+ k_v_1 = ResultDefinition(name="k_v_1", unit="MN/m", html="k<sub>v;1</sub>")
159
+ R_c_min = ResultDefinition(name="R_c_min", unit="kN", html="R<sub>c;min</sub>")
160
+ R_c_max = ResultDefinition(name="R_c_max", unit="kN", html="R<sub>c;max</sub>")
161
+ R_c_mean = ResultDefinition(name="R_c_mean", unit="kN", html="R<sub>c;mean</sub>")
162
+ R_c_std = ResultDefinition(name="R_c_std", unit="kN", html="R<sub>c;std</sub>")
163
+ R_s_mean = ResultDefinition(name="R_s_mean", unit="kN", html="R<sub>s;mean</sub>")
164
+ R_b_mean = ResultDefinition(name="R_b_mean", unit="kN", html="R<sub>b;mean</sub>")
165
+ var_coef = ResultDefinition(name="var_coef", unit="%", html="Variation coefficient")
166
+ n_cpts = ResultDefinition(name="n_cpts", unit="-", html="Number of CPTs")
167
+ use_group_average = ResultDefinition(
168
+ name="use_group_average", unit="-", html="Use group average"
169
+ )
170
+ xi_normative = ResultDefinition(name="xi_normative", unit="-", html="Normative ξ")
171
+ xi_value = ResultDefinition(name="xi_value", unit="-", html="ξ<sub>value</sub>")
172
+ cpt_Rc_min = ResultDefinition(
173
+ name="cpt_Rc_min", unit="-", html="CPT with R<sub>c;min</sub>"
174
+ )
175
+ cpt_Rc_max = ResultDefinition(
176
+ name="cpt_Rc_max", unit="-", html="CPT with R<sub>c;max</sub>"
177
+ )
178
+ cpt_normative = ResultDefinition(
179
+ name="cpt_normative", unit="-", html="Normative CPT"
180
+ )
181
+
182
+ @classmethod
183
+ def get(cls, name: str) -> CPTGroupResultDefinitions:
184
+ """Returns the result definition given the name."""
185
+ try:
186
+ return cls[name]
187
+ except KeyError:
188
+ raise ValueError(
189
+ f"Result with name '{name}' not found in 'CPTGroupResultDefinitions'."
190
+ )
191
+
192
+ @classmethod
193
+ def natsorted_names(cls) -> List[str]:
194
+ """Returns the names of the enum in natsorted order."""
195
+ return natsorted([r.name for r in cls])
@@ -0,0 +1,9 @@
1
+ from pypilecore.viewers.viewer_cpt_group_results import ViewerCptGroupResults
2
+ from pypilecore.viewers.viewer_cpt_results import ViewerCptResults
3
+ from pypilecore.viewers.viewer_cpt_results_plan_view import ViewerCptResultsPlanView
4
+
5
+ __all__ = [
6
+ "ViewerCptResults",
7
+ "ViewerCptResultsPlanView",
8
+ "ViewerCptGroupResults",
9
+ ]