orchid-python-api 5.25.3__py3-none-any.whl → 5.25.4__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.
Files changed (57) hide show
  1. orchid_python_api/examples/search_data_frames.py +1 -1
  2. {orchid_python_api-5.25.3.dist-info → orchid_python_api-5.25.4.dist-info}/METADATA +4 -3
  3. orchid_python_api-5.25.4.dist-info/RECORD +38 -0
  4. {orchid_python_api-5.25.3.dist-info → orchid_python_api-5.25.4.dist-info}/WHEEL +1 -1
  5. ReleaseNotes.md +0 -730
  6. copy_orchid_examples.py +0 -88
  7. copy_orchid_low_level_examples.py +0 -93
  8. copy_orchid_manual_examples.py +0 -93
  9. copy_orchid_tutorials.py +0 -88
  10. orchid/VERSION +0 -1
  11. orchid/__init__.py +0 -42
  12. orchid/__version__.py +0 -18
  13. orchid/base.py +0 -31
  14. orchid/base_time_series_adapter.py +0 -91
  15. orchid/configuration.py +0 -162
  16. orchid/convert.py +0 -44
  17. orchid/core.py +0 -149
  18. orchid/dom_project_object.py +0 -28
  19. orchid/dot_net.py +0 -68
  20. orchid/dot_net_disposable.py +0 -64
  21. orchid/dot_net_dom_access.py +0 -241
  22. orchid/measurement.py +0 -35
  23. orchid/native_data_frame_adapter.py +0 -247
  24. orchid/native_fiber_data.py +0 -73
  25. orchid/native_fiber_data_set_info.py +0 -28
  26. orchid/native_monitor_adapter.py +0 -67
  27. orchid/native_project_user_data_adapter.py +0 -137
  28. orchid/native_stage_adapter.py +0 -631
  29. orchid/native_stage_part_adapter.py +0 -50
  30. orchid/native_subsurface_point.py +0 -70
  31. orchid/native_time_series_adapter.py +0 -54
  32. orchid/native_trajectory_adapter.py +0 -246
  33. orchid/native_treatment_calculations.py +0 -158
  34. orchid/native_treatment_curve_adapter.py +0 -60
  35. orchid/native_well_adapter.py +0 -134
  36. orchid/net_date_time.py +0 -328
  37. orchid/net_enumerable.py +0 -72
  38. orchid/net_fracture_diagnostics_factory.py +0 -55
  39. orchid/net_quantity.py +0 -620
  40. orchid/net_stage_qc.py +0 -62
  41. orchid/physical_quantity.py +0 -37
  42. orchid/project.py +0 -182
  43. orchid/project_store.py +0 -269
  44. orchid/reference_origins.py +0 -34
  45. orchid/script_adapter_context.py +0 -81
  46. orchid/searchable_data_frames.py +0 -44
  47. orchid/searchable_project_objects.py +0 -190
  48. orchid/searchable_stage_parts.py +0 -73
  49. orchid/searchable_stages.py +0 -29
  50. orchid/unit_system.py +0 -173
  51. orchid/utils.py +0 -14
  52. orchid/validation.py +0 -52
  53. orchid/version.py +0 -37
  54. orchid_python_api-5.25.3.dist-info/LICENSE +0 -176
  55. orchid_python_api-5.25.3.dist-info/RECORD +0 -88
  56. {orchid_python_api-5.25.3.dist-info → orchid_python_api-5.25.4.dist-info}/entry_points.txt +0 -0
  57. /LICENSE → /orchid_python_api-5.25.4.dist-info/licenses/LICENSE +0 -0
orchid/net_quantity.py DELETED
@@ -1,620 +0,0 @@
1
- # Copyright (c) 2017-2025 KAPPA
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
- #
15
- # This file is part of Orchid and related technologies.
16
- #
17
-
18
- """This module contains functions for converting between instances of the (Python) `Measurement` class and
19
- instances of .NET classes like `UnitsNet.Quantity` and `DateTime`."""
20
-
21
- from functools import singledispatch
22
- import math
23
- from numbers import Real
24
- import operator
25
- from typing import Optional, Union
26
-
27
- import option
28
- import toolz.curried as toolz
29
-
30
- from orchid import (
31
- measurement as om,
32
- physical_quantity as opq,
33
- unit_system as units,
34
- )
35
-
36
- # noinspection PyUnresolvedReferences
37
- from Optional import Option
38
- # noinspection PyUnresolvedReferences
39
- import System
40
- # noinspection PyUnresolvedReferences
41
- import UnitsNet
42
-
43
-
44
- # Convenience functions
45
-
46
-
47
- def to_net_quantity_value(magnitude):
48
- """
49
- Create a `UnitsNet` `QuantityValue` instance.
50
-
51
- The `UnitsNet` package *does not* accept floating point values to create most measurements; instead, these
52
- creation functions expect an argument of type `QuantityValue`. In .NET, these values are created using an
53
- implicit conversion. This implicit version on the Python side fails.
54
-
55
- This function allows us to define that conversion in one place.
56
-
57
- Args:
58
- magnitude: The magnitude of the `UnitNet` `Quantity` (measurement) to be created.
59
-
60
- Returns:
61
- The `magnitude` wrapped in a `UnitsNet.QuantityValue` instance.
62
-
63
- """
64
- return UnitsNet.QuantityValue.op_Implicit(magnitude)
65
-
66
-
67
- def net_length_from(magnitude: float, net_unit: UnitsNet.Length.Units) -> UnitsNet.Quantity:
68
- """
69
- Create a `UnitsNet` length measurement from `magnitude` and `net_unit`.
70
-
71
- Args:
72
- magnitude: The magnitude of the length measurement
73
- net_unit: The `UnitsNet` unit of the length measurement
74
-
75
- Returns:
76
- The `UnitsNet` `Quantity` whose `Value` is `magnitude` and whose `Unit` is `net_unit`.
77
- """
78
- return UnitsNet.Length.From(to_net_quantity_value(magnitude), net_unit)
79
-
80
-
81
- def net_pressure_from(magnitude: float, net_unit: UnitsNet.Pressure.Units) -> UnitsNet.Quantity:
82
- """
83
- Create a `UnitsNet` pressure measurement from `magnitude` and `net_unit`.
84
-
85
- Args:
86
- magnitude: The magnitude of the pressure measurement
87
- net_unit: The `UnitsNet` unit of the pressure measurement
88
-
89
- Returns:
90
- The `UnitsNet` `Quantity` whose `Value` is `magnitude` and whose `Unit` is `net_unit`.
91
- """
92
- return UnitsNet.Pressure.From(to_net_quantity_value(magnitude), net_unit)
93
-
94
-
95
- # The following code creates conversion functions programmatically by:
96
- # - Creating a map from variable name to string identifying how to create the `UnitsNet` `Quantity`
97
- # - Transforming that map by:
98
- # - Transforming the map keys by prepending 'net_'
99
- # - Transforming the map values to a function creating the value. (See the documentation of
100
- # `operator.attrgetter` function for details.)
101
- # - Adding the key and value of this map to the `globals()` dict (module attributes)
102
- net_creator_attributes = {
103
- 'angle_from_deg': 'Angle.FromDegrees',
104
- 'duration_from_min': 'Duration.FromMinutes',
105
- 'density_from_lbs_per_cu_ft': 'Density.FromPoundsPerCubicFoot',
106
- 'density_from_kg_per_cu_m': 'Density.FromKilogramsPerCubicMeter',
107
- 'energy_from_ft_lbs': 'Energy.FromFootPounds',
108
- 'energy_from_J': 'Energy.FromJoules',
109
- 'force_from_lbf': 'Force.FromPoundsForce',
110
- 'force_from_N': 'Force.FromNewtons',
111
- 'length_from_ft': 'Length.FromFeet',
112
- 'length_from_m': 'Length.FromMeters',
113
- 'mass_from_lbs': 'Mass.FromPounds',
114
- 'mass_from_kg': 'Mass.FromKilograms',
115
- 'power_from_hp': 'Power.FromMechanicalHorsepower',
116
- 'power_from_W': 'Power.FromWatts',
117
- 'pressure_from_psi': 'Pressure.FromPoundsForcePerSquareInch',
118
- 'pressure_from_kPa': 'Pressure.FromKilopascals',
119
- 'pressure_from_bars': 'Pressure.FromBars',
120
- 'mass_concentration_from_lbs_per_gal': 'MassConcentration.FromPoundsPerUSGallon',
121
- 'mass_concentration_from_kg_per_cu_m': 'MassConcentration.FromKilogramsPerCubicMeter',
122
- 'volume_flow_from_oil_bbl_per_min': 'VolumeFlow.FromOilBarrelsPerMinute',
123
- 'volume_flow_from_cu_m_per_min': 'VolumeFlow.FromCubicMetersPerMinute',
124
- 'temperature_from_deg_F': 'Temperature.FromDegreesFahrenheit',
125
- 'temperature_from_deg_C': 'Temperature.FromDegreesCelsius',
126
- 'volume_from_oil_bbl': 'Volume.FromOilBarrels',
127
- 'volume_from_cu_m': 'Volume.FromCubicMeters',
128
- }
129
- net_creator_funcs = toolz.pipe(
130
- net_creator_attributes,
131
- toolz.keymap(lambda k: f'net_{k}'),
132
- toolz.valmap(lambda v: toolz.compose(operator.attrgetter(v)(UnitsNet),
133
- to_net_quantity_value)),
134
- )
135
- for variable_name, variable_value in net_creator_funcs.items():
136
- globals()[variable_name] = variable_value
137
-
138
-
139
- class EqualsComparisonDetails:
140
- def __init__(self, tolerance: Real = 1e-4,
141
- net_comparison_type: UnitsNet.ComparisonType = UnitsNet.ComparisonType.Relative):
142
- """
143
- Construct an instance that uses `tolerance` and `comparison_type` to determine equality.
144
-
145
- This class exists because the `tolerance` and `comparison_type` are closely coupled; that is, one
146
- cannot correctly interpret the use of `tolerance` without a reference to the `comparison_type`.
147
-
148
- Args:
149
- tolerance: The maximum difference tolerated between two instances in determining equality.
150
- net_comparison_type: The type of comparison: `UnitsNet.ComparisonType.Relative` or
151
- `UnitsNet.ComparisonType.Absolute`.
152
- """
153
- self._tolerance = tolerance
154
- self._comparison_type = net_comparison_type
155
-
156
- @property
157
- def tolerance(self) -> Real:
158
- """
159
- Return the tolerance to be use in determining equality.
160
-
161
- Although this property is public, it is intended only to be read by the `equal_net_comparison`
162
- function.
163
- """
164
- return self._tolerance
165
-
166
- @property
167
- def comparison_type(self) -> UnitsNet.ComparisonType:
168
- """
169
- Return the comparison type to be use in determining equality.
170
-
171
- Although this property is public, it is intended only to be read by the `equal_net_comparison`
172
- function.
173
- """
174
- return self._comparison_type
175
-
176
-
177
- #
178
- # Although Pint supports the unit `cu_ft`, we have chosen to use the synonym, `ft ** 3` (which is
179
- # printed as 'ft\u00b3` (that is, 'ft' followed by a Unicode superscript 3)). According to a
180
- # citation on [Wikipedia article](https://en.wikipedia.org/wiki/Cubic_foot), this "is the IEEE
181
- # symbol for the cubic foot." Our general rule: we accept the Pint unit `cu_ft` as **input**,
182
- # but, on various conversion, produce the Pint unit `ft**3`.
183
- #
184
-
185
-
186
- @singledispatch
187
- @toolz.curry
188
- def as_measurement(unknown, _maybe_net_quantity: option.Option[UnitsNet.IQuantity]) -> om.Quantity:
189
- """
190
- Convert an optional .NET `IQuantity` to a `pint` `Quantity` instance.
191
-
192
- This function is registered as the type-handler for the `object` type. In our situation, arriving here
193
- indicates an error by an implementer and so raises an error.
194
-
195
- Args:
196
- unknown: A parameter whose type is not expected.
197
- _maybe_net_quantity: The optional .NET `IQuantity` instance to convert. (Unused.)
198
- """
199
- raise TypeError(f'First argument, {unknown}, has type {type(unknown)}, unexpected by `as_measurement`.')
200
-
201
-
202
- # noinspection PyUnresolvedReferences
203
- @as_measurement.register(units.Common)
204
- @toolz.curry
205
- def as_measurement_in_common_unit(target_unit, maybe_net_quantity: UnitsNet.IQuantity) -> om.Quantity:
206
- """
207
- Convert an optional .NET `IQuantity` to a `pint` `Quantity` instance in a common unit.
208
-
209
- Args:
210
- target_unit: The unit (from the units.Common) for the converted `Quantity` instance.
211
- maybe_net_quantity: The optional .NET `IQuantity` instance to convert.
212
-
213
- Returns:
214
- The equivalent `Quantity` instance in the target unit.
215
- """
216
- return maybe_net_quantity.map_or(_as_measurement_in_unit(target_unit),
217
- om.Quantity(float('NaN'), target_unit.value.unit))
218
-
219
-
220
- @as_measurement.register(units.Metric)
221
- @as_measurement.register(units.UsOilfield)
222
- @toolz.curry
223
- def as_measurement_in_specified_unit(target_unit,
224
- maybe_net_quantity: option.Option[UnitsNet.IQuantity]) -> om.Quantity:
225
- """
226
- Convert an optional .NET `IQuantity` to a `pint` `Quantity` instance.
227
-
228
- Args:
229
- target_unit: The unit for the converted `Quantity` instance.
230
- maybe_net_quantity: The optional .NET `IQuantity` instance to convert.
231
-
232
- Returns:
233
- The equivalent `Quantity` instance in the target unit.
234
- """
235
-
236
- result = maybe_net_quantity.map_or(_as_measurement_in_unit(target_unit),
237
- om.Quantity(float('NaN'), target_unit.value.unit))
238
- return result
239
-
240
-
241
- @toolz.curry
242
- def _as_measurement_in_unit(target_unit: Union[units.Metric, units.UsOilfield],
243
- net_quantity: UnitsNet.IQuantity) -> om.Quantity:
244
- """
245
- Convert an `IQuantity` to a `pint` `Quantity` in a specified compatible unit.
246
-
247
- Args:
248
- target_unit: The target unit for the converted `Quantity` instance.
249
- net_quantity: The .NET `IQuantity` instance to convert.
250
-
251
- Returns:
252
- The equivalent `Quantity` instance in the specified unit.
253
- """
254
- target_magnitude = net_quantity.As(_UNIT_NET_UNITS[target_unit])
255
- result = om.Quantity(target_magnitude, target_unit.value.unit)
256
- return result
257
-
258
-
259
- # noinspection PyUnresolvedReferences
260
- _physical_quantity_to_net_physical_quantity = {
261
- opq.PhysicalQuantity.ANGLE: UnitsNet.Angle,
262
- opq.PhysicalQuantity.DURATION: UnitsNet.Duration,
263
- opq.PhysicalQuantity.DENSITY: UnitsNet.Density,
264
- opq.PhysicalQuantity.ENERGY: UnitsNet.Energy,
265
- opq.PhysicalQuantity.FORCE: UnitsNet.Force,
266
- opq.PhysicalQuantity.LENGTH: UnitsNet.Length,
267
- opq.PhysicalQuantity.MASS: UnitsNet.Mass,
268
- opq.PhysicalQuantity.POWER: UnitsNet.Power,
269
- opq.PhysicalQuantity.PRESSURE: UnitsNet.Pressure,
270
- opq.PhysicalQuantity.PROPPANT_CONCENTRATION: UnitsNet.MassConcentration,
271
- opq.PhysicalQuantity.TEMPERATURE: UnitsNet.Temperature,
272
- opq.PhysicalQuantity.SLURRY_RATE: UnitsNet.VolumeFlow,
273
- opq.PhysicalQuantity.VOLUME: UnitsNet.Volume,
274
- }
275
-
276
-
277
- @toolz.curry
278
- def _python_measurement_option(target_unit: Union[units.Metric, units.UsOilfield],
279
- optional_net_quantity: Option[UnitsNet.IQuantity]):
280
- @toolz.curry
281
- def net_option_as_pythonic(net_option):
282
- # If we are **not** an instance of `Option<Pressure>`
283
- if not hasattr(net_option, 'HasValue'):
284
- # Simply return the value (which may be `null` / `None`)
285
- return net_option
286
-
287
- # If we **are** an instance of `Option<Pressure>` yet have no value
288
- if not net_option.HasValue:
289
- return None
290
-
291
- # The variable, `net_quantity`, will contain a zero value in the `UnitsNet` unit corresponding to the Python
292
- # physical quantity of the `target_unit`. However, because of the preceding `if` statement, I expect this
293
- # value to **not** be returned. (It is actually an error if it is returned; unfortunately, it is an
294
- # undetectable error because I cannot distinguish the zero value from a zero value actually wrapped in
295
- # the `Option<T>.Some` expression.
296
- net_physical_quantity = _physical_quantity_to_net_physical_quantity[target_unit.value.physical_quantity]
297
- result = net_option.ValueOr.Overloads[net_physical_quantity](net_physical_quantity.Zero)
298
- return result
299
-
300
- return toolz.pipe(
301
- optional_net_quantity,
302
- net_option_as_pythonic,
303
- option.maybe,
304
- )
305
-
306
-
307
- def as_measurement_from_option(target_unit: Union[units.Common, units.Metric, units.UsOilfield],
308
- optional_net_quantity: Option[UnitsNet.IQuantity]):
309
- maybe_python_measurement = _python_measurement_option(target_unit, optional_net_quantity)
310
- return as_measurement(target_unit, maybe_python_measurement)
311
-
312
-
313
- @singledispatch
314
- @toolz.curry
315
- def as_net_quantity(unknown, _measurement: om.Quantity) -> Optional[UnitsNet.IQuantity]:
316
- """
317
- Convert a .NET UnitsNet.IQuantity to a `pint` `Quantity` instance.
318
-
319
- This function is registered as the type-handler for the `object` type. In our situation, arriving here
320
- indicates an error by an implementer and so raises an error.
321
-
322
- Args:
323
- unknown: A parameter whose type is not expected.
324
- _measurement: The `Quantity` instance to convert.
325
-
326
- Returns:
327
- The equivalent `UnitsNet.IQuantity` instance.
328
- """
329
- raise TypeError(f'First argument, {unknown}, has type {type(unknown)}, unexpected by `as_net_quantity`.')
330
-
331
-
332
- # noinspection PyUnresolvedReferences
333
- _PINT_UNIT_CREATE_NET_UNITS = {
334
- om.registry.deg: UnitsNet.Angle.FromDegrees,
335
- om.registry.min: UnitsNet.Duration.FromMinutes,
336
- om.registry.ft_lb: UnitsNet.Energy.FromFootPounds,
337
- om.registry.J: UnitsNet.Energy.FromJoules,
338
- om.registry.lbf: UnitsNet.Force.FromPoundsForce,
339
- om.registry.N: UnitsNet.Force.FromNewtons,
340
- om.registry.ft: UnitsNet.Length.FromFeet,
341
- om.registry.m: UnitsNet.Length.FromMeters,
342
- om.registry.lb: UnitsNet.Mass.FromPounds,
343
- om.registry.kg: UnitsNet.Mass.FromKilograms,
344
- om.registry.hp: UnitsNet.Power.FromMechanicalHorsepower,
345
- om.registry.W: UnitsNet.Power.FromWatts,
346
- om.registry.psi: UnitsNet.Pressure.FromPoundsForcePerSquareInch,
347
- om.registry.kPa: UnitsNet.Pressure.FromKilopascals,
348
- om.registry.oil_bbl / om.registry.min: net_volume_flow_from_oil_bbl_per_min,
349
- ((om.registry.m ** 3) / om.registry.min): net_volume_flow_from_cu_m_per_min,
350
- om.registry.degF: UnitsNet.Temperature.FromDegreesFahrenheit,
351
- om.registry.degC: UnitsNet.Temperature.FromDegreesCelsius,
352
- om.registry.oil_bbl: UnitsNet.Volume.FromOilBarrels,
353
- (om.registry.m ** 3): UnitsNet.Volume.FromCubicMeters,
354
- }
355
-
356
-
357
- def _us_oilfield_slurry_rate(qv):
358
- return UnitsNet.Density.FromPoundsPerCubicFoot(qv)
359
-
360
-
361
- # noinspection PyUnresolvedReferences
362
- _PHYSICAL_QUANTITY_PINT_UNIT_NET_UNITS = {
363
- opq.PhysicalQuantity.DENSITY: {
364
- om.registry.lb / om.registry.cu_ft: _us_oilfield_slurry_rate,
365
- om.registry.lb / om.registry.ft ** 3: _us_oilfield_slurry_rate,
366
- om.registry.kg / (om.registry.m ** 3): UnitsNet.Density.FromKilogramsPerCubicMeter,
367
- },
368
- opq.PhysicalQuantity.PROPPANT_CONCENTRATION: {
369
- om.registry.lb / om.registry.gal: net_mass_concentration_from_lbs_per_gal,
370
- om.registry.kg / (om.registry.m ** 3): net_mass_concentration_from_kg_per_cu_m,
371
- },
372
- }
373
-
374
-
375
- # noinspection PyUnresolvedReferences
376
- @as_net_quantity.register(opq.PhysicalQuantity)
377
- @toolz.curry
378
- def as_net_quantity_using_physical_quantity(physical_quantity,
379
- measurement: om.Quantity) -> Optional[UnitsNet.IQuantity]:
380
- """
381
- Convert a `Quantity` instance to a .NET `UnitsNet.IQuantity` instance.
382
-
383
- Args:
384
- physical_quantity: The `PhysicalQuantity`. Although we try to determine a unique mapping between units
385
- in `pint` and .NET `UnitsNet` units, we cannot perform a unique mapping for density and proppant
386
- concentration measured in the metric system (the units of both these physical quantities are
387
- "kg/m**3").
388
- measurement: The `Quantity` instance to convert.
389
-
390
- Returns:
391
- The equivalent `UnitsNet.IQuantity` instance.
392
- """
393
- if math.isnan(measurement.magnitude):
394
- return None
395
-
396
- quantity = UnitsNet.QuantityValue.op_Implicit(measurement.magnitude)
397
- if physical_quantity == opq.PhysicalQuantity.DENSITY:
398
- return toolz.get_in([physical_quantity, measurement.units], _PHYSICAL_QUANTITY_PINT_UNIT_NET_UNITS)(quantity)
399
-
400
- if physical_quantity == opq.PhysicalQuantity.PROPPANT_CONCENTRATION:
401
- return toolz.get_in([physical_quantity, measurement.units],
402
- _PHYSICAL_QUANTITY_PINT_UNIT_NET_UNITS)(measurement.magnitude)
403
-
404
- if physical_quantity == opq.PhysicalQuantity.SLURRY_RATE:
405
- return toolz.get(measurement.units, _PINT_UNIT_CREATE_NET_UNITS)(measurement.magnitude)
406
-
407
- return toolz.get(measurement.units, _PINT_UNIT_CREATE_NET_UNITS)(quantity)
408
-
409
-
410
- # noinspection PyUnresolvedReferences
411
- @as_net_quantity.register(units.Common)
412
- @toolz.curry
413
- def as_net_quantity_using_common_units(to_common_unit, measurement: om.Quantity) -> Optional[UnitsNet.IQuantity]:
414
- """
415
- Convert a `Quantity` instance to a .NET `UnitsNet.IQuantity` instance corresponding `to_unit`.
416
-
417
- Args:
418
- to_common_unit: The target unit of measurement.
419
- measurement: The `Quantity` instance to convert.
420
-
421
- Returns:
422
- The equivalent `UnitsNet.IQuantity` instance.
423
- """
424
- # units.Common support no conversion so simply call another implementation.
425
- return as_net_quantity(to_common_unit.value.physical_quantity, measurement)
426
-
427
-
428
- # noinspection PyUnresolvedReferences
429
- @as_net_quantity.register(units.Metric)
430
- @as_net_quantity.register(units.UsOilfield)
431
- @toolz.curry
432
- def as_net_quantity_in_specified_unit(specified_unit, measurement: om.Quantity) -> Optional[UnitsNet.IQuantity]:
433
- """
434
- Convert a `pint` `Quantity` to a .NET UnitsNet.IQuantity instance in a specified, but compatible unit.
435
-
436
- Args:
437
- specified_unit: The unit for the converted `Quantity` instance.
438
- measurement: The `Quantity` instance to convert.
439
-
440
- Returns:
441
- The equivalent `Quantity` instance in the specified unit.
442
- """
443
- target_measurement = measurement.to(specified_unit.value.unit)
444
- return as_net_quantity(specified_unit.value.physical_quantity, target_measurement)
445
-
446
-
447
- def equal_net_quantities(left_quantity: UnitsNet.IQuantity, right_quantity: UnitsNet.IQuantity,
448
- comparison_details: EqualsComparisonDetails = EqualsComparisonDetails()):
449
- """
450
- Compares two UnitsNet.IQuantity instances for equality
451
-
452
- Python.NET transforms == (perhaps indirectly) into a call to Equals. Unfortunately, comparing
453
- two measurements that have been transformed may have floating point differences. Specifically,
454
- UnitsNet marks the `Equals` method as `Obsolete` with the following message:
455
- > "It is not safe to compare equality due to using System.Double as the internal representation.
456
- > It is very easy to get slightly different values due to floating point operations. Instead use
457
- > Equals(Length, double, ComparisonType) to provide the max allowed absolute or relative error."
458
-
459
- Consequently, to determine if two `UnitsNet.IQuantity` instances are equal, I use the
460
- `Equals(Length, double, ComparisonType)` method applied to each instance.
461
-
462
- Args:
463
- left_quantity: The `IQuantity` instance on the "left-hand-side" of the (implicit) == operator.
464
- right_quantity: The `IQuantity` instance on the "right-hand-side" of the (implicit) == operator.
465
- comparison_details: The details of how to compare the two `UnitsNet.IQuantity` instances.
466
-
467
- Returns:
468
-
469
- """
470
- return left_quantity.Equals(right_quantity, comparison_details.tolerance, comparison_details.comparison_type)
471
-
472
-
473
- def net_decimal_to_float(net_decimal: System.Decimal) -> float:
474
- """
475
- Convert a .NET Decimal value to a Python float.
476
-
477
- Python.NET currently leaves .NET values of type `Decimal` unconverted. For example, UnitsNet models units
478
- of the physical quantity, power, as values of type .NET 'QuantityValue` whose `Value` property returns a
479
- value of .NET `Decimal` type. This function assists in converting those values to Python values of type
480
- `float`.
481
-
482
- Args:
483
- net_decimal: The .NET `Decimal` value to convert.
484
-
485
- Returns:
486
- A value of type `float` that is "equivalent" to the .NET `Decimal` value. Note that this conversion is
487
- "lossy" because .NET `Decimal` values are exact, but `float` values are not.
488
- """
489
- return System.Decimal.ToDouble(net_decimal)
490
-
491
-
492
- _UNIT_NET_UNITS = {
493
- units.Common.ANGLE: UnitsNet.Units.AngleUnit.Degree,
494
- units.Common.DURATION: UnitsNet.Units.DurationUnit.Minute,
495
- units.UsOilfield.DENSITY: UnitsNet.Units.DensityUnit.PoundPerCubicFoot,
496
- units.Metric.DENSITY: UnitsNet.Units.DensityUnit.KilogramPerCubicMeter,
497
- units.UsOilfield.ENERGY: UnitsNet.Units.EnergyUnit.FootPound,
498
- units.Metric.ENERGY: UnitsNet.Units.EnergyUnit.Joule,
499
- units.UsOilfield.FORCE: UnitsNet.Units.ForceUnit.PoundForce,
500
- units.Metric.FORCE: UnitsNet.Units.ForceUnit.Newton,
501
- units.UsOilfield.LENGTH: UnitsNet.Units.LengthUnit.Foot,
502
- units.Metric.LENGTH: UnitsNet.Units.LengthUnit.Meter,
503
- units.UsOilfield.MASS: UnitsNet.Units.MassUnit.Pound,
504
- units.Metric.MASS: UnitsNet.Units.MassUnit.Kilogram,
505
- units.UsOilfield.POWER: UnitsNet.Units.PowerUnit.MechanicalHorsepower,
506
- units.Metric.POWER: UnitsNet.Units.PowerUnit.Watt,
507
- units.UsOilfield.PRESSURE: UnitsNet.Units.PressureUnit.PoundForcePerSquareInch,
508
- units.Metric.PRESSURE: UnitsNet.Units.PressureUnit.Kilopascal,
509
- units.UsOilfield.PROPPANT_CONCENTRATION: UnitsNet.Units.MassConcentrationUnit.PoundPerUSGallon,
510
- units.Metric.PROPPANT_CONCENTRATION: UnitsNet.Units.MassConcentrationUnit.KilogramPerCubicMeter,
511
- units.UsOilfield.SLURRY_RATE: UnitsNet.Units.VolumeFlowUnit.OilBarrelPerMinute,
512
- units.Metric.SLURRY_RATE: UnitsNet.Units.VolumeFlowUnit.CubicMeterPerMinute,
513
- units.UsOilfield.TEMPERATURE: UnitsNet.Units.TemperatureUnit.DegreeFahrenheit,
514
- units.Metric.TEMPERATURE: UnitsNet.Units.TemperatureUnit.DegreeCelsius,
515
- units.UsOilfield.VOLUME: UnitsNet.Units.VolumeUnit.OilBarrel,
516
- units.Metric.VOLUME: UnitsNet.Units.VolumeUnit.CubicMeter,
517
- }
518
-
519
-
520
- @toolz.curry
521
- def _convert_net_quantity_to_different_unit(target_unit: units.UnitSystem,
522
- net_quantity: UnitsNet.IQuantity) -> UnitsNet.IQuantity:
523
- """
524
- Convert one .NET `UnitsNet.IQuantity` to another .NET `UnitsNet.IQuantity` in a different unit `target_unit`
525
- Args:
526
- net_quantity: The `UnitsNet.IQuantity` instance to convert.
527
- target_unit: The unit to which to convert `maybe_net_quantity`.
528
-
529
- Returns:
530
- The .NET `UnitsNet.IQuantity` converted to `target_unit`.
531
- """
532
- result = net_quantity.ToUnit(_UNIT_NET_UNITS[target_unit])
533
- return result
534
-
535
-
536
- def _net_decimal_to_float(net_decimal: System.Decimal) -> float:
537
- """
538
- Convert a .NET Decimal value to a Python float.
539
-
540
- Python.NET currently leaves .NET values of type `Decimal` unconverted. For example, UnitsNet models units
541
- of the physical quantity, power, as values of type .NET 'QuantityValue` whose `Value` property returns a
542
- value of .NET `Decimal` type. This function assists in converting those values to Python values of type
543
- `float`.
544
-
545
- Args:
546
- net_decimal: The .NET `Decimal` value to convert.
547
-
548
- Returns:
549
- A value of type `float` that is "equivalent" to the .NET `Decimal` value. Note that this conversion is
550
- "lossy" because .NET `Decimal` values are exact, but `float` values are not.
551
- """
552
- return System.Decimal.ToDouble(net_decimal)
553
-
554
-
555
- _PHYSICAL_QUANTITY_NET_UNIT_PINT_UNITS = {
556
- opq.PhysicalQuantity.DENSITY: {
557
- UnitsNet.Units.DensityUnit.PoundPerCubicFoot: om.registry.lb / om.registry.ft ** 3,
558
- UnitsNet.Units.DensityUnit.KilogramPerCubicMeter: om.registry.kg / (om.registry.m ** 3),
559
- },
560
- opq.PhysicalQuantity.ENERGY: {
561
- UnitsNet.Units.EnergyUnit.FootPound: om.registry.ft_lb,
562
- UnitsNet.Units.EnergyUnit.Joule: om.registry.J,
563
- },
564
- opq.PhysicalQuantity.FORCE: {
565
- UnitsNet.Units.ForceUnit.PoundForce: om.registry.lbf,
566
- UnitsNet.Units.ForceUnit.Newton: om.registry.N,
567
- },
568
- opq.PhysicalQuantity.LENGTH: {
569
- UnitsNet.Units.LengthUnit.Foot: om.registry.ft,
570
- UnitsNet.Units.LengthUnit.Meter: om.registry.m,
571
- },
572
- opq.PhysicalQuantity.MASS: {
573
- UnitsNet.Units.MassUnit.Pound: om.registry.lb,
574
- UnitsNet.Units.MassUnit.Kilogram: om.registry.kg,
575
- },
576
- opq.PhysicalQuantity.POWER: {
577
- UnitsNet.Units.PowerUnit.MechanicalHorsepower: om.registry.hp,
578
- UnitsNet.Units.PowerUnit.Watt: om.registry.W,
579
- },
580
- opq.PhysicalQuantity.PRESSURE: {
581
- UnitsNet.Units.PressureUnit.PoundForcePerSquareInch: om.registry.psi,
582
- UnitsNet.Units.PressureUnit.Kilopascal: om.registry.kPa,
583
- },
584
- opq.PhysicalQuantity.PROPPANT_CONCENTRATION: {
585
- UnitsNet.Units.MassConcentrationUnit.PoundPerUSGallon: om.registry.lb / om.registry.gallon,
586
- UnitsNet.Units.MassConcentrationUnit.KilogramPerCubicMeter: om.registry.kg / om.registry.m ** 3,
587
- },
588
- opq.PhysicalQuantity.SLURRY_RATE: {
589
- UnitsNet.Units.VolumeFlowUnit.OilBarrelPerMinute: om.registry.oil_bbl / om.registry.min,
590
- UnitsNet.Units.VolumeFlowUnit.CubicMeterPerMinute: om.registry.m ** 3 / om.registry.min,
591
- },
592
- opq.PhysicalQuantity.TEMPERATURE: {
593
- UnitsNet.Units.TemperatureUnit.DegreeFahrenheit: om.registry.degF,
594
- UnitsNet.Units.TemperatureUnit.DegreeCelsius: om.registry.degC,
595
- },
596
- opq.PhysicalQuantity.VOLUME: {
597
- UnitsNet.Units.VolumeUnit.OilBarrel: om.registry.oil_bbl,
598
- UnitsNet.Units.VolumeUnit.CubicMeter: om.registry.m ** 3,
599
- },
600
- }
601
-
602
-
603
- def _to_pint_unit(physical_quantity: opq.PhysicalQuantity, net_unit: UnitsNet.Units) -> om.Unit:
604
- """
605
- Convert `net_unit`, a unit of measure for `physical_quantity`, to a `pint` unit.
606
-
607
- Args:
608
- physical_quantity: The physical quantity measured by `net_unit`.
609
- net_unit: The .NET UnitsNet.Unit to be converted.
610
-
611
- Returns:
612
- The `pint` Unit corresponding to `net_unit`.
613
- """
614
- result = toolz.get_in([physical_quantity, net_unit], _PHYSICAL_QUANTITY_NET_UNIT_PINT_UNITS)
615
- if result is not None:
616
- return result
617
- elif physical_quantity == opq.PhysicalQuantity.ANGLE:
618
- return om.registry.deg
619
- elif physical_quantity == opq.PhysicalQuantity.DURATION:
620
- return om.registry.min
orchid/net_stage_qc.py DELETED
@@ -1,62 +0,0 @@
1
- # Copyright 2017-2025 KAPPA
2
- #
3
- # Licensed under the Apache License, Version 2.0 (the "License");
4
- # you may not use this file except in compliance with the License.
5
- # You may obtain a copy of the License at
6
- #
7
- # http://www.apache.org/licenses/LICENSE-2.0
8
- #
9
- # Unless required by applicable law or agreed to in writing, software
10
- # distributed under the License is distributed on an "AS IS" BASIS,
11
- # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
- # See the License for the specific language governing permissions and
13
- # limitations under the License.
14
- #
15
- # This file is part of Orchid and related technologies.
16
- #
17
-
18
- """
19
- Expose constants to the Orchid Python API.
20
-
21
- The .NET stage QC "class" implementation depends upon a number of constants. This module exposes those constants to the
22
- Orchid Python API.
23
- """
24
-
25
- import enum
26
- import uuid
27
-
28
- import toolz.curried as toolz
29
-
30
- # noinspection PyUnresolvedReferences,PyPackageRequirements
31
- from Orchid.FractureDiagnostics import CorrectionStatus as NetCorrectionStatus
32
-
33
-
34
- class CorrectionStatus(enum.Enum):
35
- # TODO: Change to use .NET `Enum` member.
36
- # Python.NET always transforms .NET `Enum` members into Python `int` values. This transformation is a known issue
37
- # (https://github.com/pythonnet/pythonnet/issues/1220). The Python.NET team has corrected the issue but only for
38
- # Python.NET 3.x; it has no plans for a backport.
39
- #
40
- # Although I have successfully use the Python.NET transformation of .NET `Enum` members to `ints`; I have
41
- # encountered issues with its usage in .NET `Variant` types which is used for stage QC information.
42
- #
43
- # To simplify the "work-around" implemented in `native_stage_qc_adapter`, I use the hard-coded string value of
44
- # .NET `CorrectionStatus`.
45
- #
46
- # See also the Jupyter notebook, `features/notebooks/explore_stage_qc.py`, for attempts to use the .NET `Enum`.
47
- CONFIRMED = 'Confirmed'
48
- NEW = 'New'
49
- UNCONFIRMED = 'Unconfirmed'
50
-
51
-
52
- class StageQCTags(enum.Enum):
53
- QC_NOTES = 'stage_qc_notes'
54
- START_STOP_CONFIRMATION = 'stage_start_stop_confirmation'
55
-
56
-
57
- def make_key(stage_id: uuid.UUID, tag: StageQCTags) -> str:
58
- return f'{str(stage_id)}|{tag.value}'
59
-
60
-
61
- make_start_stop_confirmation_key = toolz.flip(make_key)(StageQCTags.START_STOP_CONFIRMATION)
62
- make_qc_notes_key = toolz.flip(make_key)(StageQCTags.QC_NOTES)