Source code for sec_interp.exporters.interpretation_exporters

from __future__ import annotations

"""Interpretation exporters for SecInterp.

This module provides exporters for 2D interpretation data.
"""

from pathlib import Path
from typing import Any

from qgis.core import (
    QgsFeature,
    QgsField,
    QgsFields,
    QgsGeometry,
    QgsPointXY,
    QgsProject,
    QgsVectorFileWriter,
    QgsVectorLayer,
)
from qgis.PyQt.QtCore import QMetaType

from sec_interp.exporters.base_exporter import BaseExporter
from sec_interp.logger_config import get_logger

logger = get_logger(__name__)


[docs] class Interpretation2DExporter(BaseExporter): """Exports interpretations in 2D profile coordinates."""
[docs] def __init__(self, settings: dict[str, Any]): """Initialize with settings. Args: settings: Dictionary of configuration settings. """ super().__init__(settings)
[docs] def export( self, output_path: Path, data: dict[str, Any], ) -> bool: """Export interpretations to Shapefile. Args: output_path: Path to the output Shapefile (.shp) data: Dictionary containing: - interpretations: List of InterpretationPolygon objects Returns: bool: True if export successful, False otherwise """ interpretations = data.get("interpretations", []) if not interpretations: logger.warning("No interpretations to export.") return False try: fields, sorted_keys = self._prepare_fields(interpretations) layer = QgsVectorLayer("Polygon?crs=", "interpretations_2d", "memory") layer.dataProvider().addAttributes(fields) layer.updateFields() features = [] for interp in interpretations: feat = self._create_feature(interp, fields, sorted_keys) if feat: features.append(feat) layer.dataProvider().addFeatures(features) return self._write_to_file(layer, output_path) except Exception: logger.exception(f"Failed to export interpretations to {output_path}") return False
def _prepare_fields(self, interpretations: list[Any]) -> tuple[QgsFields, list[str]]: """Identify custom attributes and create fields.""" all_attr_keys = set() for interp in interpretations: if interp.attributes: all_attr_keys.update(interp.attributes.keys()) sorted_keys = sorted(all_attr_keys) fields = QgsFields() fields.append(QgsField("id", QMetaType.Type.QString, len=50)) fields.append(QgsField("name", QMetaType.Type.QString, len=100)) fields.append(QgsField("type", QMetaType.Type.QString, len=50)) fields.append(QgsField("color", QMetaType.Type.QString, len=10)) fields.append(QgsField("created_at", QMetaType.Type.QString, len=30)) for key in sorted_keys: fields.append(QgsField(key, QMetaType.Type.QString, len=255)) return fields, sorted_keys def _create_feature(self, interp: Any, fields: QgsFields, sorted_keys: list[str]) -> QgsFeature: """Create a QgsFeature with geometry and attributes.""" # Create polygon geometry from 2D vertices points = [QgsPointXY(x, y) for x, y in interp.vertices_2d] # Ensure polygon is closed if points and points[0] != points[-1]: points.append(points[0]) geom = QgsGeometry.fromPolygonXY([points]) feature = QgsFeature(fields) feature.setGeometry(geom) # Set attributes attrs = [ interp.id, interp.name, interp.type, interp.color, interp.created_at, ] for key in sorted_keys: val = interp.attributes.get(key, "") attrs.append(str(val)) feature.setAttributes(attrs) return feature def _write_to_file(self, layer: QgsVectorLayer, output_path: Path) -> bool: """Write the vector layer to a Shapefile on disk.""" options = QgsVectorFileWriter.SaveVectorOptions() options.driverName = "ESRI Shapefile" options.fileEncoding = "UTF-8" result, error_msg, _new_layer_id, _new_layer_path = ( QgsVectorFileWriter.writeAsVectorFormatV3( layer, str(output_path), QgsProject.instance().transformContext(), options, ) ) if result == QgsVectorFileWriter.NoError: logger.info(f"Successfully exported to {output_path}") return True else: logger.error(f"Failed to export interpretations: {error_msg}") return False
[docs] def get_supported_extensions(self) -> list[str]: """Get list of supported file extensions. Returns: List of supported extensions. """ return [".shp"]