Skip to content

Commit b443e29

Browse files
committed
fix: mapping stratigraphic column sorters to qgis fields/layers
works for age based and maximise contacts
1 parent 366e37f commit b443e29

3 files changed

Lines changed: 159 additions & 106 deletions

File tree

loopstructural/gui/map2loop_tools/sorter_widget.py

Lines changed: 79 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from qgis.PyQt import uic
88

99
from loopstructural.main.helpers import get_layer_names
10+
from loopstructural.main.m2l_api import PARAMETERS_DICTIONARY, SORTER_LIST
1011

1112

1213
class SorterWidget(QWidget):
@@ -48,14 +49,7 @@ def __init__(self, parent=None, data_manager=None):
4849
pass
4950

5051
# Initialize sorting algorithms
51-
self.sorting_algorithms = [
52-
"Age‐based",
53-
"NetworkX topological",
54-
"Hint (deprecated)",
55-
"Adjacency α",
56-
"Maximise contacts",
57-
"Observation projections",
58-
]
52+
self.sorting_algorithms = list(SORTER_LIST.keys())
5953
self.sortingAlgorithmComboBox.addItems(self.sorting_algorithms)
6054
self.sortingAlgorithmComboBox.setCurrentIndex(5) # Default to Observation projections
6155

@@ -106,7 +100,6 @@ def _guess_layers(self):
106100
dem_layer_match = dem_layer_matcher.find_match('DTM')
107101
if not dem_layer_match:
108102
dem_layer_match = dem_layer_matcher.find_match('DEM')
109-
print(dem_layer_match)
110103
dem_layer = self.data_manager.find_layer_by_name(dem_layer_match, layer_type=QgsRasterLayer)
111104
self.dtmLayerComboBox.setLayer(dem_layer)
112105

@@ -115,7 +108,6 @@ def _setup_field_combo_boxes(self):
115108
self.unitNameFieldComboBox.setLayer(self.geologyLayerComboBox.currentLayer())
116109
self.minAgeFieldComboBox.setLayer(self.geologyLayerComboBox.currentLayer())
117110
self.maxAgeFieldComboBox.setLayer(self.geologyLayerComboBox.currentLayer())
118-
self.groupFieldComboBox.setLayer(self.geologyLayerComboBox.currentLayer())
119111
self.dipFieldComboBox.setLayer(self.structureLayerComboBox.currentLayer())
120112
self.dipDirFieldComboBox.setLayer(self.structureLayerComboBox.currentLayer())
121113

@@ -127,7 +119,6 @@ def _on_geology_layer_changed(self):
127119
self.unitNameFieldComboBox.setLayer(layer)
128120
self.minAgeFieldComboBox.setLayer(layer)
129121
self.maxAgeFieldComboBox.setLayer(layer)
130-
self.groupFieldComboBox.setLayer(layer)
131122

132123
# Auto-detect appropriate fields
133124
if layer:
@@ -144,9 +135,6 @@ def _on_geology_layer_changed(self):
144135
if max_age_match := matcher.find_match('MAX_AGE'):
145136
self.maxAgeFieldComboBox.setField(max_age_match)
146137

147-
if group_match := matcher.find_match('GROUP'):
148-
self.groupFieldComboBox.setField(group_match)
149-
150138
def _on_structure_layer_changed(self):
151139
"""Update field combo boxes when structure layer changes."""
152140
from ...main.helpers import ColumnMatcher
@@ -168,21 +156,78 @@ def _on_structure_layer_changed(self):
168156
self.dipDirFieldComboBox.setField(dipdir_match)
169157

170158
def _on_algorithm_changed(self):
171-
"""Update UI based on selected sorting algorithm."""
159+
"""Update UI based on selected sorting algorithm and map2loop requirements."""
172160
algorithm_index = self.sortingAlgorithmComboBox.currentIndex()
173-
is_observation_projections = algorithm_index == 5
174-
175-
# Show/hide structure-related fields for observation projections
176-
self.structureLayerLabel.setVisible(is_observation_projections)
177-
self.structureLayerComboBox.setVisible(is_observation_projections)
178-
self.dipFieldLabel.setVisible(is_observation_projections)
179-
self.dipFieldComboBox.setVisible(is_observation_projections)
180-
self.dipDirFieldLabel.setVisible(is_observation_projections)
181-
self.dipDirFieldComboBox.setVisible(is_observation_projections)
182-
self.orientationTypeLabel.setVisible(is_observation_projections)
183-
self.orientationTypeComboBox.setVisible(is_observation_projections)
184-
self.dtmLayerLabel.setVisible(is_observation_projections)
185-
self.dtmLayerComboBox.setVisible(is_observation_projections)
161+
algorithm_name = self.sorting_algorithms[algorithm_index]
162+
# Import map2loop's required arguments for sorters
163+
try:
164+
from map2loop.project import REQUIRED_ARGUMENTS as M2L_REQUIRED_ARGUMENTS
165+
except ImportError:
166+
M2L_REQUIRED_ARGUMENTS = {}
167+
# Fallback to PARAMETERS_DICTIONARY if not found
168+
required_fields = M2L_REQUIRED_ARGUMENTS.get(algorithm_name) or PARAMETERS_DICTIONARY.get(
169+
algorithm_name, []
170+
)
171+
172+
# Hide all relevant widgets by default
173+
self.minAgeFieldLabel.setVisible(False)
174+
self.minAgeFieldComboBox.setVisible(False)
175+
self.maxAgeFieldLabel.setVisible(False)
176+
self.maxAgeFieldComboBox.setVisible(False)
177+
self.unitName1FieldLabel.setVisible(False)
178+
self.unitName1FieldComboBox.setVisible(False)
179+
self.unitName2FieldLabel.setVisible(False)
180+
self.unitName2FieldComboBox.setVisible(False)
181+
182+
self.contactsLayerLabel.setVisible(False)
183+
self.contactsLayerComboBox.setVisible(False)
184+
self.structureLayerLabel.setVisible(False)
185+
self.structureLayerComboBox.setVisible(False)
186+
self.dipFieldLabel.setVisible(False)
187+
self.dipFieldComboBox.setVisible(False)
188+
self.dipDirFieldLabel.setVisible(False)
189+
self.dipDirFieldComboBox.setVisible(False)
190+
self.orientationTypeLabel.setVisible(False)
191+
self.orientationTypeComboBox.setVisible(False)
192+
self.dtmLayerLabel.setVisible(False)
193+
self.dtmLayerComboBox.setVisible(False)
194+
195+
# Show widgets based on required fields
196+
geology_layer = self.geologyLayerComboBox.currentLayer()
197+
if 'min_age_column' in required_fields or 'min_age_field' in required_fields:
198+
self.minAgeFieldLabel.setVisible(True)
199+
self.minAgeFieldComboBox.setVisible(True)
200+
self.minAgeFieldComboBox.setLayer(geology_layer)
201+
if 'max_age_column' in required_fields or 'max_age_field' in required_fields:
202+
self.maxAgeFieldLabel.setVisible(True)
203+
self.maxAgeFieldComboBox.setVisible(True)
204+
self.maxAgeFieldComboBox.setLayer(geology_layer)
205+
if 'unitname1_column' in required_fields or 'unitname_1' in required_fields:
206+
self.unitName1FieldLabel.setVisible(True)
207+
self.unitName1FieldComboBox.setVisible(True)
208+
self.unitName1FieldComboBox.setLayer(self.contactsLayerComboBox.currentLayer())
209+
if 'unitname2_column' in required_fields or 'unitname_2' in required_fields:
210+
self.unitName2FieldLabel.setVisible(True)
211+
self.unitName2FieldComboBox.setVisible(True)
212+
self.unitName2FieldComboBox.setLayer(self.contactsLayerComboBox.currentLayer())
213+
214+
if 'contacts' in required_fields or 'contacts_layer' in required_fields:
215+
self.contactsLayerLabel.setVisible(True)
216+
self.contactsLayerComboBox.setVisible(True)
217+
if 'structure' in required_fields or 'structure_layer' in required_fields:
218+
self.structureLayerLabel.setVisible(True)
219+
self.structureLayerComboBox.setVisible(True)
220+
self.dipFieldLabel.setVisible(True)
221+
self.dipFieldComboBox.setVisible(True)
222+
self.dipDirFieldLabel.setVisible(True)
223+
self.dipDirFieldComboBox.setVisible(True)
224+
self.orientationTypeLabel.setVisible(True)
225+
self.orientationTypeComboBox.setVisible(True)
226+
self.dtmLayerLabel.setVisible(True)
227+
self.dtmLayerComboBox.setVisible(True)
228+
229+
# Optionally, handle any additional custom fields from map2loop
230+
# (Add more widget visibility logic here if new fields are added in map2loop)
186231

187232
def _run_sorter(self):
188233
"""Run the stratigraphic sorter algorithm."""
@@ -221,7 +266,7 @@ def _run_sorter(self):
221266
'geology': self.geologyLayerComboBox.currentLayer(),
222267
'contacts': self.contactsLayerComboBox.currentLayer(),
223268
'sorting_algorithm': algorithm_name,
224-
'unit_name_field': self.unitNameFieldComboBox.currentField(),
269+
'unit_name_column': self.unitNameFieldComboBox.currentField(),
225270
'updater': lambda msg: QMessageBox.information(self, "Progress", msg),
226271
}
227272

@@ -234,10 +279,6 @@ def _run_sorter(self):
234279
if max_age_field:
235280
kwargs['max_age_field'] = max_age_field
236281

237-
group_field = self.groupFieldComboBox.currentField()
238-
if group_field:
239-
kwargs['group_field'] = group_field
240-
241282
if is_observation_projections:
242283
kwargs['structure'] = self.structureLayerComboBox.currentLayer()
243284
kwargs['dip_field'] = self.dipFieldComboBox.currentField()
@@ -248,8 +289,12 @@ def _run_sorter(self):
248289
kwargs['dtm'] = self.dtmLayerComboBox.currentLayer()
249290

250291
result = sort_stratigraphic_column(**kwargs)
251-
252292
if result and len(result) > 0:
293+
# Clear and update stratigraphic column in data_manager
294+
self.data_manager.clear_stratigraphic_column()
295+
for unit in result:
296+
self.data_manager.add_to_stratigraphic_column({'name': unit, 'type': 'unit'})
297+
self.data_manager.stratigraphic_column_callback()
253298
QMessageBox.information(
254299
self,
255300
"Success",
@@ -278,7 +323,6 @@ def get_parameters(self):
278323
'unit_name_field': self.unitNameFieldComboBox.currentField(),
279324
'min_age_field': self.minAgeFieldComboBox.currentField(),
280325
'max_age_field': self.maxAgeFieldComboBox.currentField(),
281-
'group_field': self.groupFieldComboBox.currentField(),
282326
'contacts_layer': self.contactsLayerComboBox.currentLayer(),
283327
}
284328

loopstructural/gui/map2loop_tools/sorter_widget.ui

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -68,84 +68,94 @@
6868
<widget class="QgsFieldComboBox" name="maxAgeFieldComboBox"/>
6969
</item>
7070
<item row="5" column="0">
71-
<widget class="QLabel" name="groupFieldLabel">
72-
<property name="text">
73-
<string>Group Field:</string>
74-
</property>
75-
</widget>
76-
</item>
77-
<item row="5" column="1">
78-
<widget class="QgsFieldComboBox" name="groupFieldComboBox"/>
79-
</item>
80-
<item row="6" column="0">
8171
<widget class="QLabel" name="contactsLayerLabel">
8272
<property name="text">
8373
<string>Contacts Layer:</string>
8474
</property>
8575
</widget>
8676
</item>
87-
<item row="6" column="1">
77+
<item row="5" column="1">
8878
<widget class="QgsMapLayerComboBox" name="contactsLayerComboBox">
8979
</widget>
9080
</item>
91-
<item row="7" column="0">
81+
<item row="6" column="0">
9282
<widget class="QLabel" name="structureLayerLabel">
9383
<property name="text">
9484
<string>Structure Layer:</string>
9585
</property>
9686
</widget>
9787
</item>
98-
<item row="7" column="1">
88+
<item row="6" column="1">
9989
<widget class="QgsMapLayerComboBox" name="structureLayerComboBox">
10090
<property name="allowEmptyLayer">
10191
<bool>true</bool>
10292
</property>
10393
</widget>
10494
</item>
105-
<item row="8" column="0">
95+
<item row="7" column="0">
10696
<widget class="QLabel" name="dipFieldLabel">
10797
<property name="text">
10898
<string>Dip Field:</string>
10999
</property>
110100
</widget>
111101
</item>
112-
<item row="8" column="1">
102+
<item row="7" column="1">
113103
<widget class="QgsFieldComboBox" name="dipFieldComboBox"/>
114104
</item>
115-
<item row="9" column="0">
105+
<item row="8" column="0">
116106
<widget class="QLabel" name="dipDirFieldLabel">
117107
<property name="text">
118108
<string>Dip Direction Field:</string>
119109
</property>
120110
</widget>
121111
</item>
122-
<item row="9" column="1">
112+
<item row="8" column="1">
123113
<widget class="QgsFieldComboBox" name="dipDirFieldComboBox"/>
124114
</item>
125-
<item row="10" column="0">
115+
<item row="9" column="0">
126116
<widget class="QLabel" name="orientationTypeLabel">
127117
<property name="text">
128118
<string>Orientation Type:</string>
129119
</property>
130120
</widget>
131121
</item>
132-
<item row="10" column="1">
122+
<item row="9" column="1">
133123
<widget class="QComboBox" name="orientationTypeComboBox"/>
134124
</item>
135-
<item row="11" column="0">
125+
<item row="10" column="0">
136126
<widget class="QLabel" name="dtmLayerLabel">
137127
<property name="text">
138128
<string>DTM Layer:</string>
139129
</property>
140130
</widget>
141131
</item>
142-
<item row="11" column="1">
132+
<item row="10" column="1">
143133
<widget class="QgsMapLayerComboBox" name="dtmLayerComboBox">
144134
<property name="allowEmptyLayer">
145135
<bool>true</bool>
146136
</property>
147137
</widget>
148138
</item>
139+
<item row="11" column="0">
140+
<widget class="QLabel" name="unitName1FieldLabel">
141+
<property name="text">
142+
<string>Unit Name 1 Field:</string>
143+
</property>
144+
</widget>
145+
</item>
146+
<item row="11" column="1">
147+
<widget class="QgsFieldComboBox" name="unitName1FieldComboBox"/>
148+
</item>
149+
<item row="12" column="0">
150+
<widget class="QLabel" name="unitName2FieldLabel">
151+
<property name="text">
152+
<string>Unit Name 2 Field:</string>
153+
</property>
154+
</widget>
155+
</item>
156+
<item row="12" column="1">
157+
<widget class="QgsFieldComboBox" name="unitName2FieldComboBox"/>
158+
</item>
149159
</layout>
150160
</item>
151161
<item>

0 commit comments

Comments
 (0)