Skip to content

Commit 06e586f

Browse files
committed
fix: store location tracking and lines for thickness calculators
adding basal contacts unit name
1 parent 01dfbd4 commit 06e586f

File tree

3 files changed

+94
-34
lines changed

3 files changed

+94
-34
lines changed

loopstructural/gui/map2loop_tools/thickness_calculator_widget.py

Lines changed: 34 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
from loopstructural.toolbelt.preferences import PlgOptionsManager
99

1010
from ...main.helpers import ColumnMatcher, get_layer_names
11+
from ...main.vectorLayerWrapper import addGeoDataFrameToproject
1112

1213

1314
class ThicknessCalculatorWidget(QWidget):
@@ -58,6 +59,7 @@ def __init__(self, parent=None, data_manager=None):
5859
self.calculatorTypeComboBox.currentIndexChanged.connect(self._on_calculator_type_changed)
5960
self.geologyLayerComboBox.layerChanged.connect(self._on_geology_layer_changed)
6061
self.structureLayerComboBox.layerChanged.connect(self._on_structure_layer_changed)
62+
self.basalContactsComboBox.layerChanged.connect(self._on_basal_contacts_layer_changed)
6163
self.runButton.clicked.connect(self._run_calculator)
6264
self._guess_layers()
6365
# Set up field combo boxes
@@ -108,6 +110,18 @@ def _setup_field_combo_boxes(self):
108110
self.unitNameFieldComboBox.setLayer(self.geologyLayerComboBox.currentLayer())
109111
self.dipFieldComboBox.setLayer(self.structureLayerComboBox.currentLayer())
110112
self.dipDirFieldComboBox.setLayer(self.structureLayerComboBox.currentLayer())
113+
self.basalUnitNameFieldComboBox.setLayer(self.basalContactsComboBox.currentLayer())
114+
115+
def _on_basal_contacts_layer_changed(self):
116+
"""Update field combo box when basal contacts layer changes."""
117+
layer = self.basalContactsComboBox.currentLayer()
118+
self.basalUnitNameFieldComboBox.setLayer(layer)
119+
# Optionally auto-select a likely unit name field
120+
if layer:
121+
fields = [field.name() for field in layer.fields()]
122+
matcher = ColumnMatcher(fields)
123+
if unit_match := matcher.find_match('UNITNAME'):
124+
self.basalUnitNameFieldComboBox.setField(unit_match)
111125

112126
def _on_geology_layer_changed(self):
113127
"""Update field combo boxes when geology layer changes."""
@@ -188,6 +202,7 @@ def _run_calculator(self):
188202
'structure': self.structureLayerComboBox.currentLayer(),
189203
'calculator_type': calculator_type,
190204
'unit_name_field': self.unitNameFieldComboBox.currentField(),
205+
'basal_unit_name_field': self.basalUnitNameFieldComboBox.currentField(),
191206
'dip_field': self.dipFieldComboBox.currentField(),
192207
'dipdir_field': self.dipDirFieldComboBox.currentField(),
193208
'orientation_type': self.orientationTypeComboBox.currentText(),
@@ -206,19 +221,32 @@ def _run_calculator(self):
206221

207222
# Get stratigraphic order from data_manager
208223
if self.data_manager and hasattr(self.data_manager, 'stratigraphic_column'):
209-
strati_order = [unit['name'] for unit in self.data_manager.stratigraphic_column]
224+
strati_order = [unit['name'] for unit in self.data_manager._stratigraphic_column]
210225
if strati_order:
211226
kwargs['stratigraphic_order'] = strati_order
212227

213228
result = calculate_thickness(**kwargs)
214229

215-
for idx in result.index:
216-
u = result.loc[idx, 'name']
217-
thick = result.loc[idx, 'ThicknessStdDev']
230+
for idx in result['thicknesses'].index:
231+
u = result['thicknesses'].loc[idx, 'name']
232+
thick = result['thicknesses'].loc[idx, 'ThicknessStdDev']
218233
if thick > 0:
219234

220-
self.data_manager.stratigraphic_column.get_unit_by_name(u).thickness = thick
221-
if result is not None and not result.empty:
235+
self.data_manager._stratigraphic_column.get_unit_by_name(u).thickness = thick
236+
# Save debugging files if checkbox is checked
237+
if self.saveDebugCheckBox.isChecked():
238+
if 'lines' in result:
239+
if result['lines'] is not None and not result['lines'].empty:
240+
addGeoDataFrameToproject(result['lines'], "Lines")
241+
if 'location_tracking' in result:
242+
if (
243+
result['location_tracking'] is not None
244+
and not result['location_tracking'].empty
245+
):
246+
addGeoDataFrameToproject(
247+
result['location_tracking'], "Thickness Location Tracking"
248+
)
249+
if result is not None and not result['thicknesses'].empty:
222250
QMessageBox.information(
223251
self,
224252
"Success",

loopstructural/gui/map2loop_tools/thickness_calculator_widget.ui

Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,7 @@
4848
</widget>
4949
</item>
5050
<item row="2" column="1">
51-
<widget class="QgsMapLayerComboBox" name="geologyLayerComboBox">
52-
</widget>
51+
<widget class="QgsMapLayerComboBox" name="geologyLayerComboBox"/>
5352
</item>
5453
<item row="3" column="0">
5554
<widget class="QLabel" name="unitNameFieldLabel">
@@ -69,69 +68,66 @@
6968
</widget>
7069
</item>
7170
<item row="4" column="1">
72-
<widget class="QgsMapLayerComboBox" name="basalContactsComboBox">
73-
</widget>
71+
<widget class="QgsMapLayerComboBox" name="basalContactsComboBox"/>
7472
</item>
75-
<item row="5" column="0">
73+
<item row="6" column="0">
7674
<widget class="QLabel" name="sampledContactsLabel">
7775
<property name="text">
7876
<string>Sampled Contacts Layer:</string>
7977
</property>
8078
</widget>
8179
</item>
82-
<item row="5" column="1">
83-
<widget class="QgsMapLayerComboBox" name="sampledContactsComboBox">
84-
</widget>
80+
<item row="6" column="1">
81+
<widget class="QgsMapLayerComboBox" name="sampledContactsComboBox"/>
8582
</item>
86-
<item row="6" column="0">
83+
<item row="7" column="0">
8784
<widget class="QLabel" name="structureLayerLabel">
8885
<property name="text">
8986
<string>Structure/Orientation Layer:</string>
9087
</property>
9188
</widget>
9289
</item>
93-
<item row="6" column="1">
94-
<widget class="QgsMapLayerComboBox" name="structureLayerComboBox">
95-
</widget>
90+
<item row="7" column="1">
91+
<widget class="QgsMapLayerComboBox" name="structureLayerComboBox"/>
9692
</item>
97-
<item row="7" column="0">
93+
<item row="8" column="0">
9894
<widget class="QLabel" name="dipFieldLabel">
9995
<property name="text">
10096
<string>Dip Field:</string>
10197
</property>
10298
</widget>
10399
</item>
104-
<item row="7" column="1">
100+
<item row="8" column="1">
105101
<widget class="QgsFieldComboBox" name="dipFieldComboBox"/>
106102
</item>
107-
<item row="8" column="0">
103+
<item row="9" column="0">
108104
<widget class="QLabel" name="dipDirFieldLabel">
109105
<property name="text">
110106
<string>Dip Direction Field:</string>
111107
</property>
112108
</widget>
113109
</item>
114-
<item row="8" column="1">
110+
<item row="9" column="1">
115111
<widget class="QgsFieldComboBox" name="dipDirFieldComboBox"/>
116112
</item>
117-
<item row="9" column="0">
113+
<item row="10" column="0">
118114
<widget class="QLabel" name="orientationTypeLabel">
119115
<property name="text">
120116
<string>Orientation Type:</string>
121117
</property>
122118
</widget>
123119
</item>
124-
<item row="9" column="1">
120+
<item row="10" column="1">
125121
<widget class="QComboBox" name="orientationTypeComboBox"/>
126122
</item>
127-
<item row="10" column="0">
123+
<item row="11" column="0">
128124
<widget class="QLabel" name="maxLineLengthLabel">
129125
<property name="text">
130126
<string>Max Line Length:</string>
131127
</property>
132128
</widget>
133129
</item>
134-
<item row="10" column="1">
130+
<item row="11" column="1">
135131
<widget class="QgsDoubleSpinBox" name="maxLineLengthSpinBox">
136132
<property name="maximum">
137133
<double>1000000.000000000000000</double>
@@ -141,6 +137,30 @@
141137
</property>
142138
</widget>
143139
</item>
140+
<item row="12" column="0">
141+
<widget class="QLabel" name="saveDebugLabel">
142+
<property name="text">
143+
<string>Save Debug Files:</string>
144+
</property>
145+
</widget>
146+
</item>
147+
<item row="12" column="1">
148+
<widget class="QCheckBox" name="saveDebugCheckBox">
149+
<property name="text">
150+
<string>Save debugging files (location tracking, lines)</string>
151+
</property>
152+
</widget>
153+
</item>
154+
<item row="5" column="0">
155+
<widget class="QLabel" name="basalContactUnitnameLabel">
156+
<property name="text">
157+
<string>Basal Contact Unitname:</string>
158+
</property>
159+
</widget>
160+
</item>
161+
<item row="5" column="1">
162+
<widget class="QgsFieldComboBox" name="basalUnitNameFieldComboBox"/>
163+
</item>
144164
</layout>
145165
</item>
146166
<item>
@@ -167,19 +187,19 @@
167187
</widget>
168188
<customwidgets>
169189
<customwidget>
170-
<class>QgsMapLayerComboBox</class>
171-
<extends>QComboBox</extends>
172-
<header>qgsmaplayercombobox.h</header>
190+
<class>QgsDoubleSpinBox</class>
191+
<extends>QDoubleSpinBox</extends>
192+
<header>qgsdoublespinbox.h</header>
173193
</customwidget>
174194
<customwidget>
175195
<class>QgsFieldComboBox</class>
176196
<extends>QComboBox</extends>
177197
<header>qgsfieldcombobox.h</header>
178198
</customwidget>
179199
<customwidget>
180-
<class>QgsDoubleSpinBox</class>
181-
<extends>QDoubleSpinBox</extends>
182-
<header>qgsdoublespinbox.h</header>
200+
<class>QgsMapLayerComboBox</class>
201+
<extends>QComboBox</extends>
202+
<header>qgsmaplayercombobox.h</header>
183203
</customwidget>
184204
</customwidgets>
185205
<resources/>

loopstructural/main/m2l_api.py

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ def calculate_thickness(
296296
max_line_length=None,
297297
stratigraphic_order=None,
298298
updater=None,
299+
basal_contacts_unit_name=None,
299300
):
300301
"""Calculate thickness using map2loop thickness calculators.
301302
@@ -339,6 +340,11 @@ def calculate_thickness(
339340
# Convert layers to GeoDataFrames
340341
geology_gdf = qgsLayerToGeoDataFrame(geology)
341342
basal_contacts_gdf = qgsLayerToGeoDataFrame(basal_contacts)
343+
basal_contacts_gdf = (
344+
basal_contacts_gdf.rename(columns={basal_contacts_unit_name: 'basal_unit'})
345+
if basal_contacts_unit_name
346+
else basal_contacts_gdf
347+
)
342348
sampled_contacts_gdf = qgsLayerToGeoDataFrame(sampled_contacts)
343349
structure_gdf = qgsLayerToDataFrame(structure)
344350
bounding_box = {
@@ -397,6 +403,7 @@ def calculate_thickness(
397403
units_unique = units.drop_duplicates(subset=[unit_name_field]).reset_index(drop=True)
398404
units = pd.DataFrame({'name': units_unique[unit_name_field]})
399405
basal_contacts_gdf['type'] = 'BASAL' # required by calculator
406+
400407
thickness = calculator.compute(
401408
units,
402409
stratigraphic_order,
@@ -405,7 +412,12 @@ def calculate_thickness(
405412
geology_gdf,
406413
sampled_contacts_gdf,
407414
)
415+
res = {'thicknesses': thickness}
408416
if updater:
409417
updater(f"Thickness calculation complete: {len(thickness)} records")
410-
411-
return thickness
418+
if hasattr(calculator, 'lines'):
419+
res['lines'] = calculator.lines
420+
if hasattr(calculator, 'location_tracking'):
421+
res['location_tracking'] = calculator.location_tracking
422+
423+
return res

0 commit comments

Comments
 (0)