2.23.7.1. pycsamt.format.borehole#

PCBH - pyCSAMT Common Borehole Format.

This package exposes the PCBH schema, JSON serialization, and deterministic trajectory derivation. External-format adapters are introduced in later phases.

class pycsamt.format.borehole.PCBHBenchmarkResult(boreholes, json_bytes, render_points, parse_seconds, render_seconds)

Bases: object

Measured timings and output size for a synthetic project.

Parameters:
  • boreholes (int)

  • json_bytes (int)

  • render_points (int)

  • parse_seconds (float)

  • render_seconds (float)

boreholes: int
json_bytes: int
render_points: int
parse_seconds: float
render_seconds: float
to_dict()

Return a JSON-serializable result.

Return type:

dict[str, int | float]

pycsamt.format.borehole.benchmark_pcbh(boreholes=1000)

Benchmark canonical parsing and rendering of vertical boreholes.

Parameters:

boreholes (int)

Return type:

PCBHBenchmarkResult

class pycsamt.format.borehole.ValidationIssue(severity, code, message, path='', source=<factory>)

Bases: PyCSAMTObject

One machine-readable PCBH validation finding.

Parameters:
severity: str
code: str
message: str
path: str = ''
source: dict[str, Any]
exception pycsamt.format.borehole.PCBHValidationError(issues)

Bases: ValueError

Raised when error-severity issues remain after validation.

Parameters:

issues (Iterable[ValidationIssue])

class pycsamt.format.borehole.CoordinateReferenceSystem(horizontal, vertical='unknown', axis_order='xy', coordinate_unit='m')

Bases: _Validatable, PyCSAMTObject

Document-wide horizontal and vertical coordinate references.

Parameters:
  • horizontal (str)

  • vertical (str)

  • axis_order (str)

  • coordinate_unit (str)

horizontal: str
vertical: str = 'unknown'
axis_order: str = 'xy'
coordinate_unit: str = 'm'
collect_issues(path='crs')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.UnitSystem(depth='m', diameter='m', angle='deg', resistivity='ohm.m')

Bases: _Validatable, PyCSAMTObject

Units shared by all boreholes in one PCBH 0.1 document.

Parameters:
depth: str = 'm'
diameter: str = 'm'
angle: str = 'deg'
resistivity: str = 'ohm.m'
collect_issues(path='units')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.Collar(x, y, z, longitude=None, latitude=None, position_uncertainty_m=None)

Bases: _Validatable, PyCSAMTObject

Borehole reference/origin position in the document CRS.

Parameters:
x: float
y: float
z: float
longitude: float | None = None
latitude: float | None = None
position_uncertainty_m: float | None = None
collect_issues(path='collar')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.VocabularyEntry(code, name, color=None, description='', external_ids=<factory>, properties=<factory>)

Bases: _Validatable, PyCSAMTObject

Self-contained geological or domain vocabulary entry.

Parameters:
code: str
name: str
color: str | None = None
description: str = ''
external_ids: dict[str, str]
properties: dict[str, Any]
collect_issues(path='vocabulary')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.SurveyStation(md, azimuth_deg, inclination_deg)

Bases: _Validatable, PyCSAMTObject

One measured-depth orientation station.

Parameters:
md: float
azimuth_deg: float
inclination_deg: float
collect_issues(path='survey_station')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.Trajectory(method='vertical', north_reference='unknown', desurvey_method='minimum_curvature', stations=<factory>)

Bases: _Validatable, PyCSAMTObject

Vertical shorthand or measured survey for a borehole path.

Parameters:
  • method (str)

  • north_reference (str)

  • desurvey_method (str)

  • stations (list[SurveyStation])

method: str = 'vertical'
north_reference: str = 'unknown'
desurvey_method: str = 'minimum_curvature'
stations: list[SurveyStation]
collect_issues(path='trajectory')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.LogInterval(from_md, to_md, code=None, label=None, description='', resistivity_ohm_m=None, data_nature='unknown', confidence=None, properties=<factory>)

Bases: _Validatable, PyCSAMTObject

One measured-depth interval in a named log family.

Parameters:
from_md: float
to_md: float
code: str | None = None
label: str | None = None
description: str = ''
resistivity_ohm_m: float | None = None
data_nature: str = 'unknown'
confidence: float | None = None
properties: dict[str, Any]
collect_issues(path='interval')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.StructureObservation(kind, at_md=None, from_md=None, to_md=None, orientation_representation='none', strike_deg=None, dip_deg=None, dip_direction_deg=None, trend_deg=None, plunge_deg=None, alpha_deg=None, beta_deg=None, aperture_m=None, fill=None, data_nature='unknown', confidence=None)

Bases: _Validatable, PyCSAMTObject

Point or interval structural observation along a borehole.

Parameters:
  • kind (str)

  • at_md (float | None)

  • from_md (float | None)

  • to_md (float | None)

  • orientation_representation (str)

  • strike_deg (float | None)

  • dip_deg (float | None)

  • dip_direction_deg (float | None)

  • trend_deg (float | None)

  • plunge_deg (float | None)

  • alpha_deg (float | None)

  • beta_deg (float | None)

  • aperture_m (float | None)

  • fill (str | None)

  • data_nature (str)

  • confidence (float | None)

kind: str
at_md: float | None = None
from_md: float | None = None
to_md: float | None = None
orientation_representation: str = 'none'
strike_deg: float | None = None
dip_deg: float | None = None
dip_direction_deg: float | None = None
trend_deg: float | None = None
plunge_deg: float | None = None
alpha_deg: float | None = None
beta_deg: float | None = None
aperture_m: float | None = None
fill: str | None = None
data_nature: str = 'unknown'
confidence: float | None = None
collect_issues(path='structure')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.PCBHBorehole(id, name, kind, status, collar, total_depth_md, trajectory=<factory>, diameter=None, interval_logs=<factory>, structures=<factory>, aliases=<factory>, metadata=<factory>, extensions=<factory>)

Bases: _Validatable, PyCSAMTObject, MetadataMixin

One borehole and its trajectory, logs, and structures.

Parameters:
id: str
name: str
kind: str
status: str
collar: Collar
total_depth_md: float
trajectory: Trajectory
diameter: float | None = None
interval_logs: dict[str, list[LogInterval]]
structures: list[StructureObservation]
aliases: list[str]
metadata: dict[str, Any]
extensions: dict[str, Any]
collect_issues(path='borehole')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.PCBHDocument(document_id, created_at, created_by, crs, boreholes, units=<factory>, title='', description='', lithologies=<factory>, formations=<factory>, pcbh_version='0.1.0', azimuth_direction='clockwise', inclination_reference='vertical_down', depth_reference='collar', z_positive='up', metadata=<factory>, extensions=<factory>)

Bases: _Validatable, PyCSAMTObject, MetadataMixin

Root PCBH document containing one or more boreholes.

Parameters:
  • document_id (str)

  • created_at (str)

  • created_by (str)

  • crs (CoordinateReferenceSystem)

  • boreholes (list[PCBHBorehole])

  • units (UnitSystem)

  • title (str)

  • description (str)

  • lithologies (list[VocabularyEntry])

  • formations (list[VocabularyEntry])

  • pcbh_version (str)

  • azimuth_direction (str)

  • inclination_reference (str)

  • depth_reference (str)

  • z_positive (str)

  • metadata (dict[str, Any])

  • extensions (dict[str, Any])

document_id: str
created_at: str
created_by: str
crs: CoordinateReferenceSystem
boreholes: list[PCBHBorehole]
units: UnitSystem
title: str = ''
description: str = ''
lithologies: list[VocabularyEntry]
formations: list[VocabularyEntry]
pcbh_version: str = '0.1.0'
azimuth_direction: str = 'clockwise'
inclination_reference: str = 'vertical_down'
depth_reference: str = 'collar'
z_positive: str = 'up'
metadata: dict[str, Any]
extensions: dict[str, Any]
collect_issues(path='$')
Parameters:

path (str)

Return type:

list[ValidationIssue]

class pycsamt.format.borehole.TrajectoryPoint(md, x, y, z, tvd, azimuth_deg, inclination_deg)

Bases: PyCSAMTObject

One derived point and local borehole attitude.

Parameters:
md: float
x: float
y: float
z: float
tvd: float
azimuth_deg: float
inclination_deg: float
class pycsamt.format.borehole.DesurveyedTrajectory(points, source_checksum, method='minimum_curvature')

Bases: PyCSAMTObject

Immutable centerline generated from one PCBH borehole.

Parameters:
  • points (tuple[TrajectoryPoint, ...])

  • source_checksum (str)

  • method (str)

points: tuple[TrajectoryPoint, ...]
source_checksum: str
method: str = 'minimum_curvature'
at_md(md)

Return an exact or minimum-curvature-interpolated point at md.

Parameters:

md (float)

Return type:

TrajectoryPoint

split_at(measured_depths)

Return a centerline containing every requested interval boundary.

Parameters:

measured_depths (Iterable[float])

Return type:

DesurveyedTrajectory

pycsamt.format.borehole.pcbh_to_dict(document, *, validate=True)

Convert a PCBH document to its canonical JSON-compatible mapping.

Parameters:
  • document (PCBHDocument) – In-memory document to convert.

  • validate (bool, default True) – Run semantic validation before conversion.

Returns:

Canonically ordered JSON-compatible mapping.

Return type:

dict

Raises:
  • TypeError – If document is not a PCBHDocument.

  • PCBHValidationError – If semantic validation fails.

  • ValueError – If metadata or extension values are not finite JSON values.

pycsamt.format.borehole.pcbh_from_dict(value, *, validate=True, max_boreholes=10000, max_intervals=1000000, max_nesting=32)

Build a PCBH document from a decoded JSON mapping.

Parameters:
  • value (mapping) – Decoded PCBH root object.

  • validate (bool, default True) – Run semantic validation before returning.

  • max_boreholes (int) – Positive resource limits applied before object construction.

  • max_intervals (int) – Positive resource limits applied before object construction.

  • max_nesting (int) – Positive resource limits applied before object construction.

Returns:

Parsed in-memory document.

Return type:

PCBHDocument

Raises:
  • ValueError – If structure, version, or resource limits are invalid.

  • PCBHValidationError – If semantic validation fails.

pycsamt.format.borehole.read_pcbh(path, *, validate=True, max_bytes=16777216, max_boreholes=10000, max_intervals=1000000, max_nesting=32)

Read a canonical PCBH JSON file.

Parameters:
  • path (path-like) – Input .pcbh.json file.

  • validate (bool, default True) – Run semantic validation before returning.

  • max_bytes (int) – Positive limits for untrusted input.

  • max_boreholes (int) – Positive limits for untrusted input.

  • max_intervals (int) – Positive limits for untrusted input.

  • max_nesting (int) – Positive limits for untrusted input.

Returns:

Parsed and optionally validated document.

Return type:

PCBHDocument

Raises:
  • OSError – If the file cannot be read.

  • UnicodeError – If the file is not UTF-8.

  • ValueError – If JSON, structure, version, or limits are invalid.

  • PCBHValidationError – If semantic validation fails.

pycsamt.format.borehole.write_pcbh(document, path, *, validate=True, indent=2)

Atomically write a canonical PCBH JSON file.

Parameters:
  • document (PCBHDocument) – Document to serialize.

  • path (path-like) – Destination path. Parent directories are created when needed.

  • validate (bool, default True) – Run semantic validation before writing.

  • indent (int, default 2) – Positive JSON indentation width.

Returns:

Destination path.

Return type:

pathlib.Path

Raises:
  • TypeError – If document is not a PCBH document.

  • ValueError – If validation, JSON values, or indent are invalid.

  • OSError – If the atomic write fails.

Notes

The temporary file is created beside the destination so os.replace() remains an atomic same-filesystem operation.

pycsamt.format.borehole.desurvey(borehole, *, boundaries=())

Generate a 3-D centerline for borehole.

Survey stations after total depth are rejected by schema validation. If the first survey station is below the collar, its attitude is extended back to MD 0. Likewise, the final attitude is extended to total depth.

Parameters:
Return type:

DesurveyedTrajectory

pycsamt.format.borehole.trajectory_checksum(borehole)

Return a stable SHA-256 key for trajectory-defining inputs.

Parameters:

borehole (PCBHBorehole)

Return type:

str

pycsamt.format.borehole.from_legacy_borehole(borehole, *, collar, borehole_id=None, total_depth_md=None, kind='unknown', status='unknown')

Promote one legacy geology borehole to a vertical PCBH borehole.

Parameters:
  • borehole (Borehole) – Existing profile-based borehole. Depth and resistivity are assumed to be metres and ohm metres, matching the legacy API.

  • collar (Collar) – Explicit absolute XYZ collar in the target PCBH CRS. The legacy borehole.x is a profile coordinate and is not used as easting.

  • borehole_id (str, optional) – Stable PCBH identifier. Defaults to the legacy name.

  • total_depth_md (float, optional) – Total measured depth in metres. Defaults to the deepest interval. It is required when the legacy borehole has no intervals.

  • kind (str, optional) – PCBH borehole classification values.

  • status (str, optional) – PCBH borehole classification values.

Returns:

A validated vertical PCBH borehole with a lithology log.

Return type:

PCBHBorehole

Raises:
  • TypeError – If the source or collar has the wrong type.

  • ValueError – If depth or resistivity values cannot form a valid PCBH object.

Notes

The legacy profile coordinate is retained in metadata as legacy_profile_x. Empty legacy lithology names become unknown because PCBH intervals require a code or label.

pycsamt.format.borehole.to_legacy_borehole(borehole, *, profile_x, vocabulary=(), rock_db=None, family='lithology')

Create a legacy vertical-log view of a PCBH borehole.

Parameters:
  • borehole (PCBHBorehole) – Source PCBH borehole.

  • profile_x (float) – Explicit distance along the target 2-D profile, in metres. PCBH collar easting is never silently treated as profile distance.

  • vocabulary (sequence of VocabularyEntry, optional) – Embedded dictionary for resolving interval codes to names.

  • rock_db (RockDatabase, optional) – If supplied, unnamed intervals with positive resistivity are classified through this database. It is not used by default.

  • family (str, default='lithology') – PCBH interval-log family to expose through the single legacy log.

Returns:

A new legacy object suitable for existing calibrators and plots.

Return type:

Borehole

Raises:
  • TypeError – If public object parameters have incompatible types.

  • ValueError – If profile_x is non-finite or vocabulary codes conflict.

Notes

See legacy_conversion_losses() for fields unavailable in the returned view. Interval bounds and resistivity remain unchanged.

pycsamt.format.borehole.legacy_borehole_views(document, *, profile_x, family='lithology', rock_db=None)

Build legacy views for existing calibration workflows.

Parameters:
  • document (PCBHDocument) – Valid PCBH document using metres and ohm metres.

  • profile_x (mapping or callable) – Either {borehole_id: profile_distance_m} or a callable receiving a PCBH borehole and returning its profile distance in metres.

  • family (str, default='lithology') – Interval family exposed to the calibrator.

  • rock_db (RockDatabase, optional) – Explicit fallback classifier for unnamed resistivity intervals.

Returns:

Independent legacy views accepted by ModelCalibrator.fit.

Return type:

list of Borehole

Raises:
  • TypeError – If the document or profile mapping has an incompatible type.

  • ValueError – If document units are incompatible with the legacy API.

  • KeyError – If a mapping lacks a borehole identifier.

pycsamt.format.borehole.legacy_conversion_losses(borehole, *, family='lithology')

Describe information omitted from a PCBH-to-legacy view.

Parameters:
  • borehole (PCBHBorehole) – Source object to inspect.

  • family (str, default='lithology') – The one interval family retained by the legacy view.

Returns:

Stable, human-readable loss descriptions.

Return type:

tuple of str

class pycsamt.format.borehole.SheetOutline(name, n_rows, n_cols, preview=<factory>, header_candidates=<factory>)

Bases: PyCSAMTObject

Lightweight description of one worksheet.

Parameters:
name: str
n_rows: int
n_cols: int
preview: list[list[str]]
header_candidates: list[int]
class pycsamt.format.borehole.WorkbookOutline(source, sheets=<factory>)

Bases: PyCSAMTObject

All sheets in a workbook, previews only — no bulk data read.

Parameters:
  • source (str)

  • sheets (list[SheetOutline])

source: str
sheets: list[SheetOutline]
sheet(key)

Return one sheet by name or positional index.

Parameters:

key (str | int)

Return type:

SheetOutline

pycsamt.format.borehole.inspect_workbook(source)

Return sheet names, shapes, previews, and header-row guesses.

Parameters:

source (path-like or bytes) – An .xlsx workbook. Bytes are accepted so an application can pass an uploaded payload without touching disk.

Returns:

One SheetOutline per worksheet.

Return type:

WorkbookOutline

pycsamt.format.borehole.boreholes_from_xlsx(source, *, sheet=None, header_row=None, columns=None, constants=None, collars=None, default_borehole_id=None, strict=True, document_id=None, created_by='pycsamt XLSX importer', max_bytes=10485760, max_rows=250000)

Import one worksheet of a borehole workbook as a PCBH document.

Parameters:
  • source (path-like or bytes) – The .xlsx workbook.

  • sheet (str or int, optional) – Worksheet name or 0-based index. Defaults to the first sheet.

  • header_row (int, optional) – 0-based row index of the header. Auto-detected when omitted (the first row with at least two text cells).

  • columns (dict, optional) – Explicit {canonical_field: source} mapping. source may be a header string, a 0-based column index, or an Excel column letter. Canonical names use dotted paths such as interval.from_md.

  • constants (dict, optional) – Constant canonical values (commonly borehole.id and crs.horizontal for a single-hole sheet).

  • collars (dict or path-like, optional) – External collar positions, keyed by borehole id ({"ZK2203": {"x": .., "y": .., "z": .., "crs": "EPSG:32648"}}), or a single {"x": .., "y": .., "z": ..} applied to every hole, or a small CSV with id,x,y,z[,crs] columns. Spreadsheets rarely carry coordinates, so this is how they enter the document.

  • strict (bool, default=True) – Raise PCBHCSVImportError on any recorded error. In permissive mode a missing collar/CRS becomes a flagged placeholder and invalid rows are dropped.

  • document_id (str, optional) – Defaults to xlsx:<file stem>.

  • created_by (str, default='pycsamt XLSX importer') – Provenance name stored on the document.

  • max_bytes (int) – Resource limits, shared with the CSV importer.

  • max_rows (int) – Resource limits, shared with the CSV importer.

  • default_borehole_id (str | None)

Returns:

  • document (PCBHDocument)

  • report (ImportReport) – Includes the resolved sheet, header row, column mapping, injected collars, and every rejected row.

Return type:

tuple[PCBHDocument, ImportReport]

class pycsamt.format.borehole.CSVMappingProfile(name, columns=<factory>, constants=<factory>)

Bases: PyCSAMTObject

Reusable source-column mapping and constant values.

Parameters:
name: str
columns: dict[str, str]
constants: dict[str, Any]
validate()

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

to_dict()

Return a shallow dictionary representation.

Return type:

dict[str, Any]

classmethod from_dict(value)
Parameters:

value (dict[str, Any])

Return type:

CSVMappingProfile

class pycsamt.format.borehole.BuilderDiagnostic(severity, code, message, path, editor, row=None)

Bases: PyCSAMTObject

Validation issue augmented with editor/table navigation.

Parameters:
severity: str
code: str
message: str
path: str
editor: str
row: int | None = None
class pycsamt.format.borehole.BuilderValidation(document, diagnostics)

Bases: PyCSAMTObject

Result of constructing and validating a builder draft.

Parameters:
  • document (PCBHDocument | None)

  • diagnostics (tuple[BuilderDiagnostic, ...])

document: PCBHDocument | None
diagnostics: tuple[BuilderDiagnostic, ...]
property ok: bool
pycsamt.format.borehole.new_builder_draft()

Return a JSON-safe empty draft suitable for local browser storage.

Return type:

dict[str, Any]

pycsamt.format.borehole.document_from_builder(draft)

Construct the canonical PCBH object from editable flat tables.

Parameters:

draft (dict[str, Any])

Return type:

PCBHDocument

pycsamt.format.borehole.document_to_builder(document)

Flatten a valid document for editing and browser-session recovery.

Parameters:

document (PCBHDocument)

Return type:

dict[str, Any]

pycsamt.format.borehole.validate_builder(draft)

Validate a draft and return diagnostics mapped to editor rows.

Parameters:

draft (dict[str, Any])

Return type:

BuilderValidation

pycsamt.format.borehole.preview_csv_mapping(data, *, profile=None, max_rows=20)

Return bounded rows, inferred mapping, and diagnostics before import.

Parameters:
  • data (bytes)

  • profile (CSVMappingProfile | None)

  • max_rows (int)

Return type:

dict[str, Any]

class pycsamt.format.borehole.ExportLoss(code, message)

Bases: PyCSAMTObject

One field or semantic category omitted from a view export.

Parameters:
code: str
message: str
class pycsamt.format.borehole.PCBHExportReport(format, boreholes, features, source_crs, target_crs, losses)

Bases: PyCSAMTObject

Summary and explicit losses for a non-canonical export.

Parameters:
  • format (str)

  • boreholes (int)

  • features (int)

  • source_crs (str)

  • target_crs (str | None)

  • losses (tuple[ExportLoss, ...])

format: str
boreholes: int
features: int
source_crs: str
target_crs: str | None
losses: tuple[ExportLoss, ...]
pycsamt.format.borehole.write_geojson(document, path, *, target_crs='EPSG:4326', include_z=True)

Write WGS84 collar Points and trajectory LineStrings as GeoJSON.

Parameters:
  • document (PCBHDocument)

  • path (str | Path)

  • target_crs (str)

  • include_z (bool)

Return type:

tuple[Path, PCBHExportReport]

pycsamt.format.borehole.write_vtp(document, path, *, family='lithology', sides=8)

Write interval tubes as ASCII VTK XML PolyData (.vtp).

Parameters:
  • document (PCBHDocument)

  • path (str | Path)

  • family (str)

  • sides (int)

Return type:

tuple[Path, PCBHExportReport]

pycsamt.format.borehole.write_gltf(document, path, *, family='lithology', sides=8)

Write browser-ready glTF 2.0 (.gltf) or binary GLB tubes.

Parameters:
  • document (PCBHDocument)

  • path (str | Path)

  • family (str)

  • sides (int)

Return type:

tuple[Path, PCBHExportReport]

class pycsamt.format.borehole.ImportIssue(severity, code, message, row=None, column=None)

Bases: PyCSAMTObject

One localized CSV import diagnostic.

Parameters:
  • severity (str)

  • code (str)

  • message (str)

  • row (int | None)

  • column (str | None)

severity: str
code: str
message: str
row: int | None = None
column: str | None = None
class pycsamt.format.borehole.ImportReport(source, source_sha256, delimiter, strict, source_files=<factory>, rows_read=0, rows_accepted=0, rows_skipped=0, rows_rejected=0, column_mapping=<factory>, constants=<factory>, inferred_values=<factory>, unit_conversions=<factory>, conflict_resolutions=<factory>, unresolved_labels=<factory>, issues=<factory>)

Bases: PyCSAMTObject

Structured provenance and diagnostics for one CSV import.

Parameters:
source: str
source_sha256: str
delimiter: str
strict: bool
source_files: dict[str, str]
rows_read: int = 0
rows_accepted: int = 0
rows_skipped: int = 0
rows_rejected: int = 0
column_mapping: dict[str, str]
constants: dict[str, Any]
inferred_values: list[str]
unit_conversions: list[str]
conflict_resolutions: list[str]
unresolved_labels: list[str]
issues: list[ImportIssue]
property errors: tuple[ImportIssue, ...]

Return error diagnostics in source order.

property warnings: tuple[ImportIssue, ...]

Return warning diagnostics in source order.

property ok: bool

Whether the import recorded no errors.

add(severity, code, message, *, row=None, column=None)

Append one localized diagnostic.

Parameters:
  • severity (str)

  • code (str)

  • message (str)

  • row (int | None)

  • column (str | None)

Return type:

None

exception pycsamt.format.borehole.PCBHCSVImportError(report)

Bases: ValueError

Raised when strict CSV import records one or more errors.

Parameters:

report (ImportReport)

pycsamt.format.borehole.boreholes_from_csv(path, *, columns=None, constants=None, strict=True, delimiter=None, document_id=None, created_by='pycsamt CSV importer', max_bytes=10485760, max_rows=250000)

Import a combined collar-and-interval CSV as a PCBH document.

Parameters:
  • path (path-like) – UTF-8 CSV containing repeated collar fields and interval rows.

  • columns (dict, optional) – Explicit {canonical_field: source_header} mapping. Canonical names use dotted paths such as borehole.id and interval.from_md.

  • constants (dict, optional) – Constant canonical values, commonly crs.horizontal. Constants take precedence over mapped row values.

  • strict (bool, default=True) – Raise PCBHCSVImportError if any error is recorded. In permissive mode, invalid rows are rejected and valid rows returned.

  • delimiter ({',', ';', 't', '|'}, optional) – Explicit delimiter. If omitted, detection is restricted to this set.

  • document_id (str, optional) – PCBH document identifier. Defaults to csv:<file stem>.

  • created_by (str, default='pycsamt CSV importer') – Provenance name stored on the document.

  • max_bytes (int, default=10485760) – Maximum source size in bytes.

  • max_rows (int, default=250000) – Maximum number of data rows.

Returns:

  • document (PCBHDocument) – Valid document containing every accepted row.

  • report (ImportReport) – Source checksum, mappings, inferences, counts, and diagnostics.

Raises:
  • PCBHCSVImportError – If the file structure is unusable, no valid boreholes remain, or strict mode records an error. The exception exposes report.

  • ValueError – If a resource limit or delimiter parameter is invalid.

Return type:

tuple[PCBHDocument, ImportReport]

Notes

Missing tokens are normalized before conversion and never stringified. Repeated collar and total-depth values must agree within a borehole.

class pycsamt.format.borehole.RelationalManifest(crs_horizontal, tables, depth_unit='m', resistivity_unit='ohm.m', version='0.1.0')

Bases: PyCSAMTObject

Validated description of a PCBH relational CSV directory.

Parameters:
crs_horizontal: str
tables: dict[str, str]
depth_unit: str = 'm'
resistivity_unit: str = 'ohm.m'
version: str = '0.1.0'
classmethod read(path)

Read a manifest with yaml.safe_load and validate it.

Parameters:

path (str | Path)

Return type:

RelationalManifest

validate()

Validate version, units, table names, and safe relative paths.

Return type:

None

pycsamt.format.borehole.boreholes_from_csv_directory(directory, *, manifest='import.yaml', strict=True, document_id=None, created_by='pycsamt relational CSV importer')

Import joined collar, survey, log, structure, sample, assay tables.

Parameters:
Return type:

tuple[PCBHDocument, ImportReport]

pycsamt.format.borehole.write_csv_directory(document, directory)

Export supported PCBH content as a relational CSV directory.

Parameters:
  • document (PCBHDocument)

  • directory (str | Path)

Return type:

Path

class pycsamt.format.borehole.LASExportReport(path, curves_written=<factory>, losses=<factory>, warnings=<factory>)

Bases: PyCSAMTObject

Preservation and loss summary for a LAS subset export.

Parameters:
path: str
curves_written: list[str]
losses: list[str]
warnings: list[str]
pycsamt.format.borehole.borehole_from_las(path, *, collar, crs_horizontal, kind='unknown', status='unknown', depth_curve='DEPT', resistivity_curve='RESD', lithology_curve='LITH', max_samples=250000)

Import a LAS 2.0 curve subset while retaining curve metadata.

Parameters:
  • path (str | Path)

  • collar (Collar)

  • crs_horizontal (str)

  • kind (str)

  • status (str)

  • depth_curve (str)

  • resistivity_curve (str)

  • lithology_curve (str | None)

  • max_samples (int)

Return type:

tuple[PCBHDocument, ImportReport]

pycsamt.format.borehole.write_las_subset(borehole, path, *, null_value=-9999.25, company='pycsamt')

Write inline PCBH curves, or an interval-derived LAS subset.

Parameters:
  • borehole (PCBHBorehole)

  • path (str | Path)

  • null_value (float)

  • company (str)

Return type:

tuple[Path, LASExportReport]

class pycsamt.format.borehole.DisplayRadiusPolicy(mode='auto', fixed_radius=None, exaggeration=1.0, extent_fraction=0.001, minimum_radius=0.05)

Bases: PyCSAMTObject

View-only borehole radius policy in document coordinate units.

Parameters:
mode: str = 'auto'
fixed_radius: float | None = None
exaggeration: float = 1.0
extent_fraction: float = 0.001
minimum_radius: float = 0.05
resolve(diameter, model_extent)

Resolve display radius without modifying physical diameter.

Parameters:
Return type:

float

class pycsamt.format.borehole.CollarPrimitive(borehole_id, position, label, selected, metadata)

Bases: PyCSAMTObject

Collar marker, label, selection state, and hover metadata.

Parameters:
borehole_id: str
position: tuple[float, float, float]
label: str
selected: bool
metadata: dict[str, Any]
class pycsamt.format.borehole.PolylinePrimitive(borehole_id, points, color, selected, metadata)

Bases: PyCSAMTObject

One borehole centerline in document coordinates.

Parameters:
borehole_id: str
points: tuple[TrajectoryPoint, ...]
color: str
selected: bool
metadata: dict[str, Any]
class pycsamt.format.borehole.IntervalSegmentPrimitive(segment_id, borehole_id, family, from_md, to_md, points, color, display_radius, selected, metadata)

Bases: PyCSAMTObject

Colored portion of a centerline for one logged interval.

Parameters:
segment_id: str
borehole_id: str
family: str
from_md: float
to_md: float
points: tuple[TrajectoryPoint, ...]
color: str
display_radius: float
selected: bool
metadata: dict[str, Any]
class pycsamt.format.borehole.ContactPrimitive(contact_id, borehole_id, family, md, position, tangent, display_radius, left_code, right_code, selected, metadata)

Bases: PyCSAMTObject

Contact-ring input located at an exact shared interval boundary.

Parameters:
contact_id: str
borehole_id: str
family: str
md: float
position: tuple[float, float, float]
tangent: tuple[float, float, float]
display_radius: float
left_code: str | None
right_code: str | None
selected: bool
metadata: dict[str, Any]
class pycsamt.format.borehole.StructureGlyphPrimitive(glyph_id, borehole_id, kind, md, position, borehole_tangent, representation, orientation, display_radius, selected, metadata)

Bases: PyCSAMTObject

Position and orientation inputs for one structural glyph.

Parameters:
glyph_id: str
borehole_id: str
kind: str
md: float
position: tuple[float, float, float]
borehole_tangent: tuple[float, float, float]
representation: str
orientation: dict[str, float]
display_radius: float
selected: bool
metadata: dict[str, Any]
class pycsamt.format.borehole.MaterialBatch(family, color, segment_ids)

Bases: PyCSAMTObject

Stable grouping of segments sharing one family and material color.

Parameters:
family: str
color: str
segment_ids: tuple[str, ...]
class pycsamt.format.borehole.BoreholeRenderModel(borehole_id, collar, centerline, interval_segments, contacts, structure_glyphs, source_checksum, display_radius)

Bases: PyCSAMTObject

Complete viewer-neutral primitives for one borehole.

Parameters:
  • borehole_id (str)

  • collar (CollarPrimitive)

  • centerline (PolylinePrimitive)

  • interval_segments (tuple[IntervalSegmentPrimitive, ...])

  • contacts (tuple[ContactPrimitive, ...])

  • structure_glyphs (tuple[StructureGlyphPrimitive, ...])

  • source_checksum (str)

  • display_radius (float)

borehole_id: str
collar: CollarPrimitive
centerline: PolylinePrimitive
interval_segments: tuple[IntervalSegmentPrimitive, ...]
contacts: tuple[ContactPrimitive, ...]
structure_glyphs: tuple[StructureGlyphPrimitive, ...]
source_checksum: str
display_radius: float
class pycsamt.format.borehole.PCBHRenderModel(document_id, crs_horizontal, coordinate_unit, boreholes, batches, bounds, lod_tolerance, sampling_step_md, max_points_per_hole, radius_policy)

Bases: PyCSAMTObject

Complete render contract for one PCBH document.

Parameters:
document_id: str
crs_horizontal: str
coordinate_unit: str
boreholes: tuple[BoreholeRenderModel, ...]
batches: tuple[MaterialBatch, ...]
bounds: tuple[float, float, float, float, float, float]
lod_tolerance: float
sampling_step_md: float
max_points_per_hole: int
radius_policy: DisplayRadiusPolicy
class pycsamt.format.borehole.BoreholeRenderBuilder

Bases: PyCSAMTObject

Build reusable render primitives while caching scientific paths.

property cache_size: int

Number of geometry checksums currently cached.

clear_cache()

Discard cached desurveyed centerlines.

Return type:

None

build(document, *, family='lithology', selected_ids=None, radius_policy=None, lod_tolerance=0.0, sampling_step_md=10.0, max_points_per_hole=10000)

Build a backend-independent render model for one PCBH document.

Parameters:
  • document (PCBHDocument)

  • family (str)

  • selected_ids (set[str] | None)

  • radius_policy (DisplayRadiusPolicy | None)

  • lod_tolerance (float)

  • sampling_step_md (float)

  • max_points_per_hole (int)

Return type:

PCBHRenderModel

pycsamt.format.borehole.build_render_model(document, *, family='lithology', selected_ids=None, radius_policy=None, lod_tolerance=0.0, sampling_step_md=10.0, max_points_per_hole=10000)

Build a render model with a short-lived builder.

Parameters mirror BoreholeRenderBuilder.build(). Distances are in the document coordinate/depth unit and no CRS transformation is applied.

Parameters:
  • document (PCBHDocument)

  • family (str)

  • selected_ids (set[str] | None)

  • radius_policy (DisplayRadiusPolicy | None)

  • lod_tolerance (float)

  • sampling_step_md (float)

  • max_points_per_hole (int)

Return type:

PCBHRenderModel

pycsamt.format.borehole.deterministic_color(value)

Return a process-independent, readable color for a vocabulary key.

Parameters:

value (str)

Return type:

str

class pycsamt.format.borehole.PCBHReference(uri, sha256)

Bases: PyCSAMTObject

External PCBH URI and integrity checksum.

Parameters:
uri: str
sha256: str
validate()

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

class pycsamt.format.borehole.PCBHAssociation(embedded=None, reference=None)

Bases: PyCSAMTObject

Embedded and/or externally referenced PCBH attachment.

Parameters:
  • embedded (PCBHDocument | None)

  • reference (PCBHReference | None)

embedded: PCBHDocument | None = None
reference: PCBHReference | None = None
validate()

Validate object state.

Subclasses can override this hook. The base implementation intentionally accepts all states.

Return type:

None

class pycsamt.format.borehole.AlignedTrajectoryPoint(md, x, y, z)

Bases: PyCSAMTObject

A trajectory point expressed in PCSF model coordinates.

Parameters:
md: float
x: float
y: float
z: float
class pycsamt.format.borehole.BoreholeBoundsResult(borehole_id, relation, points_inside, points_total)

Bases: PyCSAMTObject

Per-hole relationship with the model bounding box.

Parameters:
  • borehole_id (str)

  • relation (str)

  • points_inside (int)

  • points_total (int)

borehole_id: str
relation: str
points_inside: int
points_total: int
class pycsamt.format.borehole.PCBHAlignmentReport(source_crs, target_crs, vertical_compatible, warnings, model_bounds, trajectories, bounds_results)

Bases: PyCSAMTObject

Aligned paths plus compatibility and bounds diagnostics.

Parameters:
source_crs: str
target_crs: str
vertical_compatible: bool
warnings: tuple[str, ...]
model_bounds: tuple[float, float, float, float, float, float]
trajectories: dict[str, tuple[AlignedTrajectoryPoint, ...]]
bounds_results: tuple[BoreholeBoundsResult, ...]
pycsamt.format.borehole.pcbh_document_checksum(document)

Return SHA-256 of canonical compact PCBH JSON.

Parameters:

document (PCBHDocument)

Return type:

str

pycsamt.format.borehole.embed_pcbh(model, document, *, uri=None)

Return a model copy with a validated portable PCBH attachment.

Parameters:
  • model (PCSFModel)

  • document (PCBHDocument)

  • uri (str | None)

Return type:

PCSFModel

pycsamt.format.borehole.reference_pcbh(model, uri, sha256)

Return a model copy with an external PCBH reference.

Parameters:
Return type:

PCSFModel

pycsamt.format.borehole.extract_pcbh(model)

Return embedded PCBH data without resolving external resources.

Parameters:

model (PCSFModel)

Return type:

PCBHDocument | None

pycsamt.format.borehole.align_pcbh_to_pcsf(document, model, *, vertical_offset=None, sampling_step_md=10.0)

Transform PCBH paths into PCSF x/y/depth coordinates.

vertical_offset is required when PCBH and PCSF vertical references cannot be established as identical. It is added to PCBH elevations before conversion to PCSF depth-positive-down coordinates.

Parameters:
  • document (PCBHDocument)

  • model (PCSFModel)

  • vertical_offset (float | None)

  • sampling_step_md (float)

Return type:

PCBHAlignmentReport