Skip to content

Commit 921542d

Browse files
Merge branch 'SC-1127' into 'master'
SC-1127: Fix horizons mismatch in TVT-ROP Heatmap script See merge request SOLO-band/python-sdk!51
2 parents 7b1b1a7 + 174dbc8 commit 921542d

File tree

9 files changed

+196
-80
lines changed

9 files changed

+196
-80
lines changed

examples/interpretation_dip_calculation.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,13 +42,13 @@ def calc_interpretation_dip():
4242

4343
segments = get_segments(
4444
well=well_data,
45-
assembled_segments=interpretation.get_assembled_segments_data()['segments'],
45+
assembled_segments=interpretation.assembled_segments['segments'],
4646
calculated_trajectory=calculated_trajectory,
4747
measure_units=MEASURE_UNITS
4848
)
4949
segments_with_dip = get_segments_with_dip(
5050
segments=segments,
51-
assembled_horizons=interpretation.get_assembled_segments_data()['horizons']
51+
assembled_horizons=interpretation.assembled_segments['horizons']
5252
)
5353

5454
calculated_dips = DataFrame(segments_with_dip, columns=['md', 'dip'])

examples/tvt_rop_heatmap/tvt_rop_heatmap.py

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -10,30 +10,12 @@
1010

1111
import rogii_solo.well
1212
from rogii_solo import SoloClient
13+
from rogii_solo.calculations.base import get_nearest_values
1314
from rogii_solo.calculations.interpretation import interpolate_trajectory_point
1415
from rogii_solo.calculations.trajectory import calculate_trajectory
1516
from rogii_solo.interpretation import Interpretation
1617

1718

18-
def get_nearest_values(value: Any, input_list: List[Any]) -> Any:
19-
if not input_list:
20-
return
21-
22-
pos = bisect_left(input_list, value)
23-
24-
if pos == 0:
25-
values = [input_list[0]]
26-
elif pos == len(input_list):
27-
values = [input_list[-1]]
28-
else:
29-
values = [
30-
input_list[pos - 1],
31-
input_list[pos]
32-
]
33-
34-
return values
35-
36-
3719
def get_interpolated_trajectory(solo_client: SoloClient, well: 'rogii_solo.well.Well') -> List[Dict[str, float]]:
3820
well_data = well.to_dict()
3921
calculated_trajectory = calculate_trajectory(
@@ -75,14 +57,30 @@ def get_interpolated_trajectory(solo_client: SoloClient, well: 'rogii_solo.well.
7557

7658

7759
def get_horizons(interpretation: Interpretation, md_step: int) -> List[Dict[str, Any]]:
78-
horizons = interpretation.get_horizons_tvt_data(md_step=md_step)
60+
horizons = interpretation.get_tvt_data(md_step)
7961

8062
if not horizons:
8163
raise Exception('Horizons\' data not found.')
8264

8365
return horizons
8466

8567

68+
def get_horizon_tvts(interpretation: Interpretation) -> List[Dict[str, Any]]:
69+
horizon_tvts = []
70+
horizons_data = interpretation.assembled_segments['horizons'].values()
71+
72+
for horizon in horizons_data:
73+
horizon_tvts.append(
74+
{
75+
'name': horizon['name'],
76+
'uuid': horizon['uuid'],
77+
'tvt': horizon['tvd'],
78+
}
79+
)
80+
81+
return horizon_tvts
82+
83+
8684
def get_horizons_data_by_md(horizons: List[Dict[str, Any]], md: float) -> Dict[str, Any]:
8785
mds = [horizon_data['md'] for horizon_data in horizons]
8886
idx = bisect_left(mds, md)
@@ -172,7 +170,6 @@ def get_heatmap_data(trajectory: List[Dict[str, float]],
172170
def get_horizon_scatters(xedges2: Any,
173171
yedges2: Any,
174172
horizons: List[Dict[str, Any]],
175-
kb: float,
176173
zero_horizon_uuid: str
177174
) -> List[go.Scatter]:
178175
tvt_margin = 0.1
@@ -183,11 +180,11 @@ def get_horizon_scatters(xedges2: Any,
183180

184181
for horizon in horizons:
185182
if horizon['uuid'] == zero_horizon_uuid:
186-
zero_tvt = kb - horizon['tvdss']
183+
zero_tvt = horizon['tvt']
187184
break
188185

189186
for horizon in horizons:
190-
tvt = kb - horizon['tvdss'] - zero_tvt
187+
tvt = horizon['tvt'] - zero_tvt
191188

192189
if y_min - tvt_margin <= tvt <= y_max + tvt_margin:
193190
data.append(
@@ -275,12 +272,12 @@ def build_tvt_rop_heatmap(script_settings: Dict[str, Any]):
275272
bins=bins
276273
)
277274
data.append(go.Heatmap(x=xedges2, y=yedges2, z=histogram2d, showscale=False))
278-
well_data = well.to_dict()
275+
276+
horizon_tvts = get_horizon_tvts(interpretation)
279277
horizon_scatters = get_horizon_scatters(
280278
xedges2=xedges2,
281279
yedges2=yedges2,
282-
horizons=horizons[0]['horizons'],
283-
kb=well_data['kb'],
280+
horizons=horizon_tvts,
284281
zero_horizon_uuid=interpretation_data['meta']['properties']['zero_horizon_uuid']
285282
)
286283
data.extend(horizon_scatters)

src/rogii_solo/base.py

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -47,15 +47,14 @@ def to_df(self, get_converted: bool = True) -> DataFrame:
4747
"""
4848
pass
4949

50-
def _find_by_path(
51-
self,
52-
obj: Dict or Iterable[Dict],
53-
path: str or Iterable[str],
54-
default: Any = None,
55-
divider: str = None,
56-
check_none: bool = False,
57-
to_list: bool = False,
58-
) -> Any:
50+
def _find_by_path(self,
51+
obj: Dict or Iterable[Dict],
52+
path: str or Iterable[str],
53+
default: Any = None,
54+
divider: str = None,
55+
check_none: bool = False,
56+
to_list: bool = False,
57+
) -> Any:
5958
"""
6059
Find nested key value in dict
6160
:param obj:
@@ -94,15 +93,14 @@ def _find_by_path(
9493

9594
return result
9695

97-
def __find_by_path(
98-
self,
99-
obj: Dict,
100-
path: str,
101-
default: Any = None,
102-
divider: str = None,
103-
check_none: bool = False,
104-
to_list: bool = False,
105-
) -> Any:
96+
def __find_by_path(self,
97+
obj: Dict,
98+
path: str,
99+
default: Any = None,
100+
divider: str = None,
101+
check_none: bool = False,
102+
to_list: bool = False,
103+
) -> Any:
106104
if not obj:
107105
return None if not to_list else []
108106

src/rogii_solo/horizon.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ def _get_data(self, get_converted: bool):
4444
def _calculate_points(self, get_converted: bool):
4545
well_data = self.interpretation.well.to_dict(get_converted=False)
4646
trajectory_data = self.interpretation.well.trajectory.to_dict(get_converted=False)
47-
assembled_segments_data = self.interpretation.get_assembled_segments_data()
47+
assembled_segments_data = self.interpretation.assembled_segments
4848
measure_units = self.interpretation.well.project.measure_unit
4949

5050
calculated_trajectory = calculate_trajectory(

src/rogii_solo/interpretation.py

Lines changed: 35 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,16 @@
44

55
import rogii_solo.well
66
from rogii_solo.base import ComplexObject, ObjectRepository
7+
from rogii_solo.calculations.converters import meters_to_feet
8+
from rogii_solo.calculations.enums import EMeasureUnits
79
from rogii_solo.horizon import Horizon
810
from rogii_solo.papi.client import PapiClient
911
from rogii_solo.papi.types import PapiAssembledSegments
1012
from rogii_solo.types import DataList
1113
from rogii_solo.types import Interpretation as InterpretationType
1214

15+
TVT_DATA_MAX_MD_STEP = 100000
16+
1317

1418
class Interpretation(ComplexObject):
1519
def __init__(self, papi_client: PapiClient, well: 'rogii_solo.well.Well', **kwargs):
@@ -27,8 +31,6 @@ def __init__(self, papi_client: PapiClient, well: 'rogii_solo.well.Well', **kwar
2731

2832
self._assembled_segments_data: Optional[PapiAssembledSegments] = None
2933

30-
self._horizons_tvt_data: Optional[DataList] = None
31-
3234
self._horizons_data: Optional[DataList] = None
3335
self._horizons: Optional[ObjectRepository[Horizon]] = None
3436

@@ -44,22 +46,38 @@ def to_df(self, get_converted: bool = True) -> InterpretationType:
4446
'segments': DataFrame(data['segments']),
4547
}
4648

47-
def get_assembled_segments_data(self) -> PapiAssembledSegments:
48-
if self._assembled_segments_data is None:
49-
self._assembled_segments_data = self._papi_client.get_interpretation_assembled_segments_data(
50-
interpretation_id=self.uuid
51-
)
49+
@property
50+
def assembled_segments(self):
51+
if self._assembled_segments_data is not None:
52+
return {
53+
'horizons': self._assembled_segments_data['horizons'],
54+
'segments': self._assembled_segments_data['segments']
55+
}
5256

53-
return self._assembled_segments_data
57+
self._assembled_segments_data = self._papi_client.get_interpretation_assembled_segments_data(
58+
interpretation_id=self.uuid
59+
)
5460

55-
def get_horizons_tvt_data(self, md_step: int = 10) -> DataList:
56-
if self._horizons_tvt_data is None:
57-
self._horizons_tvt_data = self._papi_client.get_horizons_tvt_data(
58-
interpretation_id=self.uuid,
59-
md_step=md_step
60-
)
61+
assembled_horizons_data = self._assembled_segments_data['horizons']
62+
measure_units = self.well.project.measure_unit
6163

62-
return self._horizons_tvt_data
64+
for horizon in self._get_horizons_data():
65+
assembled_horizons_data[horizon['uuid']]['name'] = horizon['name']
66+
if measure_units != EMeasureUnits.METER:
67+
assembled_horizons_data[horizon['uuid']]['tvd'] = meters_to_feet(
68+
assembled_horizons_data[horizon['uuid']]['tvd']
69+
)
70+
71+
return {
72+
'horizons': self._assembled_segments_data['horizons'],
73+
'segments': self._assembled_segments_data['segments']
74+
}
75+
76+
def get_tvt_data(self, md_step: int = 1) -> DataList:
77+
return self._papi_client.get_interpretation_tvt_data(
78+
interpretation_id=self.uuid,
79+
md_step=md_step
80+
)
6381

6482
@property
6583
def horizons(self) -> ObjectRepository[Horizon]:
@@ -77,11 +95,6 @@ def _get_horizons_data(self) -> DataList:
7795
return self._horizons_data
7896

7997
def _get_data(self):
80-
assembled_segments = self.get_assembled_segments_data()
81-
82-
for horizon in self._get_horizons_data():
83-
assembled_segments['horizons'][horizon['uuid']]['name'] = horizon['name']
84-
8598
meta = {
8699
'uuid': self.uuid,
87100
'name': self.name,
@@ -92,6 +105,6 @@ def _get_data(self):
92105

93106
return {
94107
'meta': meta,
95-
'horizons': assembled_segments['horizons'],
96-
'segments': assembled_segments['segments'],
108+
'horizons': self.assembled_segments['horizons'],
109+
'segments': self.assembled_segments['segments'],
97110
}

src/rogii_solo/papi/base.py

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -321,11 +321,11 @@ def fetch_interpretation_horizons(self,
321321
headers=headers
322322
)
323323

324-
def fetch_horizons_tvt_data(self,
325-
interpretation_id: str,
326-
md_step: int,
327-
headers: Optional[Dict[str, Any]] = None
328-
):
324+
def fetch_interpretation_horizons_data(self,
325+
interpretation_id: str,
326+
md_step: int,
327+
headers: Optional[Dict[str, Any]] = None
328+
):
329329
"""
330330
Fetches calculated by step horizons data
331331
:param interpretation_id:

src/rogii_solo/papi/client.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ def get_interpretation_horizons_data(self, interpretation_id: str, **kwargs) ->
9898
**kwargs
9999
))
100100

101-
def get_horizons_tvt_data(self, interpretation_id: str, **kwargs) -> PapiDataList:
101+
def get_interpretation_tvt_data(self, interpretation_id: str, **kwargs) -> PapiDataList:
102102
return [
103-
self.parse_papi_data(tvt_data) for tvt_data in self.fetch_horizons_tvt_data(
103+
self.parse_papi_data(tvt_data) for tvt_data in self.fetch_interpretation_horizons_data(
104104
interpretation_id=interpretation_id,
105105
**kwargs
106106
)

tests/conftest.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
TARGET_LINES_DATA_RESPONSE,
1717
NESTED_WELLS_DATA_RESPONSE,
1818
LOGS_DATA_RESPONSE,
19-
LOG_POINTS_DATA_RESPONSE
19+
LOG_POINTS_DATA_RESPONSE,
20+
HORIZONS_TVT_DATA_RESPONSE
2021
)
2122

2223

@@ -48,6 +49,10 @@ def fetch_interpretation_assembled_segments(**kwargs):
4849
return ASSEMBLED_SEGMENTS_DATA_RESPONSE['assembled_segments']
4950

5051

52+
def fetch_interpretation_horizons_data(**kwargs):
53+
return HORIZONS_TVT_DATA_RESPONSE['content']
54+
55+
5156
def fetch_well_target_lines(**kwargs):
5257
return TARGET_LINES_DATA_RESPONSE
5358

@@ -84,6 +89,7 @@ def solo_client():
8489
solo_client._papi_client.fetch_nested_well_raw_trajectory = fetch_nested_well_raw_trajectory
8590
solo_client._papi_client.fetch_well_logs = fetch_well_logs
8691
solo_client._papi_client.fetch_log_points = fetch_log_points
92+
solo_client._papi_client.fetch_interpretation_horizons_data = fetch_interpretation_horizons_data
8793

8894
return solo_client
8995

0 commit comments

Comments
 (0)