geolysis 0.2.0__py3-none-any.whl → 0.4.2__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.
geolysis/__init__.py CHANGED
@@ -1,11 +1,3 @@
1
- from . import (
2
- bearing_capacity,
3
- constants,
4
- estimators,
5
- foundation,
6
- soil_classifier,
7
- spt,
8
- utils,
9
- )
10
-
11
- __version__ = "0.2.0"
1
+ from . import foundation, soil_classifier, spt, utils
2
+
3
+ __version__ = "0.4.2"
geolysis/foundation.py CHANGED
@@ -1,176 +1,326 @@
1
- from typing import TypeAlias
2
-
3
- from geolysis.utils import FloatOrInt
4
-
5
- __all__ = [
6
- "CircularFooting",
7
- "SquareFooting",
8
- "RectangularFooting",
9
- "FoundationSize",
10
- ]
11
-
12
-
13
- class CircularFooting:
14
- """
15
- Circular Footing Size.
16
-
17
- :param float diameter: Diameter of foundation footing. (m)
18
- """
19
-
20
- def __init__(self, diameter: FloatOrInt) -> None:
21
- self._diameter = diameter
22
-
23
- @property
24
- def diameter(self) -> FloatOrInt:
25
- """
26
- Diameter of foundation footing. (m)
27
- """
28
- return self._diameter
29
-
30
- @diameter.setter
31
- def diameter(self, __val: FloatOrInt):
32
- self._diameter = __val
33
-
34
- @property
35
- def width(self) -> FloatOrInt:
36
- """
37
- Diameter of foundation footing. (m)
38
- """
39
- return self._diameter
40
-
41
- @width.setter
42
- def width(self, __val: FloatOrInt):
43
- self.diameter = __val
44
-
45
-
46
- class SquareFooting:
47
- """
48
- Square Footing Size.
49
-
50
- :param SupportFloatOrIndex width: Width of foundation footing. (m)
51
- """
52
-
53
- def __init__(self, width: FloatOrInt):
54
- self._width = width
55
- self._length = width
56
-
57
- @property
58
- def width(self) -> FloatOrInt:
59
- """
60
- Width of foundation footing. (m)
61
- """
62
- return self._width
63
-
64
- @width.setter
65
- def width(self, __val: FloatOrInt):
66
- self._width = __val
67
- self._length = __val
68
-
69
- @property
70
- def length(self) -> FloatOrInt:
71
- """
72
- Length of foundation footing. (m)
73
- """
74
- return self._length
75
-
76
- @length.setter
77
- def length(self, __val: FloatOrInt):
78
- self.width = __val # This will set the _width and _length attributes
79
-
80
-
81
- class RectangularFooting:
82
- """
83
- Rectangular Footing Size.
84
-
85
- :param SupportFloatOrIndex length: Length of foundation footing. (m)
86
- :param SupportFloatOrIndex width: Width of foundation footing. (m)
87
- """
88
-
89
- def __init__(
90
- self,
91
- width: FloatOrInt,
92
- length=FloatOrInt,
93
- ) -> None:
94
- self._width = width
95
- self._length = length
96
-
97
- @property
98
- def width(self) -> FloatOrInt:
99
- """
100
- Width of foundation footing. (m)
101
- """
102
- return self._width
103
-
104
- @width.setter
105
- def width(self, __val: FloatOrInt):
106
- self._width = __val
107
-
108
- @property
109
- def length(self) -> FloatOrInt:
110
- """
111
- Length of foundation footing. (m)
112
- """
113
- return self._length
114
-
115
- @length.setter
116
- def length(self, __val: FloatOrInt):
117
- self._length = __val
118
-
119
-
120
- _FootingShape: TypeAlias = SquareFooting | RectangularFooting | CircularFooting
121
-
122
-
123
- class FoundationSize:
124
- """
125
- A simple class representing a foundation structure.
126
-
127
- :param float depth: Depth of foundation footing. (m)
128
- :param FootingShape footing_shape: Represents the shape of the foundation footing.
129
- """
130
-
131
- def __init__(
132
- self,
133
- depth: FloatOrInt,
134
- footing_shape: _FootingShape,
135
- ) -> None:
136
- self._depth = depth
137
- self.footing_shape = footing_shape
138
-
139
- @property
140
- def depth(self) -> FloatOrInt:
141
- """
142
- Depth of foundation footing. (m)
143
- """
144
- return self._depth
145
-
146
- @depth.setter
147
- def depth(self, __val: FloatOrInt):
148
- self._depth = __val
149
-
150
- @property
151
- def width(self) -> FloatOrInt:
152
- """
153
- Width of foundation footing. (m)
154
- """
155
- return self.footing_shape.width
156
-
157
- @width.setter
158
- def width(self, __val: FloatOrInt):
159
- self.footing_shape.width = __val
160
-
161
- @property
162
- def length(self) -> FloatOrInt:
163
- """
164
- Length of foundation footing. (m)
165
-
166
- :raises AttributeError: Raises error if footing shape does not have a length
167
- attribute.
168
- """
169
- if isinstance(self.footing_shape, (SquareFooting, RectangularFooting)):
170
- return self.footing_shape.length
171
-
172
- else:
173
- err_msg = (
174
- f"{type(self.footing_shape)} have no attribute named length"
175
- )
176
- raise AttributeError(err_msg)
1
+ import enum
2
+ from abc import abstractmethod
3
+ from typing import Optional, Protocol, TypeVar
4
+
5
+ from geolysis import validators
6
+ from geolysis.utils import inf
7
+
8
+ __all__ = ["create_foundation", "FoundationSize", "Shape", "StripFooting",
9
+ "CircularFooting", "SquareFooting", "RectangularFooting"]
10
+
11
+ T = TypeVar("T")
12
+
13
+
14
+ class _Field:
15
+ """A field that references another field."""
16
+
17
+ def __init__(self, *, ref_attr: str, ref_obj: Optional[str] = None,
18
+ doc: Optional[str] = None):
19
+ self.ref_attr = ref_attr
20
+ self.ref_obj = ref_obj
21
+ self.__doc__ = doc
22
+
23
+ def __get__(self, obj, objtype=None) -> T:
24
+ if self.ref_obj is not None:
25
+ ref_obj = getattr(obj, self.ref_obj)
26
+ return getattr(ref_obj, self.ref_attr)
27
+ return getattr(obj, self.ref_attr)
28
+
29
+ def __set__(self, obj, value) -> None:
30
+ if self.ref_obj is not None:
31
+ ref_obj = getattr(obj, self.ref_obj)
32
+ setattr(ref_obj, self.ref_attr, value)
33
+ else:
34
+ setattr(obj, self.ref_attr, value)
35
+
36
+ def __set_name__(self, objtype, property_name) -> None:
37
+ self.property_name = property_name
38
+
39
+
40
+ class Shape(enum.StrEnum):
41
+ """Enumeration of foundation shapes."""
42
+ STRIP = enum.auto()
43
+ CIRCLE = enum.auto()
44
+ SQUARE = enum.auto()
45
+ RECTANGLE = enum.auto()
46
+
47
+
48
+ class FootingSize(Protocol):
49
+ @property
50
+ @abstractmethod
51
+ def width(self) -> float: ...
52
+
53
+ @property
54
+ @abstractmethod
55
+ def length(self) -> float: ...
56
+
57
+ @property
58
+ @abstractmethod
59
+ def shape(self) -> Shape: ...
60
+
61
+
62
+ class StripFooting:
63
+ """A class representation of strip footing."""
64
+
65
+ def __init__(self, width: float, length: float = inf) -> None:
66
+ """
67
+ :param width: Width of foundation footing. (m)
68
+ :type width: float
69
+
70
+ :param float length: Length of foundation footing, defaults to inf. (m)
71
+ :type length: float
72
+ """
73
+ self.width = width
74
+ self.length = length
75
+ self._shape = Shape.STRIP
76
+
77
+ @property
78
+ def width(self) -> float:
79
+ return self._width
80
+
81
+ @width.setter
82
+ @validators.gt(0.0)
83
+ def width(self, val):
84
+ self._width = val
85
+
86
+ @property
87
+ def length(self) -> float:
88
+ return self._length
89
+
90
+ @length.setter
91
+ @validators.ge(0.0)
92
+ def length(self, val):
93
+ self._length = val
94
+
95
+ @property
96
+ def shape(self) -> Shape:
97
+ return self._shape
98
+
99
+
100
+ class CircularFooting:
101
+ """A class representation of circular footing.
102
+
103
+ .. note::
104
+
105
+ The ``width`` and ``length`` properties refer to the diameter of the
106
+ circular footing. This is to make it compatible with the protocol
107
+ square and rectangular footing follow.
108
+ """
109
+
110
+ _doc = "Refers to the diameter of the circular footing."
111
+
112
+ width = _Field(ref_attr="diameter", doc=_doc)
113
+ length = _Field(ref_attr="diameter", doc=_doc)
114
+
115
+ del _doc
116
+
117
+ def __init__(self, diameter: float):
118
+ """
119
+ :param float diameter: Diameter of foundation footing. (m)
120
+ """
121
+ self.diameter = diameter
122
+ self._shape = Shape.CIRCLE
123
+
124
+ @property
125
+ def diameter(self) -> float:
126
+ return self._diameter
127
+
128
+ @diameter.setter
129
+ @validators.gt(0.0)
130
+ def diameter(self, val):
131
+ self._diameter = val
132
+
133
+ @property
134
+ def shape(self) -> Shape:
135
+ return self._shape
136
+
137
+
138
+ class SquareFooting:
139
+ """A class representation of square footing."""
140
+
141
+ length = _Field(ref_attr="width",
142
+ doc="Refers to the width of the square footing.")
143
+
144
+ def __init__(self, width: float):
145
+ """
146
+ :param float width: Width of foundation footing. (m)
147
+ """
148
+ self.width = width
149
+ self._shape = Shape.SQUARE
150
+
151
+ @property
152
+ def width(self):
153
+ return self._width
154
+
155
+ @width.setter
156
+ @validators.gt(0)
157
+ def width(self, val):
158
+ self._width = val
159
+
160
+ @property
161
+ def shape(self):
162
+ return self._shape
163
+
164
+
165
+ class RectangularFooting:
166
+ """A class representation of rectangular footing."""
167
+
168
+ def __init__(self, width: float, length: float):
169
+ """
170
+ :param width: Width of foundation footing. (m)
171
+ :type width: float
172
+
173
+ :param length: Length of foundation footing. (m)
174
+ :type length: float
175
+ """
176
+ self.width = width
177
+ self.length = length
178
+ self._shape = Shape.RECTANGLE
179
+
180
+ @property
181
+ def width(self) -> float:
182
+ return self._width
183
+
184
+ @width.setter
185
+ @validators.gt(0.0)
186
+ def width(self, val):
187
+ self._width = val
188
+
189
+ @property
190
+ def length(self) -> float:
191
+ return self._length
192
+
193
+ @length.setter
194
+ @validators.gt(0.0)
195
+ def length(self, val):
196
+ self._length = val
197
+
198
+ @property
199
+ def shape(self) -> Shape:
200
+ return self._shape
201
+
202
+
203
+ class FoundationSize:
204
+ """A simple class representing a foundation structure."""
205
+
206
+ width = _Field(ref_attr="width", ref_obj="footing_size",
207
+ doc="Refers to the width of foundation footing.")
208
+ length = _Field(ref_attr="length", ref_obj="footing_size",
209
+ doc="Refers to the length of foundation footing.")
210
+ footing_shape = _Field(ref_attr="shape", ref_obj="footing_size",
211
+ doc="Refers to the shape of foundation footing.")
212
+
213
+ def __init__(self, depth: float, footing_size: FootingSize,
214
+ eccentricity: float = 0.0,
215
+ ground_water_level: float = inf) -> None:
216
+ """
217
+ :param depth: Depth of foundation. (m)
218
+ :type depth: float
219
+
220
+ :param footing_size: Represents the size of the foundation footing.
221
+ :type footing_size: FootingSize
222
+
223
+ :param eccentricity: The deviation of the foundation load from the
224
+ center of gravity of the foundation footing,
225
+ defaults to 0.0. This means that the foundation
226
+ load aligns with the center of gravity of the
227
+ foundation footing. (m)
228
+ :type eccentricity: float, optional
229
+
230
+ :param ground_water_level: Depth of the water below ground level (m),
231
+ defaults to inf.
232
+ :type ground_water_level: float, optional
233
+ """
234
+ self.depth = depth
235
+ self.footing_size = footing_size
236
+ self.eccentricity = eccentricity
237
+ self.ground_water_level = ground_water_level
238
+
239
+ @property
240
+ def depth(self) -> float:
241
+ return self._depth
242
+
243
+ @depth.setter
244
+ @validators.gt(0.0)
245
+ def depth(self, val: float) -> None:
246
+ self._depth = val
247
+
248
+ @property
249
+ def eccentricity(self) -> float:
250
+ return self._eccentricity
251
+
252
+ @eccentricity.setter
253
+ @validators.ge(0.0)
254
+ def eccentricity(self, val: float) -> None:
255
+ self._eccentricity = val
256
+
257
+ @property
258
+ def ground_water_level(self) -> float:
259
+ return self._ground_water_level
260
+
261
+ @ground_water_level.setter
262
+ @validators.ge(0.0)
263
+ def ground_water_level(self, val: float) -> None:
264
+ self._ground_water_level = val
265
+
266
+ @property
267
+ def effective_width(self) -> float:
268
+ """Returns the effective width of the foundation footing."""
269
+ return self.width - 2.0 * self.eccentricity
270
+
271
+
272
+ def create_foundation(depth: float, width: float,
273
+ length: Optional[float] = None,
274
+ eccentricity: float = 0.0,
275
+ ground_water_level: float = inf,
276
+ shape: Shape | str = Shape.SQUARE) -> FoundationSize:
277
+ """A factory function that encapsulate the creation of a foundation.
278
+
279
+ :param depth: Depth of foundation. (m)
280
+ :type depth: float
281
+
282
+ :param width: Width of foundation footing. In the case of a circular
283
+ footing, it refers to the footing diameter. (m)
284
+ :type width: float
285
+
286
+ :param length: Length of foundation footing, defaults to None. (m)
287
+ :type length: float, optional
288
+
289
+ :param eccentricity: The deviation of the foundation load from the
290
+ center of gravity of the foundation footing,
291
+ defaults to 0.0. This means that the foundation
292
+ load aligns with the center of gravity of the
293
+ foundation footing. (m)
294
+ :type eccentricity: float, optional
295
+
296
+ :param ground_water_level: Depth of the water below ground level (m),
297
+ defaults to inf.
298
+ :type ground_water_level: float, optional
299
+
300
+ :param shape: Shape of foundation footing, defaults to :class:`Shape.SQUARE`
301
+ :type shape: Shape | str
302
+
303
+ :raises ValueError: Raised when length is not provided for a rectangular
304
+ footing.
305
+ :raises TypeError: Raised if an invalid footing shape is provided.
306
+ """
307
+
308
+ if isinstance(shape, str):
309
+ shape = Shape(shape.casefold())
310
+
311
+ if shape is Shape.STRIP:
312
+ footing_size = StripFooting(width=width)
313
+ elif shape is Shape.SQUARE:
314
+ footing_size = SquareFooting(width=width)
315
+ elif shape is Shape.CIRCLE:
316
+ footing_size = CircularFooting(diameter=width)
317
+ elif shape is Shape.RECTANGLE:
318
+ if not length:
319
+ raise ValueError("Length of footing must be provided.")
320
+ footing_size = RectangularFooting(width=width, length=length)
321
+ else:
322
+ raise TypeError(f"shape {shape} is not supported.")
323
+
324
+ return FoundationSize(depth=depth, eccentricity=eccentricity,
325
+ ground_water_level=ground_water_level,
326
+ footing_size=footing_size)