well-log-toolkit 0.1.138__py3-none-any.whl → 0.1.139__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.
- well_log_toolkit/visualization.py +38 -52
- {well_log_toolkit-0.1.138.dist-info → well_log_toolkit-0.1.139.dist-info}/METADATA +14 -10
- {well_log_toolkit-0.1.138.dist-info → well_log_toolkit-0.1.139.dist-info}/RECORD +5 -5
- {well_log_toolkit-0.1.138.dist-info → well_log_toolkit-0.1.139.dist-info}/WHEEL +0 -0
- {well_log_toolkit-0.1.138.dist-info → well_log_toolkit-0.1.139.dist-info}/top_level.txt +0 -0
|
@@ -1120,17 +1120,18 @@ class WellView:
|
|
|
1120
1120
|
)
|
|
1121
1121
|
|
|
1122
1122
|
# Collect all tops data from all tops groups
|
|
1123
|
-
|
|
1123
|
+
all_tops_list = []
|
|
1124
1124
|
for tops_group in self.tops:
|
|
1125
|
-
|
|
1126
|
-
|
|
1125
|
+
entries = tops_group.get('entries', [])
|
|
1126
|
+
for entry in entries:
|
|
1127
|
+
all_tops_list.append((entry['depth'], entry['name']))
|
|
1127
1128
|
|
|
1128
1129
|
# Find depths for specified tops
|
|
1129
1130
|
tops_depths = []
|
|
1130
1131
|
not_found = []
|
|
1131
1132
|
for top_name in tops_list:
|
|
1132
1133
|
found = False
|
|
1133
|
-
for depth, name in
|
|
1134
|
+
for depth, name in all_tops_list:
|
|
1134
1135
|
if name == top_name:
|
|
1135
1136
|
tops_depths.append(depth)
|
|
1136
1137
|
found = True
|
|
@@ -1140,7 +1141,7 @@ class WellView:
|
|
|
1140
1141
|
|
|
1141
1142
|
# Only raise error if NONE of the tops were found
|
|
1142
1143
|
if not tops_depths:
|
|
1143
|
-
available_tops = list(set(
|
|
1144
|
+
available_tops = list(set(name for _, name in all_tops_list))
|
|
1144
1145
|
raise ValueError(
|
|
1145
1146
|
f"None of the specified formation tops were found: {tops_list}. "
|
|
1146
1147
|
f"Available tops: {available_tops}"
|
|
@@ -1338,11 +1339,8 @@ class WellView:
|
|
|
1338
1339
|
if property_name is not None and tops_dict is not None:
|
|
1339
1340
|
raise ValueError("Cannot specify both 'property_name' and 'tops_dict'")
|
|
1340
1341
|
|
|
1341
|
-
# Get tops data
|
|
1342
|
-
|
|
1343
|
-
color_data = {} # depth -> color
|
|
1344
|
-
style_data = {} # depth -> line style
|
|
1345
|
-
thickness_data = {} # depth -> line thickness
|
|
1342
|
+
# Get tops data as list of entries (supports multiple tops at same depth)
|
|
1343
|
+
tops_entries = [] # List of {'depth': d, 'name': n, 'color': c, 'style': s, 'thickness': t}
|
|
1346
1344
|
|
|
1347
1345
|
if property_name is not None:
|
|
1348
1346
|
# Load from discrete property
|
|
@@ -1375,7 +1373,7 @@ class WellView:
|
|
|
1375
1373
|
if valid_values[i] != valid_values[i-1]:
|
|
1376
1374
|
boundaries.append(i)
|
|
1377
1375
|
|
|
1378
|
-
# Build tops
|
|
1376
|
+
# Build tops entries list
|
|
1379
1377
|
for idx in boundaries:
|
|
1380
1378
|
depth = float(valid_depth[idx])
|
|
1381
1379
|
value = int(valid_values[idx])
|
|
@@ -1386,42 +1384,43 @@ class WellView:
|
|
|
1386
1384
|
else:
|
|
1387
1385
|
formation_name = f"Zone {value}"
|
|
1388
1386
|
|
|
1389
|
-
|
|
1387
|
+
entry = {'depth': depth, 'name': formation_name}
|
|
1390
1388
|
|
|
1391
1389
|
# Get color if available (colors parameter overrides property colors)
|
|
1392
1390
|
if colors is not None and value in colors:
|
|
1393
|
-
|
|
1391
|
+
entry['color'] = colors[value]
|
|
1394
1392
|
elif prop.colors and value in prop.colors:
|
|
1395
|
-
|
|
1393
|
+
entry['color'] = prop.colors[value]
|
|
1396
1394
|
|
|
1397
1395
|
# Get style if available (styles parameter overrides property styles)
|
|
1398
1396
|
if styles is not None and value in styles:
|
|
1399
|
-
|
|
1397
|
+
entry['style'] = styles[value]
|
|
1400
1398
|
elif prop.styles and value in prop.styles:
|
|
1401
|
-
|
|
1399
|
+
entry['style'] = prop.styles[value]
|
|
1402
1400
|
|
|
1403
1401
|
# Get thickness if available (thicknesses parameter overrides property thicknesses)
|
|
1404
1402
|
if thicknesses is not None and value in thicknesses:
|
|
1405
|
-
|
|
1403
|
+
entry['thickness'] = thicknesses[value]
|
|
1406
1404
|
elif prop.thicknesses and value in prop.thicknesses:
|
|
1407
|
-
|
|
1405
|
+
entry['thickness'] = prop.thicknesses[value]
|
|
1406
|
+
|
|
1407
|
+
tops_entries.append(entry)
|
|
1408
1408
|
|
|
1409
1409
|
else:
|
|
1410
|
-
# Use provided dictionary
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1417
|
-
|
|
1410
|
+
# Use provided dictionary - convert to list format
|
|
1411
|
+
for depth, name in tops_dict.items():
|
|
1412
|
+
entry = {'depth': depth, 'name': name}
|
|
1413
|
+
if colors is not None and depth in colors:
|
|
1414
|
+
entry['color'] = colors[depth]
|
|
1415
|
+
if styles is not None and depth in styles:
|
|
1416
|
+
entry['style'] = styles[depth]
|
|
1417
|
+
if thicknesses is not None and depth in thicknesses:
|
|
1418
|
+
entry['thickness'] = thicknesses[depth]
|
|
1419
|
+
tops_entries.append(entry)
|
|
1418
1420
|
|
|
1419
1421
|
# Store tops for rendering
|
|
1420
1422
|
self.tops.append({
|
|
1421
|
-
'
|
|
1422
|
-
'colors': color_data if color_data else None,
|
|
1423
|
-
'styles': style_data if style_data else None,
|
|
1424
|
-
'thicknesses': thickness_data if thickness_data else None
|
|
1423
|
+
'entries': tops_entries
|
|
1425
1424
|
})
|
|
1426
1425
|
|
|
1427
1426
|
def _get_depth_mask(self, depth: np.ndarray) -> np.ndarray:
|
|
@@ -1451,34 +1450,21 @@ class WellView:
|
|
|
1451
1450
|
|
|
1452
1451
|
# For each tops group
|
|
1453
1452
|
for tops_group in self.tops:
|
|
1454
|
-
|
|
1455
|
-
colors_data = tops_group['colors']
|
|
1456
|
-
styles_data = tops_group['styles']
|
|
1457
|
-
thicknesses_data = tops_group['thicknesses']
|
|
1453
|
+
entries = tops_group.get('entries', [])
|
|
1458
1454
|
|
|
1459
1455
|
# Draw each top
|
|
1460
|
-
for
|
|
1456
|
+
for entry in entries:
|
|
1457
|
+
depth = entry['depth']
|
|
1458
|
+
formation_name = entry['name']
|
|
1459
|
+
|
|
1461
1460
|
# Skip tops outside depth range
|
|
1462
1461
|
if depth < self.depth_range[0] or depth > self.depth_range[1]:
|
|
1463
1462
|
continue
|
|
1464
1463
|
|
|
1465
|
-
# Get color
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
color = 'black' # Default color
|
|
1470
|
-
|
|
1471
|
-
# Get line style for this top
|
|
1472
|
-
if styles_data and depth in styles_data:
|
|
1473
|
-
linestyle = styles_data[depth]
|
|
1474
|
-
else:
|
|
1475
|
-
linestyle = 'solid' # Default style
|
|
1476
|
-
|
|
1477
|
-
# Get line thickness for this top
|
|
1478
|
-
if thicknesses_data and depth in thicknesses_data:
|
|
1479
|
-
linewidth = thicknesses_data[depth]
|
|
1480
|
-
else:
|
|
1481
|
-
linewidth = 1.5 # Default thickness
|
|
1464
|
+
# Get color, style, thickness from entry (with defaults)
|
|
1465
|
+
color = entry.get('color', 'black')
|
|
1466
|
+
linestyle = entry.get('style', 'solid')
|
|
1467
|
+
linewidth = entry.get('thickness', 1.5)
|
|
1482
1468
|
|
|
1483
1469
|
# Draw line across all non-depth tracks
|
|
1484
1470
|
for ax in non_depth_axes:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: well-log-toolkit
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.139
|
|
4
4
|
Summary: Fast LAS file processing with lazy loading and filtering for well log analysis
|
|
5
5
|
Author-email: Kristian dF Kollsgård <kkollsg@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -463,7 +463,10 @@ template.add_track(track_type="continuous", logs=[...], title="Resistivity")
|
|
|
463
463
|
template.add_track(track_type="discrete", logs=[...], title="Facies")
|
|
464
464
|
template.add_track(track_type="depth", width=0.3, title="Depth")
|
|
465
465
|
|
|
466
|
-
#
|
|
466
|
+
# Add to project (saves with manager.save())
|
|
467
|
+
manager.add_template(template) # Uses template name "reservoir"
|
|
468
|
+
|
|
469
|
+
# Or save standalone file
|
|
467
470
|
template.save("reservoir_template.json")
|
|
468
471
|
```
|
|
469
472
|
|
|
@@ -811,8 +814,8 @@ view.show()
|
|
|
811
814
|
|
|
812
815
|
**Option 2: Store in manager (recommended for multi-well projects)**
|
|
813
816
|
```python
|
|
814
|
-
# Store template in manager
|
|
815
|
-
manager.
|
|
817
|
+
# Store template in manager (uses template.name automatically)
|
|
818
|
+
manager.add_template(template)
|
|
816
819
|
|
|
817
820
|
# Use by name in any well
|
|
818
821
|
view = well.WellView(depth_range=[2800, 3000], template="reservoir")
|
|
@@ -859,8 +862,8 @@ template.remove_track(2)
|
|
|
859
862
|
template.add_track(track_type="continuous", logs=[{"name": "RT"}])
|
|
860
863
|
|
|
861
864
|
# Save changes
|
|
862
|
-
manager.
|
|
863
|
-
template.save("updated_template.json")
|
|
865
|
+
manager.add_template(template) # Update in manager (uses template.name)
|
|
866
|
+
template.save("updated_template.json") # Save to file
|
|
864
867
|
```
|
|
865
868
|
|
|
866
869
|
### Customization
|
|
@@ -1006,8 +1009,8 @@ template.add_track(track_type="depth", width=0.3, title="MD (m)")
|
|
|
1006
1009
|
# Add formation tops spanning all tracks
|
|
1007
1010
|
template.add_tops(property_name='Zone')
|
|
1008
1011
|
|
|
1009
|
-
#
|
|
1010
|
-
manager.
|
|
1012
|
+
# Add to project and display
|
|
1013
|
+
manager.add_template(template)
|
|
1011
1014
|
view = well.WellView(depth_range=[2800, 3200], template="comprehensive")
|
|
1012
1015
|
view.save("comprehensive_log.png", dpi=300)
|
|
1013
1016
|
```
|
|
@@ -1886,7 +1889,8 @@ from well_log_toolkit import WellDataManager, Well, Property, LasFile
|
|
|
1886
1889
|
- `remove_well(name)` - Remove well
|
|
1887
1890
|
- `save(directory)` - Save project
|
|
1888
1891
|
- `load(directory)` - Load project
|
|
1889
|
-
- `
|
|
1892
|
+
- `add_template(template)` - Store template (uses template.name)
|
|
1893
|
+
- `set_template(name, template)` - Store template with custom name
|
|
1890
1894
|
- `get_template(name)` - Retrieve template
|
|
1891
1895
|
- `list_templates()` - List template names
|
|
1892
1896
|
- `Crossplot(x, y, wells=None, shape="well", ...)` - Create multi-well crossplot
|
|
@@ -2053,7 +2057,7 @@ template.add_track(
|
|
|
2053
2057
|
logs=[{"name": "GR", "x_range": [0, 150], "color": "green"}],
|
|
2054
2058
|
title="Gamma Ray"
|
|
2055
2059
|
)
|
|
2056
|
-
manager.
|
|
2060
|
+
manager.add_template(template) # Stored as "custom"
|
|
2057
2061
|
view = well.WellView(template="custom")
|
|
2058
2062
|
view.save("log.png", dpi=300)
|
|
2059
2063
|
```
|
|
@@ -7,9 +7,9 @@ well_log_toolkit/property.py,sha256=ol_E4r31ButSnQEzAZjI00ofaRePPcJstRLOFFcgtp4,
|
|
|
7
7
|
well_log_toolkit/regression.py,sha256=JDcRxaODJnFikAdPJyTq8eUV7iY0vCDmvnGufqlojxs,31625
|
|
8
8
|
well_log_toolkit/statistics.py,sha256=_huPMbv2H3o9ezunjEM94mJknX5wPK8V4nDv2lIZZRw,16814
|
|
9
9
|
well_log_toolkit/utils.py,sha256=O2KPq4htIoUlL74V2zKftdqqTjRfezU9M-568zPLme0,6866
|
|
10
|
-
well_log_toolkit/visualization.py,sha256=
|
|
10
|
+
well_log_toolkit/visualization.py,sha256=ve6CQSrPsjKoszSNf_9OC-XEsTMOvLTIC2fVzVGe6lo,202169
|
|
11
11
|
well_log_toolkit/well.py,sha256=Aav5Y-rui8YsJdvk7BFndNPUu1O9mcjwDApAGyqV9kw,104535
|
|
12
|
-
well_log_toolkit-0.1.
|
|
13
|
-
well_log_toolkit-0.1.
|
|
14
|
-
well_log_toolkit-0.1.
|
|
15
|
-
well_log_toolkit-0.1.
|
|
12
|
+
well_log_toolkit-0.1.139.dist-info/METADATA,sha256=srO5ck8M8BJGwa5F7S87dPyJ_iPnrvsPYwvAqHhCw-U,61388
|
|
13
|
+
well_log_toolkit-0.1.139.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
14
|
+
well_log_toolkit-0.1.139.dist-info/top_level.txt,sha256=BMOo7OKLcZEnjo0wOLMclwzwTbYKYh31I8RGDOGSBdE,17
|
|
15
|
+
well_log_toolkit-0.1.139.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|