1+ from unittest import runner
2+
13import pandas as pd
24from map2loop .contact_extractor import ContactExtractor
35from map2loop .sampler import SamplerDecimator , SamplerSpacing
1012)
1113from map2loop .thickness_calculator import InterpolatedStructure , StructuralPoint
1214from osgeo import gdal
15+ from pkg_resources import run_main
16+
17+ from loopstructural .main .debug import export
1318
1419from ..main .vectorLayerWrapper import qgsLayerToDataFrame , qgsLayerToGeoDataFrame
20+ from .debug .export import export_debug_package
1521
1622# Mapping of sorter names to sorter classes
1723SORTER_LIST = {
@@ -38,6 +44,7 @@ def extract_basal_contacts(
3844 unit_name_field = None ,
3945 all_contacts = False ,
4046 updater = None ,
47+ debug_manager = None ,
4148):
4249 """Extract basal contacts from geological data.
4350
@@ -76,9 +83,40 @@ def extract_basal_contacts(
7683 faults = qgsLayerToGeoDataFrame (faults ) if faults else None
7784 if unit_name_field and unit_name_field != 'UNITNAME' and unit_name_field in geology .columns :
7885 geology = geology .rename (columns = {unit_name_field : 'UNITNAME' })
86+ # Log parameters via DebugManager if provided
87+ if debug_manager :
88+ debug_manager .log_params (
89+ "extract_basal_contacts" ,
90+ {
91+ "stratigraphic_order" : stratigraphic_order ,
92+ "ignore_units" : ignore_units ,
93+ "unit_name_field" : unit_name_field ,
94+ "all_contacts" : all_contacts ,
95+ "geology" : geology ,
96+ "faults" : faults ,
97+ },
98+ )
7999 if updater :
80100 updater ("Extracting Basal Contacts..." )
81101 contact_extractor = ContactExtractor (geology , faults )
102+ # If debug_manager present and debug mode enabled, export tool, layers and params
103+ try :
104+ if debug_manager and getattr (debug_manager , "is_debug" , lambda : False )():
105+
106+ layers = {"geology" : geology , "faults" : faults }
107+ pickles = {"contact_extractor" : contact_extractor }
108+ # export layers and pickles first to get the actual filenames used
109+ exported = export_debug_package (
110+ debug_manager ,
111+ runner_script_name = "run_extract_basal_contacts.py" ,
112+ m2l_object = contact_extractor ,
113+ params = {'stratigraphic_order' : stratigraphic_order },
114+ )
115+
116+ except Exception as e :
117+ print ("Failed to save sampler debug info" )
118+ print (e )
119+
82120 all_contacts_result = contact_extractor .extract_all_contacts ()
83121 basal_contacts = contact_extractor .extract_basal_contacts (stratigraphic_order )
84122
@@ -104,6 +142,7 @@ def sort_stratigraphic_column(
104142 dipdir_field = "DIPDIR" ,
105143 orientation_type = "Dip Direction" ,
106144 dtm = None ,
145+ debug_manager = None ,
107146 updater = None ,
108147 contacts = None ,
109148):
@@ -153,6 +192,23 @@ def sort_stratigraphic_column(
153192 # Convert layers to GeoDataFrames
154193 geology_gdf = qgsLayerToGeoDataFrame (geology )
155194 contacts_gdf = qgsLayerToGeoDataFrame (contacts )
195+
196+ # Log parameters via DebugManager if provided
197+ if debug_manager :
198+ debug_manager .log_params (
199+ "sort_stratigraphic_column" ,
200+ {
201+ "sorting_algorithm" : sorting_algorithm ,
202+ "unit_name_field" : unit_name_field ,
203+ "min_age_field" : min_age_field ,
204+ "max_age_field" : max_age_field ,
205+ "orientation_type" : orientation_type ,
206+ "dtm" : dtm ,
207+ "geology" : geology_gdf ,
208+ "contacts" : contacts_gdf ,
209+ },
210+ )
211+
156212 # Build units DataFrame
157213 if (
158214 unit_name_field
@@ -208,6 +264,21 @@ def sort_stratigraphic_column(
208264 sorter_args = {k : v for k , v in all_args .items () if k in required_args }
209265 print (f'Calling sorter with args: { sorter_args .keys ()} ' )
210266 sorter = sorter_cls (** sorter_args )
267+ # If debugging, pickle sorter and write a small runner script
268+ try :
269+ if debug_manager and getattr (debug_manager , "is_debug" , lambda : False )():
270+
271+ _exported = export_debug_package (
272+ debug_manager ,
273+ m2l_object = sorter ,
274+ params = {'units_df' : units_df },
275+ runner_script_name = "run_sort_stratigraphic_column.py" ,
276+ )
277+
278+ except Exception as e :
279+ print ("Failed to save sampler debug info" )
280+ print (e )
281+
211282 order = sorter .sort (units_df )
212283 if updater :
213284 updater (f"Sorting complete: { len (order )} units ordered" )
@@ -222,6 +293,7 @@ def sample_contacts(
222293 spacing = None ,
223294 dtm = None ,
224295 geology = None ,
296+ debug_manager = None ,
225297 updater = None ,
226298):
227299 """Sample spatial data using map2loop samplers.
@@ -267,6 +339,20 @@ def sample_contacts(
267339 if geology is not None :
268340 geology_gdf = qgsLayerToGeoDataFrame (geology )
269341
342+ # Log parameters via DebugManager if provided
343+ if debug_manager :
344+ debug_manager .log_params (
345+ "sample_contacts" ,
346+ {
347+ "sampler_type" : sampler_type ,
348+ "decimation" : decimation ,
349+ "spacing" : spacing ,
350+ "dtm" : dtm ,
351+ "geology" : geology_gdf ,
352+ "spatial_data" : spatial_gdf ,
353+ },
354+ )
355+
270356 # Run sampler
271357 if sampler_type == "Decimator" :
272358 if decimation is None :
@@ -281,8 +367,19 @@ def sample_contacts(
281367
282368 samples = sampler .sample (spatial_gdf )
283369
284- if updater :
285- updater (f"Sampling complete: { len (samples )} samples generated" )
370+ try :
371+ if debug_manager and getattr (debug_manager , "is_debug" , lambda : False )():
372+ _exported = export_debug_package (
373+ debug_manager ,
374+ m2l_object = sampler ,
375+ params = {'spatial_data' : spatial_gdf },
376+ runner_script_name = 'run_sample_contacts.py' ,
377+ )
378+
379+ except Exception as e :
380+ print ("Failed to save sampler debug info" )
381+ print (e )
382+ pass
286383
287384 return samples
288385
@@ -300,6 +397,7 @@ def calculate_thickness(
300397 orientation_type = "Dip Direction" ,
301398 max_line_length = None ,
302399 stratigraphic_order = None ,
400+ debug_manager = None ,
303401 updater = None ,
304402 basal_contacts_unit_name = None ,
305403):
@@ -352,6 +450,24 @@ def calculate_thickness(
352450 )
353451 sampled_contacts_gdf = qgsLayerToGeoDataFrame (sampled_contacts )
354452 structure_gdf = qgsLayerToDataFrame (structure )
453+
454+ # Log parameters via DebugManager if provided
455+ if debug_manager :
456+ debug_manager .log_params (
457+ "calculate_thickness" ,
458+ {
459+ "calculator_type" : calculator_type ,
460+ "unit_name_field" : unit_name_field ,
461+ "orientation_type" : orientation_type ,
462+ "max_line_length" : max_line_length ,
463+ "stratigraphic_order" : stratigraphic_order ,
464+ "geology" : geology_gdf ,
465+ "basal_contacts" : basal_contacts_gdf ,
466+ "sampled_contacts" : sampled_contacts_gdf ,
467+ "structure" : structure_gdf ,
468+ },
469+ )
470+
355471 bounding_box = {
356472 'maxx' : geology_gdf .total_bounds [2 ],
357473 'minx' : geology_gdf .total_bounds [0 ],
@@ -408,7 +524,30 @@ def calculate_thickness(
408524 units_unique = units .drop_duplicates (subset = ['UNITNAME' ]).reset_index (drop = True )
409525 units = pd .DataFrame ({'name' : units_unique ['UNITNAME' ]})
410526 basal_contacts_gdf ['type' ] = 'BASAL' # required by calculator
411-
527+
528+ # No local export path placeholders required; export_debug_package handles exports
529+ try :
530+ if debug_manager and getattr (debug_manager , "is_debug" , lambda : False )():
531+ # Export layers and pickled objects first to get their exported filenames
532+
533+ _exported = export_debug_package (
534+ debug_manager ,
535+ runner_script_name = "run_calculate_thickness.py" ,
536+ m2l_object = calculator ,
537+ params = {
538+ 'units' : units ,
539+ 'stratigraphic_order' : stratigraphic_order ,
540+ 'basal_contacts' : basal_contacts_gdf ,
541+ 'structure' : structure_gdf ,
542+ 'geology' : geology_gdf ,
543+ 'sampled_contacts' : sampled_contacts_gdf ,
544+ },
545+ )
546+
547+ except Exception as e :
548+ print ("Failed to save sampler debug info" )
549+ raise e
550+
412551 thickness = calculator .compute (
413552 units ,
414553 stratigraphic_order ,
@@ -417,12 +556,6 @@ def calculate_thickness(
417556 geology_gdf ,
418557 sampled_contacts_gdf ,
419558 )
559+ # Ensure result object exists for return and for any debug export
420560 res = {'thicknesses' : thickness }
421- if updater :
422- updater (f"Thickness calculation complete: { len (thickness )} records" )
423- if hasattr (calculator , 'lines' ):
424- res ['lines' ] = calculator .lines
425- if hasattr (calculator , 'location_tracking' ):
426- res ['location_tracking' ] = calculator .location_tracking
427-
428561 return res
0 commit comments