Skip to content

Commit 9dde205

Browse files
authored
Merge pull request #3 from lachlangrose/copilot/fix-8cde58d8-18e8-4afa-9a04-ba3a50f409ee
docs: Comprehensive numpy docstring format review and enhancement
2 parents 50887f6 + f999217 commit 9dde205

11 files changed

Lines changed: 834 additions & 149 deletions

File tree

LoopStructural/__init__.py

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,21 @@
2323
loggers = {}
2424
@dataclass
2525
class LoopStructuralConfig:
26-
"""
27-
Configuration for LoopStructural
26+
"""Configuration for LoopStructural package.
27+
28+
This dataclass holds configuration parameters for the LoopStructural
29+
geological modelling package.
30+
31+
Parameters
32+
----------
33+
nelements : int, optional
34+
The default number of elements to use in interpolation, by default 10_000
35+
36+
Examples
37+
--------
38+
>>> config = LoopStructuralConfig(nelements=50000)
39+
>>> config.nelements
40+
50000
2841
"""
2942

3043
nelements: int = 10_000
@@ -42,15 +55,21 @@ class LoopStructuralConfig:
4255

4356

4457
def setLogging(level="info", handler=None):
45-
"""
46-
Set the logging parameters for log file or custom handler
58+
"""Set the logging parameters for log file or custom handler.
4759
4860
Parameters
4961
----------
50-
level : str
51-
'info', 'warning', 'error', 'debug'
62+
level : str, optional
63+
Logging level to set, by default "info"
64+
Valid options: 'info', 'warning', 'error', 'debug'
5265
handler : logging.Handler, optional
53-
A logging handler to use instead of the default StreamHandler
66+
A logging handler to use instead of the default StreamHandler, by default None
67+
68+
Examples
69+
--------
70+
>>> import LoopStructural
71+
>>> LoopStructural.setLogging('debug')
72+
>>> LoopStructural.setLogging('info', logging.FileHandler('loop.log'))
5473
"""
5574
import LoopStructural
5675

LoopStructural/datatypes/_bounding_box.py

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,10 +82,24 @@ def __init__(
8282

8383
@property
8484
def global_origin(self):
85+
"""Get the global origin of the bounding box.
86+
87+
Returns
88+
-------
89+
np.ndarray
90+
The global origin coordinates
91+
"""
8592
return self._global_origin
8693

8794
@global_origin.setter
8895
def global_origin(self, global_origin):
96+
"""Set the global origin of the bounding box.
97+
98+
Parameters
99+
----------
100+
global_origin : array_like
101+
The global origin coordinates
102+
"""
89103
if self.dimensions != len(global_origin):
90104
logger.warning(
91105
f"Global origin has {len(global_origin)} dimensions but bounding box has {self.dimensions}"
@@ -94,20 +108,53 @@ def global_origin(self, global_origin):
94108

95109
@property
96110
def global_maximum(self):
111+
"""Get the global maximum coordinates of the bounding box.
112+
113+
Returns
114+
-------
115+
np.ndarray
116+
The global maximum coordinates (local maximum + global origin)
117+
"""
97118
return self.maximum + self.global_origin
98119

99120
@property
100121
def valid(self):
122+
"""Check if the bounding box has valid origin and maximum values.
123+
124+
Returns
125+
-------
126+
bool
127+
True if both origin and maximum are set, False otherwise
128+
"""
101129
return self._origin is not None and self._maximum is not None
102130

103131
@property
104132
def origin(self) -> np.ndarray:
133+
"""Get the origin coordinates of the bounding box.
134+
135+
Returns
136+
-------
137+
np.ndarray
138+
Origin coordinates
139+
140+
Raises
141+
------
142+
LoopValueError
143+
If the origin is not set
144+
"""
105145
if self._origin is None:
106146
raise LoopValueError("Origin is not set")
107147
return self._origin
108148

109149
@origin.setter
110150
def origin(self, origin: np.ndarray):
151+
"""Set the origin coordinates of the bounding box.
152+
153+
Parameters
154+
----------
155+
origin : np.ndarray
156+
Origin coordinates
157+
"""
111158
if self.dimensions != len(origin):
112159
logger.warning(
113160
f"Origin has {len(origin)} dimensions but bounding box has {self.dimensions}"
@@ -116,24 +163,64 @@ def origin(self, origin: np.ndarray):
116163

117164
@property
118165
def maximum(self) -> np.ndarray:
166+
"""Get the maximum coordinates of the bounding box.
167+
168+
Returns
169+
-------
170+
np.ndarray
171+
Maximum coordinates
172+
173+
Raises
174+
------
175+
LoopValueError
176+
If the maximum is not set
177+
"""
119178
if self._maximum is None:
120179
raise LoopValueError("Maximum is not set")
121180
return self._maximum
122181

123182
@maximum.setter
124183
def maximum(self, maximum: np.ndarray):
184+
"""Set the maximum coordinates of the bounding box.
185+
186+
Parameters
187+
----------
188+
maximum : np.ndarray
189+
Maximum coordinates
190+
"""
125191
self._maximum = maximum
126192

127193
@property
128194
def nelements(self):
195+
"""Get the total number of elements in the bounding box.
196+
197+
Returns
198+
-------
199+
int
200+
Total number of elements (product of nsteps)
201+
"""
129202
return self.nsteps.prod()
130203

131204
@property
132205
def volume(self):
206+
"""Calculate the volume of the bounding box.
207+
208+
Returns
209+
-------
210+
float
211+
Volume of the bounding box
212+
"""
133213
return np.prod(self.maximum - self.origin)
134214

135215
@property
136216
def bb(self):
217+
"""Get a numpy array containing origin and maximum coordinates.
218+
219+
Returns
220+
-------
221+
np.ndarray
222+
Array with shape (2, n_dimensions) containing [origin, maximum]
223+
"""
137224
return np.array([self.origin, self.maximum])
138225

139226
@nelements.setter

LoopStructural/datatypes/_structured_grid.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,26 @@
88

99
@dataclass
1010
class StructuredGrid:
11+
"""A structured grid for storing 3D geological data.
12+
13+
This class represents a regular 3D grid with properties and cell properties
14+
that can be used for geological modelling and visualisation.
15+
16+
Parameters
17+
----------
18+
origin : np.ndarray, optional
19+
Origin point of the grid, by default [0, 0, 0]
20+
step_vector : np.ndarray, optional
21+
Step size in each direction, by default [1, 1, 1]
22+
nsteps : np.ndarray, optional
23+
Number of steps in each direction, by default [10, 10, 10]
24+
cell_properties : Dict[str, np.ndarray], optional
25+
Properties defined at cell centres, by default empty dict
26+
properties : Dict[str, np.ndarray], optional
27+
Properties defined at grid nodes, by default empty dict
28+
name : str, optional
29+
Name of the grid, by default "default_grid"
30+
"""
1131
origin: np.ndarray = field(default_factory=lambda: np.array([0, 0, 0]))
1232
step_vector: np.ndarray = field(default_factory=lambda: np.array([1, 1, 1]))
1333
nsteps: np.ndarray = field(default_factory=lambda: np.array([10, 10, 10]))
@@ -16,6 +36,13 @@ class StructuredGrid:
1636
name: str = "default_grid"
1737

1838
def to_dict(self):
39+
"""Convert the structured grid to a dictionary representation.
40+
41+
Returns
42+
-------
43+
dict
44+
Dictionary containing all grid properties and metadata
45+
"""
1946
return {
2047
"origin": self.origin,
2148
"maximum": self.maximum,
@@ -28,9 +55,28 @@ def to_dict(self):
2855

2956
@property
3057
def maximum(self):
58+
"""Calculate the maximum coordinates of the grid.
59+
60+
Returns
61+
-------
62+
np.ndarray
63+
Maximum coordinates (origin + nsteps * step_vector)
64+
"""
3165
return self.origin + self.nsteps * self.step_vector
3266

3367
def vtk(self):
68+
"""Convert the structured grid to a PyVista RectilinearGrid.
69+
70+
Returns
71+
-------
72+
pv.RectilinearGrid
73+
PyVista grid object with all properties attached
74+
75+
Raises
76+
------
77+
ImportError
78+
If PyVista is not installed
79+
"""
3480
try:
3581
import pyvista as pv
3682
except ImportError:
@@ -65,6 +111,13 @@ def plot(self, pyvista_kwargs={}):
65111

66112
@property
67113
def cell_centres(self):
114+
"""Calculate the coordinates of cell centres.
115+
116+
Returns
117+
-------
118+
tuple of np.ndarray
119+
X, Y, Z coordinates of all cell centres
120+
"""
68121
x = np.linspace(
69122
self.origin[0] + self.step_vector[0] * 0.5,
70123
self.maximum[0] + self.step_vector[0] * 0.5,

LoopStructural/interpolators/__init__.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
"""
2-
Interpolators and interpolation supports
1+
"""Interpolators and interpolation supports for LoopStructural.
32
3+
This module provides various interpolation methods and support structures
4+
for geological modelling, including finite difference, piecewise linear,
5+
and radial basis function interpolators.
46
"""
57

68

0 commit comments

Comments
 (0)