pyvale 2025.5.3__cp311-cp311-macosx_13_0_x86_64.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 pyvale might be problematic. Click here for more details.

Files changed (175) hide show
  1. pyvale/.dylibs/libomp.dylib +0 -0
  2. pyvale/__init__.py +89 -0
  3. pyvale/analyticmeshgen.py +102 -0
  4. pyvale/analyticsimdatafactory.py +91 -0
  5. pyvale/analyticsimdatagenerator.py +323 -0
  6. pyvale/blendercalibrationdata.py +15 -0
  7. pyvale/blenderlightdata.py +26 -0
  8. pyvale/blendermaterialdata.py +15 -0
  9. pyvale/blenderrenderdata.py +30 -0
  10. pyvale/blenderscene.py +488 -0
  11. pyvale/blendertools.py +420 -0
  12. pyvale/camera.py +146 -0
  13. pyvale/cameradata.py +69 -0
  14. pyvale/cameradata2d.py +84 -0
  15. pyvale/camerastereo.py +217 -0
  16. pyvale/cameratools.py +522 -0
  17. pyvale/cython/rastercyth.c +32211 -0
  18. pyvale/cython/rastercyth.cpython-311-darwin.so +0 -0
  19. pyvale/cython/rastercyth.py +640 -0
  20. pyvale/data/__init__.py +5 -0
  21. pyvale/data/cal_target.tiff +0 -0
  22. pyvale/data/case00_HEX20_out.e +0 -0
  23. pyvale/data/case00_HEX27_out.e +0 -0
  24. pyvale/data/case00_HEX8_out.e +0 -0
  25. pyvale/data/case00_TET10_out.e +0 -0
  26. pyvale/data/case00_TET14_out.e +0 -0
  27. pyvale/data/case00_TET4_out.e +0 -0
  28. pyvale/data/case13_out.e +0 -0
  29. pyvale/data/case16_out.e +0 -0
  30. pyvale/data/case17_out.e +0 -0
  31. pyvale/data/case18_1_out.e +0 -0
  32. pyvale/data/case18_2_out.e +0 -0
  33. pyvale/data/case18_3_out.e +0 -0
  34. pyvale/data/case25_out.e +0 -0
  35. pyvale/data/case26_out.e +0 -0
  36. pyvale/data/optspeckle_2464x2056px_spec5px_8bit_gblur1px.tiff +0 -0
  37. pyvale/dataset.py +325 -0
  38. pyvale/errorcalculator.py +109 -0
  39. pyvale/errordriftcalc.py +146 -0
  40. pyvale/errorintegrator.py +336 -0
  41. pyvale/errorrand.py +607 -0
  42. pyvale/errorsyscalib.py +134 -0
  43. pyvale/errorsysdep.py +327 -0
  44. pyvale/errorsysfield.py +414 -0
  45. pyvale/errorsysindep.py +808 -0
  46. pyvale/examples/__init__.py +5 -0
  47. pyvale/examples/basics/ex1_1_basicscalars_therm2d.py +131 -0
  48. pyvale/examples/basics/ex1_2_sensormodel_therm2d.py +158 -0
  49. pyvale/examples/basics/ex1_3_customsens_therm3d.py +216 -0
  50. pyvale/examples/basics/ex1_4_basicerrors_therm3d.py +153 -0
  51. pyvale/examples/basics/ex1_5_fielderrs_therm3d.py +168 -0
  52. pyvale/examples/basics/ex1_6_caliberrs_therm2d.py +133 -0
  53. pyvale/examples/basics/ex1_7_spatavg_therm2d.py +123 -0
  54. pyvale/examples/basics/ex2_1_basicvectors_disp2d.py +112 -0
  55. pyvale/examples/basics/ex2_2_vectorsens_disp2d.py +111 -0
  56. pyvale/examples/basics/ex2_3_sensangle_disp2d.py +139 -0
  57. pyvale/examples/basics/ex2_4_chainfielderrs_disp2d.py +196 -0
  58. pyvale/examples/basics/ex2_5_vectorfields3d_disp3d.py +109 -0
  59. pyvale/examples/basics/ex3_1_basictensors_strain2d.py +114 -0
  60. pyvale/examples/basics/ex3_2_tensorsens2d_strain2d.py +111 -0
  61. pyvale/examples/basics/ex3_3_tensorsens3d_strain3d.py +182 -0
  62. pyvale/examples/basics/ex4_1_expsim2d_thermmech2d.py +171 -0
  63. pyvale/examples/basics/ex4_2_expsim3d_thermmech3d.py +252 -0
  64. pyvale/examples/genanalyticdata/ex1_1_scalarvisualisation.py +35 -0
  65. pyvale/examples/genanalyticdata/ex1_2_scalarcasebuild.py +43 -0
  66. pyvale/examples/genanalyticdata/ex2_1_analyticsensors.py +80 -0
  67. pyvale/examples/imagedef2d/ex_imagedef2d_todisk.py +79 -0
  68. pyvale/examples/renderblender/ex1_1_blenderscene.py +121 -0
  69. pyvale/examples/renderblender/ex1_2_blenderdeformed.py +119 -0
  70. pyvale/examples/renderblender/ex2_1_stereoscene.py +128 -0
  71. pyvale/examples/renderblender/ex2_2_stereodeformed.py +131 -0
  72. pyvale/examples/renderblender/ex3_1_blendercalibration.py +120 -0
  73. pyvale/examples/renderrasterisation/ex_rastenp.py +153 -0
  74. pyvale/examples/renderrasterisation/ex_rastercyth_oneframe.py +218 -0
  75. pyvale/examples/renderrasterisation/ex_rastercyth_static_cypara.py +187 -0
  76. pyvale/examples/renderrasterisation/ex_rastercyth_static_pypara.py +190 -0
  77. pyvale/examples/visualisation/ex1_1_plot_traces.py +102 -0
  78. pyvale/examples/visualisation/ex2_1_animate_sim.py +89 -0
  79. pyvale/experimentsimulator.py +175 -0
  80. pyvale/field.py +128 -0
  81. pyvale/fieldconverter.py +351 -0
  82. pyvale/fieldsampler.py +111 -0
  83. pyvale/fieldscalar.py +166 -0
  84. pyvale/fieldtensor.py +218 -0
  85. pyvale/fieldtransform.py +388 -0
  86. pyvale/fieldvector.py +213 -0
  87. pyvale/generatorsrandom.py +505 -0
  88. pyvale/imagedef2d.py +569 -0
  89. pyvale/integratorfactory.py +240 -0
  90. pyvale/integratorquadrature.py +217 -0
  91. pyvale/integratorrectangle.py +165 -0
  92. pyvale/integratorspatial.py +89 -0
  93. pyvale/integratortype.py +43 -0
  94. pyvale/output.py +17 -0
  95. pyvale/pyvaleexceptions.py +11 -0
  96. pyvale/raster.py +31 -0
  97. pyvale/rastercy.py +77 -0
  98. pyvale/rasternp.py +603 -0
  99. pyvale/rendermesh.py +147 -0
  100. pyvale/sensorarray.py +178 -0
  101. pyvale/sensorarrayfactory.py +196 -0
  102. pyvale/sensorarraypoint.py +278 -0
  103. pyvale/sensordata.py +71 -0
  104. pyvale/sensordescriptor.py +213 -0
  105. pyvale/sensortools.py +142 -0
  106. pyvale/simcases/case00_HEX20.i +242 -0
  107. pyvale/simcases/case00_HEX27.i +242 -0
  108. pyvale/simcases/case00_HEX8.i +242 -0
  109. pyvale/simcases/case00_TET10.i +242 -0
  110. pyvale/simcases/case00_TET14.i +242 -0
  111. pyvale/simcases/case00_TET4.i +242 -0
  112. pyvale/simcases/case01.i +101 -0
  113. pyvale/simcases/case02.i +156 -0
  114. pyvale/simcases/case03.i +136 -0
  115. pyvale/simcases/case04.i +181 -0
  116. pyvale/simcases/case05.i +234 -0
  117. pyvale/simcases/case06.i +305 -0
  118. pyvale/simcases/case07.geo +135 -0
  119. pyvale/simcases/case07.i +87 -0
  120. pyvale/simcases/case08.geo +144 -0
  121. pyvale/simcases/case08.i +153 -0
  122. pyvale/simcases/case09.geo +204 -0
  123. pyvale/simcases/case09.i +87 -0
  124. pyvale/simcases/case10.geo +204 -0
  125. pyvale/simcases/case10.i +257 -0
  126. pyvale/simcases/case11.geo +337 -0
  127. pyvale/simcases/case11.i +147 -0
  128. pyvale/simcases/case12.geo +388 -0
  129. pyvale/simcases/case12.i +329 -0
  130. pyvale/simcases/case13.i +140 -0
  131. pyvale/simcases/case14.i +159 -0
  132. pyvale/simcases/case15.geo +337 -0
  133. pyvale/simcases/case15.i +150 -0
  134. pyvale/simcases/case16.geo +391 -0
  135. pyvale/simcases/case16.i +357 -0
  136. pyvale/simcases/case17.geo +135 -0
  137. pyvale/simcases/case17.i +144 -0
  138. pyvale/simcases/case18.i +254 -0
  139. pyvale/simcases/case18_1.i +254 -0
  140. pyvale/simcases/case18_2.i +254 -0
  141. pyvale/simcases/case18_3.i +254 -0
  142. pyvale/simcases/case19.geo +252 -0
  143. pyvale/simcases/case19.i +99 -0
  144. pyvale/simcases/case20.geo +252 -0
  145. pyvale/simcases/case20.i +250 -0
  146. pyvale/simcases/case21.geo +74 -0
  147. pyvale/simcases/case21.i +155 -0
  148. pyvale/simcases/case22.geo +82 -0
  149. pyvale/simcases/case22.i +140 -0
  150. pyvale/simcases/case23.geo +164 -0
  151. pyvale/simcases/case23.i +140 -0
  152. pyvale/simcases/case24.geo +79 -0
  153. pyvale/simcases/case24.i +123 -0
  154. pyvale/simcases/case25.geo +82 -0
  155. pyvale/simcases/case25.i +140 -0
  156. pyvale/simcases/case26.geo +166 -0
  157. pyvale/simcases/case26.i +140 -0
  158. pyvale/simcases/run_1case.py +61 -0
  159. pyvale/simcases/run_all_cases.py +69 -0
  160. pyvale/simcases/run_build_case.py +64 -0
  161. pyvale/simcases/run_example_cases.py +69 -0
  162. pyvale/simtools.py +67 -0
  163. pyvale/visualexpplotter.py +191 -0
  164. pyvale/visualimagedef.py +74 -0
  165. pyvale/visualimages.py +76 -0
  166. pyvale/visualopts.py +493 -0
  167. pyvale/visualsimanimator.py +111 -0
  168. pyvale/visualsimsensors.py +318 -0
  169. pyvale/visualtools.py +136 -0
  170. pyvale/visualtraceplotter.py +142 -0
  171. pyvale-2025.5.3.dist-info/METADATA +144 -0
  172. pyvale-2025.5.3.dist-info/RECORD +175 -0
  173. pyvale-2025.5.3.dist-info/WHEEL +6 -0
  174. pyvale-2025.5.3.dist-info/licenses/LICENSE +21 -0
  175. pyvale-2025.5.3.dist-info/top_level.txt +1 -0
@@ -0,0 +1,505 @@
1
+ # ==============================================================================
2
+ # pyvale: the python validation engine
3
+ # License: MIT
4
+ # Copyright (C) 2025 The Computer Aided Validation Team
5
+ # ==============================================================================
6
+
7
+ from abc import ABC, abstractmethod
8
+ import numpy as np
9
+
10
+
11
+ class IGenRandom(ABC):
12
+ """Interface (abstract base class) for wrapping numpy random number
13
+ generation to allow probability distribution parameters to be specified in
14
+ the initialiser whereas the generation of random numbers has a common
15
+ method that just takes the require shape to return. Allows for easy
16
+ subsitution of different probability distributions.
17
+ """
18
+
19
+ @abstractmethod
20
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
21
+ """Abstract method. Generates an array of random numbers with the shape
22
+ specified by the input.
23
+
24
+ Parameters
25
+ ----------
26
+ shape : tuple[int,...]
27
+ Shape of the array of random numbers to be returned.
28
+
29
+ Returns
30
+ -------
31
+ np.ndarray
32
+ Array of random numbers with shape specified by the input shape.
33
+ """
34
+ pass
35
+
36
+
37
+ class GenNormal(IGenRandom):
38
+ """Class wrapping the numpy normal random number generator. Implements the
39
+ IGeneratorRandom interface to allow for interchangeability with other random
40
+ number generators.
41
+ """
42
+ __slots__ = ("_std","_mean","_rng")
43
+
44
+ def __init__(self,
45
+ std: float = 1.0,
46
+ mean: float = 0.0,
47
+ seed: int | None = None) -> None:
48
+ """
49
+ Parameters
50
+ ----------
51
+ std : float, optional
52
+ Standard deviation of the normal distribution to sample, by default
53
+ 1.0
54
+ mean : float, optional
55
+ Mean of the normal distribution to sample, by default 0.0
56
+ seed : int | None, optional
57
+ Optional seed for the random generator to allow for reproducibility
58
+ and testing, by default None
59
+ """
60
+ self._std =std
61
+ self._mean = mean
62
+ self._rng = np.random.default_rng(seed)
63
+
64
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
65
+ """Generates an array of random numbers with the shape specified by the
66
+ input.
67
+
68
+ Parameters
69
+ ----------
70
+ shape : tuple[int,...]
71
+ Shape of the array to return.
72
+
73
+ Returns
74
+ -------
75
+ np.ndarray
76
+ Array of random numbers with the specified shape.
77
+ """
78
+ return self._rng.normal(loc = self._mean,
79
+ scale = self._std,
80
+ size = shape)
81
+
82
+
83
+ class GenLogNormal(IGenRandom):
84
+ """Class wrapping the numpy lognormal random generator. Implements the
85
+ IGeneratorRandom interface to allow for interchangeability with other random
86
+ number generators.
87
+ """
88
+ __slots__ = ("_std","_mean","_rng")
89
+
90
+ def __init__(self,
91
+ std: float = 1.0,
92
+ mean: float = 0.0,
93
+ seed: int | None = None) -> None:
94
+ """
95
+ Parameters
96
+ ----------
97
+ std : float, optional
98
+ Standard deviation of the normal distribution to sample, by default
99
+ 1.0
100
+ mean : float, optional
101
+ Mean of the normal distribution to sample, by default 0.0
102
+ seed : int | None, optional
103
+ Optional seed for the random generator to allow for reproducibility
104
+ and testing, by default None
105
+ """
106
+ self._std =std
107
+ self._mean = mean
108
+ self._rng = np.random.default_rng(seed)
109
+
110
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
111
+ """Generates an array of random numbers with the shape specified by the
112
+ input.
113
+
114
+ Parameters
115
+ ----------
116
+ shape : tuple[int,...]
117
+ Shape of the array to return.
118
+ Returns
119
+ -------
120
+ np.ndarray
121
+ Array of random numbers with the specified shape.
122
+ """
123
+ return self._rng.lognormal(mean = self._mean,
124
+ sigma = self._std,
125
+ size = shape)
126
+
127
+
128
+ class GenUniform(IGenRandom):
129
+ """Class wrapping the numpy uniform random number generator. Implements the
130
+ IGeneratorRandom interface to allow for interchangeability with other random
131
+ number generators.
132
+ """
133
+ __slots__ = ("_low","_high","_rng")
134
+
135
+ def __init__(self,
136
+ low: float = -1.0,
137
+ high: float = 1.0,
138
+ seed: int | None = None) -> None:
139
+ """
140
+ Parameters
141
+ ----------
142
+ low : float, optional
143
+ Lower bound of the uniform dsitribution., by default -1.0
144
+ high : float, optional
145
+ Upper bound of the uniform distribution, by default 1.0
146
+ seed : int | None, optional
147
+ Optional seed for the random generator to allow for reproducibility
148
+ and testing, by default None
149
+ """
150
+
151
+ self._low = low
152
+ self._high = high
153
+ self._rng = np.random.default_rng(seed)
154
+
155
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
156
+ """Generates an array of random numbers with the shape specified by the
157
+ input.
158
+
159
+ Parameters
160
+ ----------
161
+ shape : tuple[int,...]
162
+ Shape of the array to return.
163
+ Returns
164
+ -------
165
+ np.ndarray
166
+ Array of random numbers with the specified shape.
167
+ """
168
+ return self._rng.uniform(low = self._low,
169
+ high = self._high,
170
+ size = shape)
171
+
172
+
173
+ class GenExponential(IGenRandom):
174
+ """Class wrapping the numpy exponential random generator. Implements the
175
+ IGeneratorRandom interface to allow for interchangeability with other random
176
+ number generators.
177
+ """
178
+ __slots__ = ("_scale","_rng")
179
+
180
+ def __init__(self,
181
+ scale: float = 1.0,
182
+ seed: int | None = None) -> None:
183
+ """
184
+ Parameters
185
+ ----------
186
+ scale : float, optional
187
+ Scale parameter of the distribution which must be positive, by
188
+ default 1.0
189
+ seed : int | None, optional
190
+ Optional seed for the random generator to allow for reproducibility
191
+ and testing, by default None
192
+ """
193
+ self._scale = np.abs(scale)
194
+ self._rng = np.random.default_rng(seed)
195
+
196
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
197
+ """Generates an array of random numbers with the shape specified by the
198
+ input.
199
+
200
+ Parameters
201
+ ----------
202
+ shape : tuple[int,...]
203
+ Shape of the array to return.
204
+ Returns
205
+ -------
206
+ np.ndarray
207
+ Array of random numbers with the specified shape.
208
+ """
209
+ return self._rng.exponential(scale = self._scale,
210
+ size = shape)
211
+
212
+
213
+ class GenChiSquare(IGenRandom):
214
+ """Class wrapping the numpy chi square random generator. Implements the
215
+ IGeneratorRandom interface to allow for interchangeability with other random
216
+ number generators.
217
+ """
218
+ __slots__ = ("_dofs","_rng")
219
+
220
+ def __init__(self,
221
+ dofs: float,
222
+ seed: int | None = None) -> None:
223
+ """
224
+ Parameters
225
+ ----------
226
+ dofs : float
227
+ Number of degrees of freedom of the distribution must be greater
228
+ than zero.
229
+ seed : int | None, optional
230
+ Optional seed for the random generator to allow for reproducibility
231
+ and testing, by default None
232
+ """
233
+ self._dofs = np.abs(dofs)
234
+ self._rng = np.random.default_rng(seed)
235
+
236
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
237
+ """Generates an array of random numbers with the shape specified by the
238
+ input.
239
+
240
+ Parameters
241
+ ----------
242
+ shape : tuple[int,...]
243
+ Shape of the array to return.
244
+ Returns
245
+ -------
246
+ np.ndarray
247
+ Array of random numbers with the specified shape.
248
+ """
249
+ return self._rng.chisquare(df = self._dofs,
250
+ size = shape)
251
+
252
+
253
+ class GenDirichlet(IGenRandom):
254
+ """Class wrapping the numpy dirichlet random generator. Implements the
255
+ IGeneratorRandom interface to allow for interchangeability with other random
256
+ number generators.
257
+ """
258
+ __slots__ = ("_alpha","_rng")
259
+
260
+ def __init__(self,
261
+ alpha: float,
262
+ seed: int | None = None) -> None:
263
+ """
264
+ Parameters
265
+ ----------
266
+ alpha : float
267
+ Alpha parameter of the distribution
268
+ seed : int | None, optional
269
+ Optional seed for the random generator to allow for reproducibility
270
+ and testing, by default None
271
+ """
272
+ self._alpha = alpha
273
+ self._rng = np.random.default_rng(seed)
274
+
275
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
276
+ """Generates an array of random numbers with the shape specified by the
277
+ input.
278
+
279
+ Parameters
280
+ ----------
281
+ shape : tuple[int,...]
282
+ Shape of the array to return.
283
+ Returns
284
+ -------
285
+ np.ndarray
286
+ Array of random numbers with the specified shape.
287
+ """
288
+ return self._rng.dirichlet(alpha = self._alpha, size = shape)
289
+
290
+
291
+ class GenF(IGenRandom):
292
+ """Class wrapping the numpy F distribution random generator. Implements the
293
+ IGeneratorRandom interface to allow for interchangeability with other random
294
+ number generators.
295
+ """
296
+ __slots__ = ("_dofs","_rng")
297
+
298
+ def __init__(self,
299
+ dofs: float,
300
+ seed: int | None = None) -> None:
301
+ """
302
+ Parameters
303
+ ----------
304
+ dofs : float
305
+ Number of degrees of freedom of the distribution must be greater
306
+ than zero
307
+ seed : int | None, optional
308
+ Optional seed for the random generator to allow for reproducibility
309
+ and testing, by default None
310
+ """
311
+ self._dofs = np.abs(dofs)
312
+ self._rng = np.random.default_rng(seed)
313
+
314
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
315
+ """Generates an array of random numbers with the shape specified by the
316
+ input.
317
+
318
+ Parameters
319
+ ----------
320
+ shape : tuple[int,...]
321
+ Shape of the array to return.
322
+ Returns
323
+ -------
324
+ np.ndarray
325
+ Array of random numbers with the specified shape.
326
+ """
327
+ return self._rng.f(dfnum = self._dofs, size = shape)
328
+
329
+
330
+ class GenGamma(IGenRandom):
331
+ """Class wrapping the numpy gamma random generator. Implements the
332
+ IGeneratorRandom interface to allow for interchangeability with other random
333
+ number generators.
334
+ """
335
+ __slots__ = ("_shape","_scale","_rng")
336
+
337
+ def __init__(self,
338
+ shape: float,
339
+ scale: float = 1.0,
340
+ seed: int | None = None) -> None:
341
+ """
342
+ Parameters
343
+ ----------
344
+ shape : float
345
+ Shape parameter of the gamma distribution, must be greater than zero
346
+ scale : float, optional
347
+ Scale parameter of the gamma distribution which must be greater than
348
+ zero, by default 1.0
349
+ seed : int | None, optional
350
+ Optional seed for the random generator to allow for reproducibility
351
+ and testing, by default None
352
+ """
353
+ self._shape = np.abs(shape)
354
+ self._scale = np.abs(scale)
355
+ self._rng = np.random.default_rng(seed)
356
+
357
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
358
+ """Generates an array of random numbers with the shape specified by the
359
+ input.
360
+
361
+ Parameters
362
+ ----------
363
+ shape : tuple[int,...]
364
+ Shape of the array to return.
365
+ Returns
366
+ -------
367
+ np.ndarray
368
+ Array of random numbers with the specified shape.
369
+ """
370
+ return self._rng.gamma(scale = self._scale,
371
+ size = shape)
372
+
373
+
374
+ class GenStandardT(IGenRandom):
375
+ """Class wrapping the numpy t distribution random generator. Implements the
376
+ IGeneratorRandom interface to allow for interchangeability with other random
377
+ number generators.
378
+ """
379
+ __slots__ = ("_dofs","_rng")
380
+
381
+ def __init__(self,
382
+ dofs: float,
383
+ seed: int | None = None) -> None:
384
+ """
385
+ Parameters
386
+ ----------
387
+ dofs : float
388
+ Number of degrees of freedom of the distribution must be greater
389
+ than zero.
390
+ seed : int | None, optional
391
+ Optional seed for the random generator to allow for reproducibility
392
+ and testing, by default None
393
+ """
394
+ self._dofs = np.abs(dofs)
395
+ self._rng = np.random.default_rng(seed)
396
+
397
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
398
+ """Generates an array of random numbers with the shape specified by the
399
+ input.
400
+
401
+ Parameters
402
+ ----------
403
+ shape : tuple[int,...]
404
+ Shape of the array to return.
405
+ Returns
406
+ -------
407
+ np.ndarray
408
+ Array of random numbers with the specified shape.
409
+ """
410
+ return self._rng.standard_t(df = self._dofs,
411
+ size = shape)
412
+
413
+
414
+ class GenBeta(IGenRandom):
415
+ """Class wrapping the numpy beta distribution random generator. Implements
416
+ the IGeneratorRandom interface to allow for interchangeability with other
417
+ random number generators.
418
+ """
419
+ __slots__ = ("_a","_b","_rng")
420
+
421
+ def __init__(self,
422
+ a: float,
423
+ b: float,
424
+ seed: int | None = None) -> None:
425
+ """
426
+ Parameters
427
+ ----------
428
+ a : float
429
+ Alpha parameter of the distribution which must be greater than zero
430
+ b : float
431
+ Beta parameter of the distribution which must be greater than zero
432
+ seed : int | None, optional
433
+ Optional seed for the random generator to allow for reproducibility
434
+ and testing, by default None
435
+ """
436
+ self._a = np.abs(a)
437
+ self._b = np.abs(b)
438
+ self._rng = np.random.default_rng(seed)
439
+
440
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
441
+ """Generates an array of random numbers with the shape specified by the
442
+ input.
443
+
444
+ Parameters
445
+ ----------
446
+ shape : tuple[int,...]
447
+ Shape of the array to return.
448
+ Returns
449
+ -------
450
+ np.ndarray
451
+ Array of random numbers with the specified shape.
452
+ """
453
+ return self._rng.beta(a = self._a,
454
+ b = self._b,
455
+ size = shape)
456
+
457
+
458
+ class GenTriangular(IGenRandom):
459
+ """Class wrapping the numpy triangular random generator. Implements the
460
+ IGeneratorRandom interface to allow for interchangeability with other random
461
+ number generators.
462
+ """
463
+ __slots__ = ("_left","_mode","_right","_rng")
464
+
465
+ def __init__(self,
466
+ left: float = -1.0,
467
+ mode: float = 0.0,
468
+ right: float = 1.0,
469
+ seed: int | None = None) -> None:
470
+ """
471
+ Parameters
472
+ ----------
473
+ left : float, optional
474
+ Left (min) corner of the triangular distribution, by default -1.0
475
+ mode : float, optional
476
+ Central peak of the triangular distribution, by default 0.0
477
+ right : float, optional
478
+ Right (max) corner of the triangular distribution , by default 1.0
479
+ seed : int | None, optional
480
+ Optional seed for the random generator to allow for reproducibility
481
+ and testing, by default None
482
+ """
483
+ self._left = left
484
+ self._mode = mode
485
+ self._right = right
486
+
487
+ self._rng = np.random.default_rng(seed)
488
+
489
+ def generate(self, shape: tuple[int,...]) -> np.ndarray:
490
+ """Generates an array of random numbers with the shape specified by the
491
+ input.
492
+
493
+ Parameters
494
+ ----------
495
+ shape : tuple[int,...]
496
+ Shape of the array to return.
497
+ Returns
498
+ -------
499
+ np.ndarray
500
+ Array of random numbers with the specified shape.
501
+ """
502
+ return self._rng.triangular(left = self._left,
503
+ mode = self._mode,
504
+ right = self._right,
505
+ size = shape)