orchid-python-api 5.25.2__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.
- orchid_python_api/examples/search_data_frames.py +1 -1
- {orchid_python_api-5.25.2.dist-info → orchid_python_api-5.25.4.dist-info}/METADATA +4 -3
- orchid_python_api-5.25.4.dist-info/RECORD +38 -0
- {orchid_python_api-5.25.2.dist-info → orchid_python_api-5.25.4.dist-info}/WHEEL +1 -1
- ReleaseNotes.md +0 -708
- copy_orchid_examples.py +0 -88
- copy_orchid_low_level_examples.py +0 -93
- copy_orchid_manual_examples.py +0 -93
- copy_orchid_tutorials.py +0 -88
- orchid/VERSION +0 -1
- orchid/__init__.py +0 -42
- orchid/__version__.py +0 -18
- orchid/base.py +0 -31
- orchid/base_time_series_adapter.py +0 -91
- orchid/configuration.py +0 -162
- orchid/convert.py +0 -44
- orchid/core.py +0 -149
- orchid/dom_project_object.py +0 -28
- orchid/dot_net.py +0 -68
- orchid/dot_net_disposable.py +0 -64
- orchid/dot_net_dom_access.py +0 -241
- orchid/measurement.py +0 -35
- orchid/native_data_frame_adapter.py +0 -247
- orchid/native_fiber_data.py +0 -73
- orchid/native_fiber_data_set_info.py +0 -28
- orchid/native_monitor_adapter.py +0 -67
- orchid/native_project_user_data_adapter.py +0 -137
- orchid/native_stage_adapter.py +0 -631
- orchid/native_stage_part_adapter.py +0 -50
- orchid/native_subsurface_point.py +0 -70
- orchid/native_time_series_adapter.py +0 -54
- orchid/native_trajectory_adapter.py +0 -246
- orchid/native_treatment_calculations.py +0 -158
- orchid/native_treatment_curve_adapter.py +0 -60
- orchid/native_well_adapter.py +0 -134
- orchid/net_date_time.py +0 -328
- orchid/net_enumerable.py +0 -72
- orchid/net_fracture_diagnostics_factory.py +0 -55
- orchid/net_quantity.py +0 -620
- orchid/net_stage_qc.py +0 -62
- orchid/physical_quantity.py +0 -37
- orchid/project.py +0 -182
- orchid/project_store.py +0 -269
- orchid/reference_origins.py +0 -34
- orchid/script_adapter_context.py +0 -81
- orchid/searchable_data_frames.py +0 -44
- orchid/searchable_project_objects.py +0 -190
- orchid/searchable_stage_parts.py +0 -73
- orchid/searchable_stages.py +0 -29
- orchid/unit_system.py +0 -173
- orchid/utils.py +0 -14
- orchid/validation.py +0 -52
- orchid/version.py +0 -37
- orchid_python_api-5.25.2.dist-info/LICENSE +0 -176
- orchid_python_api-5.25.2.dist-info/RECORD +0 -88
- {orchid_python_api-5.25.2.dist-info → orchid_python_api-5.25.4.dist-info}/entry_points.txt +0 -0
- /LICENSE → /orchid_python_api-5.25.4.dist-info/licenses/LICENSE +0 -0
orchid/dot_net_dom_access.py
DELETED
|
@@ -1,241 +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
|
-
import uuid
|
|
19
|
-
from typing import Callable, Mapping, Union
|
|
20
|
-
|
|
21
|
-
import deal
|
|
22
|
-
import option
|
|
23
|
-
import toolz.curried as toolz
|
|
24
|
-
|
|
25
|
-
from orchid import (
|
|
26
|
-
unit_system as units,
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
# noinspection PyUnresolvedReferences
|
|
30
|
-
from System import Guid
|
|
31
|
-
|
|
32
|
-
# These methods in this module are based on the StackOverflow post:
|
|
33
|
-
# https://stackoverflow.com/questions/36580931/python-property-factory-or-descriptor-class-for-wrapping-an-external-library
|
|
34
|
-
#
|
|
35
|
-
# Additionally, it resolves an issue I was experiencing with PyCharm: when I used `property` directly
|
|
36
|
-
# in the class definition, PyCharm reported "Property 'xyz' could not be read. I think it might have been
|
|
37
|
-
# than I needed to apply `curry` to the "getter method" I also defined in the class in order to pass the
|
|
38
|
-
# attribute name at definition time (because `self` was only available at run-time).
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
def get_dot_net_property_value(attribute_name, dom_object):
|
|
42
|
-
"""
|
|
43
|
-
Return the value of the DOM property whose name corresponds to `attribute_name`.
|
|
44
|
-
:param attribute_name: The Python `attribute_name`.
|
|
45
|
-
:param dom_object: The DOM object whose property is sought.
|
|
46
|
-
:return: The value of the DOM property.
|
|
47
|
-
"""
|
|
48
|
-
@toolz.curry
|
|
49
|
-
def python_name_to_words(python_name):
|
|
50
|
-
return python_name.split('_')
|
|
51
|
-
|
|
52
|
-
def capitalize_words(words):
|
|
53
|
-
return toolz.map(str.capitalize, words)
|
|
54
|
-
|
|
55
|
-
def words_to_dot_net_property_name(words):
|
|
56
|
-
return ''.join(words)
|
|
57
|
-
|
|
58
|
-
@toolz.curry
|
|
59
|
-
def get_value_from_dom(dom, property_name):
|
|
60
|
-
return getattr(dom, property_name)
|
|
61
|
-
|
|
62
|
-
# The function, `thread_last`, from `toolz.curried`, "splices" threads a value (the first argument)
|
|
63
|
-
# through each of the remaining functions as the *last* argument to each of these functions.
|
|
64
|
-
result = toolz.thread_last(attribute_name,
|
|
65
|
-
python_name_to_words,
|
|
66
|
-
capitalize_words,
|
|
67
|
-
words_to_dot_net_property_name,
|
|
68
|
-
get_value_from_dom(dom_object))
|
|
69
|
-
return result
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
def dom_property(attribute_name, docstring):
|
|
73
|
-
"""
|
|
74
|
-
Return the property of the DOM corresponding to `attribute_name` with doc string.
|
|
75
|
-
:param attribute_name: The name of the Python attribute.
|
|
76
|
-
:param docstring: The doc string to be attached to the resulting property.
|
|
77
|
-
:return: The Python property wrapping the value of the DOM property.
|
|
78
|
-
"""
|
|
79
|
-
def getter(self):
|
|
80
|
-
result = get_dot_net_property_value(attribute_name, self._adaptee)
|
|
81
|
-
return result
|
|
82
|
-
|
|
83
|
-
# Ensure no setter for the DOM properties
|
|
84
|
-
return property(fget=getter, doc=docstring, fset=None)
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
def map_reduce_dom_property(attribute_name, docstring, mapper, reducer, initial):
|
|
88
|
-
"""
|
|
89
|
-
Return reduced collection property of the DOM corresponding to `attribute_name` with doc string, `docstring`.
|
|
90
|
-
|
|
91
|
-
Args:
|
|
92
|
-
attribute_name: The name of the transformed attribute.
|
|
93
|
-
docstring: The doc string to be attached to the resultant property.
|
|
94
|
-
mapper: A callable that transforms every item of the .NET DOM property.
|
|
95
|
-
reducer: A callable invoked to reduce the collection.
|
|
96
|
-
initial: The initial value of the reduction.
|
|
97
|
-
|
|
98
|
-
Returns:
|
|
99
|
-
The Python property wrapping the mapped and reduced DOM (collection) property items.
|
|
100
|
-
"""
|
|
101
|
-
def getter(self):
|
|
102
|
-
result = toolz.pipe(get_dot_net_property_value(attribute_name, self._adaptee),
|
|
103
|
-
lambda container: container.Items,
|
|
104
|
-
toolz.map(mapper),
|
|
105
|
-
lambda items: toolz.reduce(reducer, items, initial))
|
|
106
|
-
return result
|
|
107
|
-
|
|
108
|
-
# Ensure no setter for the DOM properties
|
|
109
|
-
return property(fget=getter, doc=docstring, fset=None)
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
def transformed_dom_property(attribute_name, docstring, transformer):
|
|
113
|
-
"""
|
|
114
|
-
Return the transformed property of the DOM corresponding to `attribute_name`.
|
|
115
|
-
:param attribute_name: The name of the Python attribute.
|
|
116
|
-
:param docstring: The doc string to be attached to the resulting property.
|
|
117
|
-
:param transformer: A callable to transform the value returned by the .NET DOM property.
|
|
118
|
-
:return: The Python property wrapping the transformed value of the DOM property.
|
|
119
|
-
"""
|
|
120
|
-
def getter(self):
|
|
121
|
-
raw_result = get_dot_net_property_value(attribute_name, self._adaptee)
|
|
122
|
-
result = transformer(raw_result)
|
|
123
|
-
return result
|
|
124
|
-
|
|
125
|
-
# Ensure no setter for the DOM properties
|
|
126
|
-
return property(fget=getter, doc=docstring, fset=None)
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
def transformed_dom_property_iterator(attribute_name, docstring, transformer):
|
|
130
|
-
"""
|
|
131
|
-
Return transformed collection property of the DOM corresponding to `attribute_name` with doc string, `docstring`.
|
|
132
|
-
:param attribute_name: The name of the original attribute.
|
|
133
|
-
:param docstring: The doc string to be attached to the resultant property.
|
|
134
|
-
:param transformer: A callable invoked on each value in the list returned by the .NET DOM property.
|
|
135
|
-
:return: The Python property wrapping a Python iterator mapping values from the DOM property (collection) items.
|
|
136
|
-
"""
|
|
137
|
-
def getter(self):
|
|
138
|
-
container = get_dot_net_property_value(attribute_name, self._adaptee)
|
|
139
|
-
result = toolz.map(transformer, container.Items)
|
|
140
|
-
return result
|
|
141
|
-
|
|
142
|
-
# Ensure no setter for the DOM properties
|
|
143
|
-
return property(fget=getter, doc=docstring, fset=None)
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
def as_object_id(guid: Guid):
|
|
147
|
-
return uuid.UUID(str(guid))
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
class DotNetAdapter:
|
|
151
|
-
@deal.pre(lambda _self, adaptee, _net_project_callable=None: adaptee is not None)
|
|
152
|
-
def __init__(self, adaptee):
|
|
153
|
-
"""
|
|
154
|
-
Construct an instance adapting the .NET `adaptee`.
|
|
155
|
-
|
|
156
|
-
Args:
|
|
157
|
-
adaptee: The .NET DOM object to adapt.
|
|
158
|
-
"""
|
|
159
|
-
self._adaptee = adaptee
|
|
160
|
-
|
|
161
|
-
@property
|
|
162
|
-
def dom_object(self):
|
|
163
|
-
"""
|
|
164
|
-
(PROTECTED) Determine the DOM object being adapted.
|
|
165
|
-
|
|
166
|
-
This method is only intended to be used **INSIDE** the orchid package. It is **NOT** intended for
|
|
167
|
-
external use.
|
|
168
|
-
|
|
169
|
-
Returns:
|
|
170
|
-
The .NET DOM object being adapted.
|
|
171
|
-
"""
|
|
172
|
-
return self._adaptee
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
class IdentifiedDotNetAdapter(DotNetAdapter):
|
|
176
|
-
def __init__(self, adaptee, net_project_callable: Callable = None):
|
|
177
|
-
"""
|
|
178
|
-
Construct an instance adapting `adaptee` with access to the .NET `IProject` provided by `net_project_callable`.
|
|
179
|
-
Args:
|
|
180
|
-
adaptee: The .NET DOM object to adapt.
|
|
181
|
-
net_project_callable: A callable returning the .NET `IProject` instance.
|
|
182
|
-
"""
|
|
183
|
-
super().__init__(adaptee)
|
|
184
|
-
self._net_project_callable = net_project_callable
|
|
185
|
-
|
|
186
|
-
object_id = transformed_dom_property('object_id', 'The object ID of the adapted .NET DOM object.', as_object_id)
|
|
187
|
-
|
|
188
|
-
@property
|
|
189
|
-
def expect_project_units(self) -> Union[units.UsOilfield, units.Metric]:
|
|
190
|
-
"""
|
|
191
|
-
(PROTECTED) Return the `UnitSystem` appropriate the .NET `IProject` of this instance.
|
|
192
|
-
|
|
193
|
-
Although by naming convention, this property is "public," the author intends it to be "protected";
|
|
194
|
-
that is, only called by classes derived from `IdentifiedDotNetAdapter` (and not necessarily all of those).
|
|
195
|
-
|
|
196
|
-
Returns:
|
|
197
|
-
A unit system - either `units.UsOilfield` or `units.Metric`.
|
|
198
|
-
|
|
199
|
-
Raises:
|
|
200
|
-
ValueError if the derived instances, for example, a `BaseTimeSeriesAdapter` is **not** associated with
|
|
201
|
-
an `IProject`.
|
|
202
|
-
"""
|
|
203
|
-
return self._maybe_project_units.expect('Expected associated project')
|
|
204
|
-
|
|
205
|
-
@property
|
|
206
|
-
def _maybe_project_units(self) -> option.Option[Union[units.UsOilfield, units.Metric]]:
|
|
207
|
-
"""
|
|
208
|
-
Return the `option.Option[UnitSystem]` appropriate the .NET `IProject` of this instance.
|
|
209
|
-
|
|
210
|
-
Although by naming convention, this property is "public," the author intends it to be "protected";
|
|
211
|
-
that is, only called by classes derived from `IdentifiedDotNetAdapter` (and not necessarily all of those).
|
|
212
|
-
|
|
213
|
-
Returns:
|
|
214
|
-
An `option.Option()` instance.
|
|
215
|
-
|
|
216
|
-
Some derived classes, such as 'NativeWellAdapter` and
|
|
217
|
-
`NativeDataFrame`, contain a `Project` property that returns the `IProject` of the .NET class.
|
|
218
|
-
For other derived classes, such as `BaseTimeSeriesAdapter`, the `IProject` cannot be determined. In the
|
|
219
|
-
former situation, an associated `IProject`, this method returns an
|
|
220
|
-
`option.Some[units.UsOilfield]` or an `option.Some[units.Metric]`. For the latter situation, no
|
|
221
|
-
associated `IProject`, this method returns `option.NONE`. The methods of the
|
|
222
|
-
[option.Option class](https://mat1g3r.github.io/option/option.html#module-option.option) allow
|
|
223
|
-
derived classes to process these two situations with less likelihood of an error.
|
|
224
|
-
"""
|
|
225
|
-
return (option.Some(units.as_unit_system(self._net_project_callable().ProjectUnits))
|
|
226
|
-
if self._net_project_callable
|
|
227
|
-
else option.NONE)
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
def dictionary_by_id(accumulator: Mapping[uuid.UUID, IdentifiedDotNetAdapter], mapped_object: IdentifiedDotNetAdapter):
|
|
231
|
-
"""
|
|
232
|
-
Return a `Mapping` resulting from adding `mapped_object` to `accumulator`.
|
|
233
|
-
|
|
234
|
-
Args:
|
|
235
|
-
accumulator: The accumulated result.
|
|
236
|
-
mapped_object: The `IdentifiedDotNetAdapter` to be added to `accumulator`.
|
|
237
|
-
|
|
238
|
-
Returns:
|
|
239
|
-
The updated `Mapping`.
|
|
240
|
-
"""
|
|
241
|
-
return toolz.assoc(accumulator, mapped_object.object_id, mapped_object)
|
orchid/measurement.py
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# This file is part of Orchid and related technologies.
|
|
3
|
-
#
|
|
4
|
-
# Copyright (c) 2017-2025 KAPPA. All Rights Reserved.
|
|
5
|
-
#
|
|
6
|
-
# LEGAL NOTICE:
|
|
7
|
-
# Orchid contains trade secrets and otherwise confidential information
|
|
8
|
-
# owned by KAPPA. Access to and use of this information is
|
|
9
|
-
# strictly limited and controlled by the Company. This file may not be copied,
|
|
10
|
-
# distributed, or otherwise disclosed outside of the Company's facilities
|
|
11
|
-
# except under appropriate precautions to maintain the confidentiality hereof,
|
|
12
|
-
# and may not be used in any way not expressly authorized by the Company.
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
import pint
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
registry = pint.UnitRegistry()
|
|
20
|
-
"""
|
|
21
|
-
The single registry of all known `pint` units. See the Pint tutorial,
|
|
22
|
-
https://pint.readthedocs.io/en/stable/tutorial.html, for general information on the registry. Specifically,
|
|
23
|
-
see the section, https://pint.readthedocs.io/en/stable/tutorial.html#using-pint-in-your-projects, for the
|
|
24
|
-
"perils" of using multiple registry instances.
|
|
25
|
-
"""
|
|
26
|
-
|
|
27
|
-
# Expose general types for use by type annotations
|
|
28
|
-
Quantity = registry.Quantity
|
|
29
|
-
"""The type of a Pint measurement exposed for convenience."""
|
|
30
|
-
Unit = registry.Unit
|
|
31
|
-
"""The type of Pint units of measure."""
|
|
32
|
-
|
|
33
|
-
# Register this instance of the registry as the application registry to support pickling and unpickling of Pint
|
|
34
|
-
# Quantity and Unit instances.
|
|
35
|
-
pint.set_application_registry(registry)
|
|
@@ -1,247 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# This file is part of Orchid and related technologies.
|
|
3
|
-
#
|
|
4
|
-
# Copyright (c) 2017-2025 KAPPA. All Rights Reserved.
|
|
5
|
-
#
|
|
6
|
-
# LEGAL NOTICE:
|
|
7
|
-
# Orchid contains trade secrets and otherwise confidential information
|
|
8
|
-
# owned by KAPPA. Access to and use of this information is
|
|
9
|
-
# strictly limited and controlled by the Company. This file may not be copied,
|
|
10
|
-
# distributed, or otherwise disclosed outside of the Company's facilities
|
|
11
|
-
# except under appropriate precautions to maintain the confidentiality hereof,
|
|
12
|
-
# and may not be used in any way not expressly authorized by the Company.
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
import dataclasses
|
|
16
|
-
import traceback
|
|
17
|
-
import uuid
|
|
18
|
-
from typing import Iterable
|
|
19
|
-
|
|
20
|
-
import functools
|
|
21
|
-
import option
|
|
22
|
-
import pandas as pd
|
|
23
|
-
import toolz.curried as toolz
|
|
24
|
-
|
|
25
|
-
from orchid import (
|
|
26
|
-
base,
|
|
27
|
-
dot_net_dom_access as dna,
|
|
28
|
-
dot_net_disposable as dnd,
|
|
29
|
-
net_date_time as net_dt,
|
|
30
|
-
)
|
|
31
|
-
|
|
32
|
-
# noinspection PyUnresolvedReferences
|
|
33
|
-
from System import DateTime, DateTimeOffset, DBNull, Guid, TimeSpan
|
|
34
|
-
# noinspection PyUnresolvedReferences
|
|
35
|
-
from System.Data import DataTable
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
@dataclasses.dataclass
|
|
39
|
-
class CellDto:
|
|
40
|
-
row: int
|
|
41
|
-
column: str
|
|
42
|
-
value: object
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
@dataclasses.dataclass
|
|
46
|
-
class DateTimeOffsetSentinelRange:
|
|
47
|
-
lower: DateTimeOffset
|
|
48
|
-
upper: DateTimeOffset
|
|
49
|
-
|
|
50
|
-
def __contains__(self, to_test: DateTimeOffset):
|
|
51
|
-
return self.lower <= to_test <= self.upper
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
_MAX_SENTINEL_RANGE = DateTimeOffsetSentinelRange(DateTimeOffset.MaxValue.Subtract(TimeSpan(9999999)),
|
|
55
|
-
DateTimeOffset.MaxValue)
|
|
56
|
-
"""The range used to determine equality to the .NET `DateTimeOffset.MaxValue` sentinel."""
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
class DataFrameAdapterDateTimeError(TypeError):
|
|
60
|
-
pass
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
class DataFrameAdapterDateTimeOffsetMinValueError(ValueError):
|
|
64
|
-
def __init__(self, row_no, column_name):
|
|
65
|
-
super(DataFrameAdapterDateTimeOffsetMinValueError, self).__init__(
|
|
66
|
-
f'Unexpectedly found `DateTimeOffset.MinValue` at'
|
|
67
|
-
f' row, {row_no}, and column, "{column_name}", of Orchid `DataFrame`.')
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
def transform_display_name(net_display_name):
|
|
71
|
-
maybe_display_name = option.maybe(net_display_name)
|
|
72
|
-
return maybe_display_name.expect('Unexpected value, `None`, for `display_name`.')
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
class NativeDataFrameAdapterIdentified(dna.IdentifiedDotNetAdapter):
|
|
76
|
-
def __init__(self, net_data_frame):
|
|
77
|
-
super().__init__(net_data_frame, base.constantly(net_data_frame.Project))
|
|
78
|
-
|
|
79
|
-
name = dna.dom_property('name', 'The name of this data frame.')
|
|
80
|
-
display_name = dna.transformed_dom_property('display_name', 'The display name of this data frame.',
|
|
81
|
-
transform_display_name)
|
|
82
|
-
|
|
83
|
-
@property
|
|
84
|
-
def is_potentially_corrupt(self):
|
|
85
|
-
return self.name.endswith(' (Potentially Corrupted)')
|
|
86
|
-
|
|
87
|
-
def pandas_data_frame(self) -> pd.DataFrame:
|
|
88
|
-
"""
|
|
89
|
-
Return the `pandas` `DataFrame` built from the native `IStaticDataFrame`.
|
|
90
|
-
|
|
91
|
-
Returns:
|
|
92
|
-
A `pandas` `DataFrame`.
|
|
93
|
-
"""
|
|
94
|
-
return _table_to_data_frame(self.dom_object.DataTable)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
@functools.singledispatch
|
|
98
|
-
def net_cell_value_to_pandas_cell_value(cell_value):
|
|
99
|
-
"""
|
|
100
|
-
Convert a .NET `DataFrame` cell value to a `pandas.DataFrame` cell value.
|
|
101
|
-
Args:
|
|
102
|
-
cell_value: The cell value to convert.
|
|
103
|
-
"""
|
|
104
|
-
raise NotImplementedError(f'Unexpected type, {type(cell_value)}, of value, {cell_value}')
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
@net_cell_value_to_pandas_cell_value.register(int)
|
|
108
|
-
@net_cell_value_to_pandas_cell_value.register(float)
|
|
109
|
-
@net_cell_value_to_pandas_cell_value.register(str)
|
|
110
|
-
def _(cell_value):
|
|
111
|
-
return cell_value
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
@net_cell_value_to_pandas_cell_value.register(DateTime)
|
|
115
|
-
def _(_cell_value):
|
|
116
|
-
raise TypeError('`System.DateTime` unexpected.')
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
@net_cell_value_to_pandas_cell_value.register(DateTimeOffset)
|
|
120
|
-
def _(cell_value):
|
|
121
|
-
def is_net_max_sentinel(cv):
|
|
122
|
-
# TODO: Loss of fractional second work-around
|
|
123
|
-
# Using equality "works-around" the acceptance test error for the Permian FDI Observations data frame. (The
|
|
124
|
-
# "Timestamp" field is not **actually** `DateTimeOffset.MaxValue` but `DateTimeOffset.MaxValue` minus 1 second.)
|
|
125
|
-
return cv in _MAX_SENTINEL_RANGE
|
|
126
|
-
|
|
127
|
-
if is_net_max_sentinel(cell_value):
|
|
128
|
-
return pd.NaT
|
|
129
|
-
|
|
130
|
-
if cell_value == DateTimeOffset.MinValue:
|
|
131
|
-
raise ValueError('`DateTimeOffset.MinValue` unexpected.')
|
|
132
|
-
|
|
133
|
-
return net_dt.as_date_time(cell_value)
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
@net_cell_value_to_pandas_cell_value.register(DBNull)
|
|
137
|
-
def _(_cell_value):
|
|
138
|
-
return None
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
@net_cell_value_to_pandas_cell_value.register(Guid)
|
|
142
|
-
def _(_cell_value):
|
|
143
|
-
return uuid.UUID(_cell_value.ToString())
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
@net_cell_value_to_pandas_cell_value.register(TimeSpan)
|
|
147
|
-
def _(cell_value):
|
|
148
|
-
if cell_value == TimeSpan.MaxValue or cell_value == TimeSpan.MinValue:
|
|
149
|
-
return pd.NaT
|
|
150
|
-
|
|
151
|
-
# TODO: TimeSpan 3 Mdays calculation work-around
|
|
152
|
-
# The Orchid code to create the `ObservationSetDataFrame` calculates a `TimeSpan` from the "Pick Time"
|
|
153
|
-
# and the stage part start time; however, one item in the .NET `DataFrame` has the corresponding
|
|
154
|
-
# "Pick Time" of `DateTimeOffset.MaxValue`. Unfortunately, the calculation simply subtracts which results
|
|
155
|
-
# in a very large (<~ 3 million days) but valid value. The work-around I chose to implement is to
|
|
156
|
-
# transform these kinds of values into `pd.NaT`.
|
|
157
|
-
if cell_value.TotalDays > 36525: # ~ 100 years
|
|
158
|
-
return pd.NaT
|
|
159
|
-
|
|
160
|
-
return net_dt.as_duration(cell_value)
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def _table_to_data_frame(data_table: DataTable):
|
|
164
|
-
"""
|
|
165
|
-
Converts a .NET `DataTable` to a `pandas` `DataFrame`.
|
|
166
|
-
|
|
167
|
-
Args:
|
|
168
|
-
data_table: The .NET `DataTable` to convert.
|
|
169
|
-
|
|
170
|
-
Returns:
|
|
171
|
-
The `pandas` `DataFrame` converted from the .NET `DataTable`.
|
|
172
|
-
"""
|
|
173
|
-
result = toolz.pipe(data_table,
|
|
174
|
-
_read_data_table,
|
|
175
|
-
toolz.map(toolz.keymap(lambda e: e[1])),
|
|
176
|
-
list,
|
|
177
|
-
lambda rs: pd.DataFrame(data=rs),
|
|
178
|
-
)
|
|
179
|
-
return result
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
def _read_data_table(data_table: DataTable) -> Iterable[dict]:
|
|
183
|
-
"""
|
|
184
|
-
Read each row of the .NET `DataTable` into an `Iterable` of `dicts`.
|
|
185
|
-
|
|
186
|
-
Args:
|
|
187
|
-
data_table: The .NET `DataTable` to read.
|
|
188
|
-
|
|
189
|
-
Returns:
|
|
190
|
-
Yields a
|
|
191
|
-
"""
|
|
192
|
-
# Adapted from code at
|
|
193
|
-
# https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/dataset-datatable-dataview/creating-a-datareader
|
|
194
|
-
# retrieved on 18-Apr-2021.
|
|
195
|
-
with dnd.disposable(data_table.CreateDataReader()) as reader:
|
|
196
|
-
while True:
|
|
197
|
-
if reader.HasRows:
|
|
198
|
-
has_row = reader.Read()
|
|
199
|
-
while has_row:
|
|
200
|
-
yield _table_row_to_dict(reader)
|
|
201
|
-
has_row = reader.Read()
|
|
202
|
-
else:
|
|
203
|
-
return
|
|
204
|
-
if not reader.NextResult():
|
|
205
|
-
break
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
def _table_row_to_dict(reader):
|
|
209
|
-
@toolz.curry
|
|
210
|
-
def get_value(dt_reader, cell_location):
|
|
211
|
-
_, column_name = cell_location
|
|
212
|
-
return cell_location, dt_reader[column_name]
|
|
213
|
-
|
|
214
|
-
def add_to_dict(so_far, to_accumulate):
|
|
215
|
-
column_name, cell_value = to_accumulate
|
|
216
|
-
return toolz.assoc(so_far, column_name, cell_value)
|
|
217
|
-
|
|
218
|
-
def to_dict(pairs):
|
|
219
|
-
dict_result = toolz.reduce(add_to_dict, pairs, {})
|
|
220
|
-
return dict_result
|
|
221
|
-
|
|
222
|
-
def net_value_to_python_value(cell_location_value_pair):
|
|
223
|
-
(column_no, column_name), value = cell_location_value_pair
|
|
224
|
-
try:
|
|
225
|
-
converted = dataclasses.replace(CellDto(column_no, column_name, value),
|
|
226
|
-
value=net_cell_value_to_pandas_cell_value(value))
|
|
227
|
-
return (converted.row, converted.column), converted.value
|
|
228
|
-
except ValueError as ve:
|
|
229
|
-
if 'DateTimeOffset.MinValue' in str(ve):
|
|
230
|
-
raise DataFrameAdapterDateTimeOffsetMinValueError(column_no, column_name)
|
|
231
|
-
else:
|
|
232
|
-
raise Exception(f"Cannot read value from dot net data table column {column_no} named {column_name}, value {value}, {traceback.format_exc()}")
|
|
233
|
-
except TypeError as te:
|
|
234
|
-
if 'System.DateTime' in str(te):
|
|
235
|
-
raise DataFrameAdapterDateTimeError(value.GetType())
|
|
236
|
-
else:
|
|
237
|
-
raise Exception(f"Cannot read value from dot net data table column {column_no} named {column_name}, value {value}, {traceback.format_exc()}")
|
|
238
|
-
|
|
239
|
-
result = toolz.pipe(
|
|
240
|
-
reader.FieldCount,
|
|
241
|
-
range,
|
|
242
|
-
toolz.map(lambda column_no: (column_no, reader.GetName(column_no))),
|
|
243
|
-
toolz.map(get_value(reader)),
|
|
244
|
-
to_dict,
|
|
245
|
-
toolz.itemmap(net_value_to_python_value),
|
|
246
|
-
)
|
|
247
|
-
return result
|
orchid/native_fiber_data.py
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
|
2
|
-
from Orchid.FractureDiagnostics.FiberDataSet import IFiberDataSet
|
|
3
|
-
import orchid.base
|
|
4
|
-
from orchid import (
|
|
5
|
-
dom_project_object as dpo,
|
|
6
|
-
native_fiber_data_set_info as info
|
|
7
|
-
)
|
|
8
|
-
from .utils import convert_dotnet_datetime_to_python_datetime
|
|
9
|
-
from typing import List, Optional
|
|
10
|
-
from datetime import datetime
|
|
11
|
-
import pandas as pd
|
|
12
|
-
|
|
13
|
-
INT32_MAX = 2147483647
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class NativeFiberData(dpo.DomProjectObject):
|
|
17
|
-
"""Adapts a native IFiberDataSet to python."""
|
|
18
|
-
|
|
19
|
-
def __init__(self, net_fiber_data_set: IFiberDataSet):
|
|
20
|
-
"""
|
|
21
|
-
Constructs an instance adapting a .NET IFiberDataSet.
|
|
22
|
-
Args:
|
|
23
|
-
net_fiber_data_set: The .NET fiber data set to be adapted.
|
|
24
|
-
"""
|
|
25
|
-
super().__init__(net_fiber_data_set, orchid.base.constantly(net_fiber_data_set.Project))
|
|
26
|
-
|
|
27
|
-
@property
|
|
28
|
-
def file_path(self) -> str:
|
|
29
|
-
return self.dom_object.FilePath
|
|
30
|
-
|
|
31
|
-
@property
|
|
32
|
-
def depth_unit(self) -> str:
|
|
33
|
-
return self.dom_object.DepthUnit
|
|
34
|
-
|
|
35
|
-
@property
|
|
36
|
-
def timezone_info(self) -> str:
|
|
37
|
-
return self.dom_object.TimeZoneInfo
|
|
38
|
-
|
|
39
|
-
@property
|
|
40
|
-
def times_data_set(self) -> str:
|
|
41
|
-
return self.dom_object.TimesDataSet
|
|
42
|
-
|
|
43
|
-
@property
|
|
44
|
-
def data_sets_info(self) -> List[info.NativeFiberDataSetInfo]:
|
|
45
|
-
return [info.NativeFiberDataSetInfo(x) for x in self.dom_object.FiberDataSets]
|
|
46
|
-
|
|
47
|
-
def get_data_set(self, data_set_name: Optional[str] = None):
|
|
48
|
-
try:
|
|
49
|
-
data_set_info = next(x for x in self.dom_object.FiberDataSets if x.name == data_set_name) if data_set_name is not None else self.dom_object.FiberDataSets[0]
|
|
50
|
-
except StopIteration:
|
|
51
|
-
raise ValueError("No Data Set with this name in this fiber data object")
|
|
52
|
-
data = self.dom_object.GetDataSet(data_set_info)
|
|
53
|
-
data_list = [[data[i, j] for j in range(data.GetLength(1))] for i in range(data.GetLength(0))]
|
|
54
|
-
return pd.DataFrame(data_list)
|
|
55
|
-
|
|
56
|
-
def get_data_table(self, start_index: int = 0, end_index: int = INT32_MAX):
|
|
57
|
-
if end_index == INT32_MAX:
|
|
58
|
-
print("We strongly recommend that you avoid loading the entire data table and instead work with chunks, "
|
|
59
|
-
"specifying the start and end indexes. You can also use the get_data_set method, which is faster.")
|
|
60
|
-
print("Retrieving the data table... This may take a few minutes")
|
|
61
|
-
data_table = self.dom_object.GetDataTable(self.dom_object.DepthUnit, start_index, end_index)
|
|
62
|
-
data_dict = {column: [row[column] for row in data_table.Rows] for column in data_table.Columns}
|
|
63
|
-
df = pd.DataFrame(data_dict)
|
|
64
|
-
print("Data table Retrieved")
|
|
65
|
-
return df
|
|
66
|
-
|
|
67
|
-
@property
|
|
68
|
-
def dates(self) -> List[datetime]:
|
|
69
|
-
return [convert_dotnet_datetime_to_python_datetime(x.ToString()) for x in self.dom_object.Times]
|
|
70
|
-
|
|
71
|
-
@property
|
|
72
|
-
def depths(self) -> List[float]:
|
|
73
|
-
return [x.Value for x in self.dom_object.Depths]
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
# noinspection PyUnresolvedReferences,PyPackageRequirements
|
|
2
|
-
from Orchid.FractureDiagnostics.FiberDataSet import IFiberDataSetInfo
|
|
3
|
-
import orchid.base
|
|
4
|
-
from orchid import (
|
|
5
|
-
dot_net_dom_access as dna,
|
|
6
|
-
dom_project_object as dpo,
|
|
7
|
-
dot_net_disposable as dnd,
|
|
8
|
-
net_date_time as ndt,
|
|
9
|
-
)
|
|
10
|
-
import json
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class NativeFiberDataSetInfo(dpo.DomProjectObject):
|
|
14
|
-
"""Adapts a native IFiberDataSet to python."""
|
|
15
|
-
|
|
16
|
-
def __init__(self, net_fiber_data_set_info: IFiberDataSetInfo):
|
|
17
|
-
"""
|
|
18
|
-
Constructs an instance adapting a .NET IFiberDataSet.
|
|
19
|
-
Args:
|
|
20
|
-
net_fiber_data_set_info: The .NET fiber data set to be adapted.
|
|
21
|
-
"""
|
|
22
|
-
super().__init__(net_fiber_data_set_info)
|
|
23
|
-
|
|
24
|
-
description = dna.dom_property('description', 'Description')
|
|
25
|
-
type = dna.dom_property('type', 'Type')
|
|
26
|
-
unit = dna.dom_property('unit', 'Unit of this data set')
|
|
27
|
-
min = dna.dom_property('min', 'Minimum value of this data set')
|
|
28
|
-
max = dna.dom_property('max', 'Maximum value of this data set')
|
orchid/native_monitor_adapter.py
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# This file is part of Orchid and related technologies.
|
|
3
|
-
#
|
|
4
|
-
# Copyright (c) 2017-2025 KAPPA. All Rights Reserved.
|
|
5
|
-
#
|
|
6
|
-
# LEGAL NOTICE:
|
|
7
|
-
# Orchid contains trade secrets and otherwise confidential information
|
|
8
|
-
# owned by KAPPA. Access to and use of this information is
|
|
9
|
-
# strictly limited and controlled by the Company. This file may not be copied,
|
|
10
|
-
# distributed, or otherwise disclosed outside of the Company's facilities
|
|
11
|
-
# except under appropriate precautions to maintain the confidentiality hereof,
|
|
12
|
-
# and may not be used in any way not expressly authorized by the Company.
|
|
13
|
-
#
|
|
14
|
-
|
|
15
|
-
import pendulum
|
|
16
|
-
|
|
17
|
-
import orchid.base
|
|
18
|
-
from orchid import (
|
|
19
|
-
dot_net_dom_access as dna,
|
|
20
|
-
dom_project_object as dpo,
|
|
21
|
-
native_time_series_adapter as tsa,
|
|
22
|
-
net_date_time as ndt,
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
# noinspection PyUnresolvedReferences
|
|
26
|
-
from Orchid.FractureDiagnostics.Monitors import ITimeSeriesMonitor
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
class NativeMonitorAdapter(dpo.DomProjectObject):
|
|
30
|
-
"""Adapts a native ITimeSeriesMonitor to python."""
|
|
31
|
-
def __init__(self, net_monitor: ITimeSeriesMonitor):
|
|
32
|
-
"""
|
|
33
|
-
Constructs an instance adapting a .NET ITimeSeriesMonitor.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
net_monitor: The .NET monitor to be adapted.
|
|
37
|
-
"""
|
|
38
|
-
super().__init__(net_monitor, orchid.base.constantly(net_monitor.Project))
|
|
39
|
-
|
|
40
|
-
start_time = dna.transformed_dom_property('start_time', 'The start time of this monitor.',
|
|
41
|
-
ndt.as_date_time)
|
|
42
|
-
stop_time = dna.transformed_dom_property('stop_time', 'The stop time of this monitor.',
|
|
43
|
-
ndt.as_date_time)
|
|
44
|
-
well_time_series = dna.transformed_dom_property(
|
|
45
|
-
'time_series',
|
|
46
|
-
"""The complete time series for the well that may be monitoring treatments.
|
|
47
|
-
|
|
48
|
-
The returned time series contains all samples recorded for the project. More specifically, it may
|
|
49
|
-
contain samples either before or after `time_range()`.
|
|
50
|
-
|
|
51
|
-
Another consequence of this definition is that if a client wants to access sample inside
|
|
52
|
-
`time_range()`, one must write code to manually filter the series samples to only include the samples
|
|
53
|
-
in `time_range()`.
|
|
54
|
-
""",
|
|
55
|
-
tsa.NativeTimeSeriesAdapter)
|
|
56
|
-
|
|
57
|
-
@property
|
|
58
|
-
def time_range(self):
|
|
59
|
-
"""
|
|
60
|
-
Calculate the time range during which this monitor is active; that is, monitoring the treatment stage.
|
|
61
|
-
|
|
62
|
-
Returns:
|
|
63
|
-
The time range during which this monitor is active. The type of the returned value is
|
|
64
|
-
`pendulum.Interval`. See the [documentation](https://pendulum.eustace.io/docs/) to understand the
|
|
65
|
-
methods available from a `pendulum.Interval` instance.
|
|
66
|
-
"""
|
|
67
|
-
return pendulum.Interval(self.start_time, self.stop_time)
|