# sec_interp.core.validation package

class sec_interp.core.validation.ProjectValidator

  Bases: `TranslatableMixin`

  Orchestrates validation of project parameters independent of the GUI.

  Level 2: Business Logic Validation. Uses ValidationContext to accumulate errors and verify cross-field dependencies.

  classmethod is_dem_complete(params: ValidationParams) → bool

    Check if DEM configuration is complete.

  classmethod is_drillhole_complete(params: ValidationParams) → bool

    Check if required fields are filled if drillhole layers are selected.

  classmethod is_geology_complete(params: ValidationParams) → bool

    Check if geology configuration is complete.

  classmethod is_structure_complete(params: ValidationParams) → bool

    Check if structural configuration is complete.

  classmethod validate_all(params: ValidationParams) → bool

    Perform a comprehensive validation of all project parameters.

  classmethod validate_preview_requirements(params: ValidationParams) → bool

    Validate only the minimum requirements needed to generate a preview.

class sec_interp.core.validation.ValidationParams(raster_layer: str | QgsRasterLayer | None = None, band_number: int | None = None, line_layer: str | QgsVectorLayer | None = None, output_path: str = '', scale: float = 1.0, vert_exag: float = 1.0, buffer_dist: float = 0.0, outcrop_layer: str | QgsVectorLayer | None = None, outcrop_field: str | None = None, struct_layer: str | QgsVectorLayer | None = None, struct_dip_field: str | None = None, struct_strike_field: str | None = None, dip_scale_factor: float = 1.0, collar_layer: str | QgsVectorLayer | None = None, collar_id: str | None = None, collar_use_geom: bool = True, collar_x: str | None = None, collar_y: str | None = None, survey_layer: str | QgsVectorLayer | None = None, survey_id: str | None = None, survey_depth: str | None = None, survey_azim: str | None = None, survey_incl: str | None = None, interval_layer: str | QgsVectorLayer | None = None, interval_id: str | None = None, interval_from: str | None = None, interval_to: str | None = None, interval_lith: str | None = None)

  Bases: `object`

  Data container for all parameters that need cross-layer validation.

  band_number: int | None = None
  buffer_dist: float = 0.0
  collar_id: str | None = None
  collar_layer: str | QgsVectorLayer | None = None
  collar_use_geom: bool = True
  collar_x: str | None = None
  collar_y: str | None = None
  dip_scale_factor: float = 1.0
  interval_from: str | None = None
  interval_id: str | None = None
  interval_layer: str | QgsVectorLayer | None = None
  interval_lith: str | None = None
  interval_to: str | None = None
  line_layer: str | QgsVectorLayer | None = None
  outcrop_field: str | None = None
  outcrop_layer: str | QgsVectorLayer | None = None
  output_path: str = ''
  raster_layer: str | QgsRasterLayer | None = None
  scale: float = 1.0
  struct_dip_field: str | None = None
  struct_layer: str | QgsVectorLayer | None = None
  struct_strike_field: str | None = None
  survey_azim: str | None = None
  survey_depth: str | None = None
  survey_id: str | None = None
  survey_incl: str | None = None
  survey_layer: str | QgsVectorLayer | None = None
  vert_exag: float = 1.0

sec_interp.core.validation.validate_angle_range(value: float, field_name: str, min_angle: float = 0.0, max_angle: float = 360.0) → tuple[bool, str]

  Validate that an angle value is within the expected range.

  Parameters:

    - value – The angle value to validate.

    - field_name – Name of the field for error messages.

    - min_angle – Minimum allowed angle (default 0.0).

    - max_angle – Maximum allowed angle (default 360.0).

  Returns:

    (is_valid, error_message)

      - is_valid: True if validation passed.

      - error_message: Error details if validation failed.

  Return type:

    tuple

sec_interp.core.validation.validate_crs_compatibility(layers: list[qgis.core.QgsMapLayer]) → tuple[bool, str]

  Validate that a list of layers have compatible Coordinate Reference Systems.

  If layers have different CRSs, it returns a warning message instead of an error.

sec_interp.core.validation.validate_field_exists(layer: qgis.core.QgsVectorLayer, field_name: str | None) → tuple[bool, str]

  Validate that a specific field exists in a vector layer.

  Parameters:

    - layer – The QGIS vector layer to check.

    - field_name – The name of the field to search for.

  Returns:

    (is_valid, error_message)

      - is_valid: True if validation passed.

      - error_message: Error details if validation failed.

  Return type:

    tuple

sec_interp.core.validation.validate_field_type(layer: qgis.core.QgsVectorLayer, field_name: str, expected_types: list[FieldType]) → tuple[bool, str]

  Validate that a field in a layer has one of the expected data types.

  Parameters:

    - layer – The QGIS vector layer containing the field.

    - field_name – The name of the field to check.

    - expected_types – List of allowed FieldType values.

  Returns:

    (is_valid, error_message)

      - is_valid: True if validation passed.

      - error_message: Error details if validation failed.

  Return type:

    tuple

sec_interp.core.validation.validate_integer_input(value: str, min_val: int | None = None, max_val: int | None = None, field_name: str = 'Value', allow_empty: bool = False) → tuple[bool, str, int | None]

  Validate an integer input string from a text field.

  Parameters:

    - value – The string value to validate.

    - min_val – Optional minimum value allowed.

    - max_val – Optional maximum value allowed.

    - field_name – Name of the field for error messages.

    - allow_empty – Whether to allow an empty string.

  Returns:

    (is_valid, error_message, int_value)

      - is_valid: True if validation passed.

      - error_message: Error details if validation failed.

      - int_value: The parsed integer value if valid, else None.

  Return type:

    tuple

sec_interp.core.validation.validate_layer_exists(layer_name: str | None) → tuple[bool, str, QgsMapLayer | None]

  Validate that a layer with the given name exists in the current QGIS project.

  Parameters:

    layer_name – The name of the layer to search for.

  Returns:

    (is_valid, error_message, layer)

      - is_valid: True if at least one matching layer was found.

      - error_message: Error details if no layer was found.

      - layer: The first matching layer instance if valid, else None.

  Return type:

    tuple

sec_interp.core.validation.validate_layer_geometry(layer: qgis.core.QgsVectorLayer, expected_type: qgis.core.QgsWkbTypes.GeometryType) → tuple[bool, str]

  Validate that a vector layer matches the expected QGIS geometry type.

  Parameters:

    - layer – The QGIS vector layer to check.

    - expected_type – The required QgsWkbTypes.GeometryType.

  Returns:

    (is_valid, error_message)

      - is_valid: True if the geometry type matches.

      - error_message: Detailed error if types mismatch.

  Return type:

    tuple

sec_interp.core.validation.validate_layer_has_features(layer: qgis.core.QgsVectorLayer) → tuple[bool, str]

  Validate that a vector layer contains at least one feature.

  Parameters:

    layer – The QGIS vector layer to check.

  Returns:

    (is_valid, error_message)

      - is_valid: True if the layer has features.

      - error_message: Error details if the layer is empty.

  Return type:

    tuple

sec_interp.core.validation.validate_numeric_input(value: str, min_val: float | None = None, max_val: float | None = None, field_name: str = 'Value', allow_empty: bool = False) → tuple[bool, str, float | None]

  Validate a numeric input string from a text field.

  Parameters:

    - value – The string value to validate.

    - min_val – Optional minimum value allowed.

    - max_val – Optional maximum value allowed.

    - field_name – Name of the field for error messages.

    - allow_empty – Whether to allow an empty string.

  Returns:

    (is_valid, error_message, float_value)

      - is_valid: True if validation passed.

      - error_message: Error details if validation failed.

      - float_value: The parsed numeric value if valid, else None.

  Return type:

    tuple

sec_interp.core.validation.validate_output_path(path: str) → tuple[bool, str, Path | None]

  Validate that an output path is a valid directory and currently writable.

  This is a convenience wrapper around validate_safe_output_path() for general directory validation.

  Parameters:

    path – The path string to validate.

  Returns:

    (is_valid, error_message, resolved_path)

      - is_valid: True if the directory is valid and writable.

      - error_message: Error details if validation fails.

      - resolved_path: Absolute Path object if valid, else None.

  Return type:

    tuple

sec_interp.core.validation.validate_raster_band(layer: qgis.core.QgsRasterLayer, band_number: int) → tuple[bool, str]

  Validate that a specified band number exists in the given raster layer.

  Parameters:

    - layer – The QGIS raster layer to check.

    - band_number – The 1-based index of the raster band.

  Returns:

    (is_valid, error_message)

      - is_valid: True if the band exists.

      - error_message: Error message if the band is out of range.

  Return type:

    tuple

sec_interp.core.validation.validate_reasonable_ranges(values: dict[str, Any]) → list[str]

  Check for unreasonable or potentially erroneous parameter values.

  This function does not return hard errors, but a list of warning strings to inform the user about extreme values (e.g., vertical exaggeration > 10).

  Parameters:

    values – Dictionary containing parameter names and their current values.

  Returns:

    A list of warning messages. If empty, all values are reasonable.

sec_interp.core.validation.validate_safe_output_path(path: str, base_dir: Path | None = None, must_exist: bool = False, create_if_missing: bool = False) → tuple[bool, str, Path | None]

  Validate an output path string with security and path traversal protection.

sec_interp.core.validation.validate_structural_requirements(layer: QgsVectorLayer, layer_name: str, dip_field: str | None, strike_field: str | None, context: ValidationContext | None = None) → tuple[bool, str]

  Validate structural layer requirements (geometry and attribute fields).

## Submodules

- sec_interp.core.validation.base_validator module
  - `IValidator`
    - `IValidator.validate()`
- sec_interp.core.validation.field_validator module
  - `validate_angle_range()`
  - `validate_field_exists()`
  - `validate_field_type()`
  - `validate_integer_input()`
  - `validate_numeric_input()`
- sec_interp.core.validation.layer_validator module
  - `validate_crs_compatibility()`
  - `validate_geology_requirements()`
  - `validate_layer_exists()`
  - `validate_layer_geometry()`
  - `validate_layer_has_features()`
  - `validate_raster_band()`
  - `validate_structural_requirements()`
- sec_interp.core.validation.path_validator module
  - `validate_output_path()`
  - `validate_safe_output_path()`
- sec_interp.core.validation.pipeline module
  - `ValidationPipeline`
    - `ValidationPipeline.__init__()`
    - `ValidationPipeline.add_validator()`
    - `ValidationPipeline.execute()`
- sec_interp.core.validation.project_validator module
  - `ProjectValidator`
    - `ProjectValidator.is_dem_complete()`
    - `ProjectValidator.is_drillhole_complete()`
    - `ProjectValidator.is_geology_complete()`
    - `ProjectValidator.is_structure_complete()`
    - `ProjectValidator.validate_all()`
    - `ProjectValidator.validate_preview_requirements()`
  - `ValidationParams`
    - `ValidationParams.band_number`
    - `ValidationParams.buffer_dist`
    - `ValidationParams.collar_id`
    - `ValidationParams.collar_layer`
    - `ValidationParams.collar_use_geom`
    - `ValidationParams.collar_x`
    - `ValidationParams.collar_y`
    - `ValidationParams.dip_scale_factor`
    - `ValidationParams.interval_from`
    - `ValidationParams.interval_id`
    - `ValidationParams.interval_layer`
    - `ValidationParams.interval_lith`
    - `ValidationParams.interval_to`
    - `ValidationParams.line_layer`
    - `ValidationParams.outcrop_field`
    - `ValidationParams.outcrop_layer`
    - `ValidationParams.output_path`
    - `ValidationParams.raster_layer`
    - `ValidationParams.scale`
    - `ValidationParams.struct_dip_field`
    - `ValidationParams.struct_layer`
    - `ValidationParams.struct_strike_field`
    - `ValidationParams.survey_azim`
    - `ValidationParams.survey_depth`
    - `ValidationParams.survey_id`
    - `ValidationParams.survey_incl`
    - `ValidationParams.survey_layer`
    - `ValidationParams.vert_exag`
- sec_interp.core.validation.project_validators module
  - `DEMValidator`
    - `DEMValidator.validate()`
  - `DrillholeValidator`
    - `DrillholeValidator.validate()`
  - `GeologyValidator`
    - `GeologyValidator.validate()`
  - `OutputValidator`
    - `OutputValidator.validate()`
  - `SectionValidator`
    - `SectionValidator.validate()`
  - `StructureValidator`
    - `StructureValidator.validate()`
- sec_interp.core.validation.validation_helpers module
  - `DependencyRule`
    - `DependencyRule.check`
    - `DependencyRule.condition`
    - `DependencyRule.error_message`
    - `DependencyRule.target_field`
    - `DependencyRule.validate()`
  - `LayerResolver`
    - `LayerResolver.clear_cache()`
    - `LayerResolver.invalidate()`
    - `LayerResolver.resolve()`
  - `RichValidationError`
    - `RichValidationError.__str__()`
    - `RichValidationError.context`
    - `RichValidationError.field_name`
    - `RichValidationError.message`
    - `RichValidationError.severity`
  - `ValidationContext`
    - `ValidationContext.__init__()`
    - `ValidationContext.add_error()`
    - `ValidationContext.add_warning()`
    - `ValidationContext.errors`
    - `ValidationContext.has_errors`
    - `ValidationContext.has_warnings`
    - `ValidationContext.merge()`
    - `ValidationContext.raise_if_errors()`
    - `ValidationContext.warnings`
  - `validate_dependencies()`
  - `validate_reasonable_ranges()`
- sec_interp.core.validation.validators module
  - `FieldValidator`
    - `FieldValidator.__call__()`
    - `FieldValidator.__init__()`
  - `coerce_type()`
  - `validate_and_clamp()`
  - `validate_non_empty()`
  - `validate_non_negative()`
  - `validate_percentage()`
  - `validate_positive()`
  - `validate_positive_int()`
  - `validate_probability()`
  - `validate_range()`