数据库操作
dimine_python_sdk.lib.prospecting 模块提供对 Dimine 钻孔数据库(.dmd)的原生访问能力,无需启动 Dimine GUI 即可读取和处理数据。
前置条件:
- 环境变量 DIMINE_HOME 指向包含 DmPyBindInterface.pyd 的目录
- Python >= 3.12
模块定位
SDK 的数据处理层模块:
| 模块 | 用途 | 典型类 |
|---|---|---|
lib.prospecting |
钻孔数据库、块模型操作与储量估算 | DrillDBManager、BlockModelEvaluator、DmBlockData |
lib.io |
DMF/DMG/DMT 文件读写 | DmfFile、DmgFile、DmtFile |
models |
对外 Pydantic 纯数据模型 | Point、Line、Shell |
本文档覆盖 lib.prospecting 中的钻孔数据库操作。DMF 文件处理请参考 IO操作 和 文件格式转换。
一、钻孔数据库操作
dimine_python_sdk.lib.prospecting 提供对 Dimine 钻孔数据库(.dmd)的专用访问能力。钻孔数据库包含四大核心表:孔口表、测斜表、岩性表、样品表,API 统一返回 pandas.DataFrame,列名均为中文标准格式,与 Python 数据科学生态无缝衔接。
列名规范:写入时 DataFrame 的列名必须使用中文标准列名;读取时返回的列名也为中文标准格式。
前置导入:
from dimine_python_sdk.lib.prospecting import DrillDBManager, drill_conn
from dimine_python_sdk.lib.prospecting import (
DrillDBError,
DrillDBLoadError,
DrillDBProcessError,
)
1.1 加载与创建
从文件加载
from dimine_python_sdk.lib.prospecting import DrillDBManager
# 加载钻孔数据库
db = DrillDBManager("C:/Projects/Mine/钻孔数据.dmd")
# 支持相对路径
db = DrillDBManager("钻孔数据.dmd", base_path="C:/Projects/Mine")
创建空对象(从 DataFrame 写入)
初始化时不传路径,可以创建一个空白钻孔数据库对象,通过赋值 DataFrame 后再保存:
import pandas as pd
from dimine_python_sdk.lib.prospecting import DrillDBManager
db = DrillDBManager()
# 准备 DataFrame(必须使用中文标准列名)
df_collar = pd.DataFrame({
"工程号": ["ZK001", "ZK002"],
"横坐标": [100.0, 200.0],
"纵坐标": [300.0, 400.0],
"高程": [500.0, 550.0],
"总深度": [100.0, 120.0],
"勘探线": ["L1", "L2"],
})
# 赋值到数据库
db.collar = df_collar
# 保存到文件
db.save("C:/Projects/Mine/新钻孔数据.dmd")
显式加载方法
也可以在创建空对象后,通过 load() 方法加载文件:
db = DrillDBManager()
db.load("C:/Projects/Mine/钻孔数据.dmd")
print(db.collar.head())
使用上下文管理器(推荐)
使用 drill_conn 可确保资源自动释放,避免内存泄漏。支持传文件路径或创建空对象:
from dimine_python_sdk.lib.prospecting import drill_conn
# 从文件加载
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
print(db.collar.head())
# 离开 with 块后自动释放资源
# 创建空对象,赋值后保存
with drill_conn() as db:
db.collar = df_collar
db.save("C:/Projects/Mine/新钻孔数据.dmd")
1.2 访问钻孔数据表
钻孔数据库包含四大核心表,通过属性即可访问,返回类型均为 pandas.DataFrame:
| 属性 | 说明 | 返回类型 |
|---|---|---|
db.collar |
孔口表(钻孔基本信息:孔号、坐标、深度等) | pd.DataFrame |
db.survey |
测斜表(钻孔轨迹测斜数据) | pd.DataFrame |
db.lithology |
岩性表(钻孔岩性分层信息) | pd.DataFrame |
db.sample |
样品表(化验样品数据) | pd.DataFrame |
from dimine_python_sdk.lib.prospecting import drill_conn
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
# 访问四大表(均为 pd.DataFrame)
collar = db.collar # 孔口表
survey = db.survey # 测斜表
lithology = db.lithology # 岩性表
sample = db.sample # 样品表
# 也可以使用 dict 风格访问
collar = db["collar"]
survey = db["survey"]
lithology = db["lithology"]
sample = db["sample"]
print(f"孔口表记录数: {len(collar)}")
print(f"测斜表记录数: {len(survey)}")
print(f"岩性表记录数: {len(lithology)}")
print(f"样品表记录数: {len(sample)}")
DataFrame 操作示例
由于返回的是 pd.DataFrame,可直接使用 pandas 原生操作:
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
# 获取所有钻孔孔号(Series)
hole_ids = db.collar["工程号"]
print(f"钻孔数量: {len(hole_ids)}")
# 查看第一条孔口记录(Series)
row = db.collar.iloc[0]
print(row["工程号"], row["总深度"])
# 获取前5条
print(db.collar.head(5))
# 字段名列表(均为中文标准列名)
print(db.collar.columns.tolist())
# 条件筛选
deep_holes = db.collar[db.collar["总深度"] > 500]
print(f"深孔数量: {len(deep_holes)}")
通过 setter 修改数据表
可以将修改后的 DataFrame 赋值回数据库:
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
# 读取
df = db.collar.copy()
# 修改(保持中文标准列名)
df["总深度"] = df["总深度"] * 1.1
# 写回(仅更新内存缓存)
db.collar = df
# 保存(写入 .dmt 子表 + .dmd 引用)
db.save()
1.3 标准列名映射规范
DrillDBManager 对四大表的 DataFrame 列名有严格的格式要求。写入时必须使用中文标准列名;读取时返回中文标准列名。
孔口表(db.collar)
| 中文列名(输入) | 英文列名(存储) | 说明 | 必选 |
|---|---|---|---|
工程号 |
BHID |
钻孔唯一标识 | 是 |
横坐标 |
EAST |
X 坐标 | 是 |
纵坐标 |
NOTRH |
Y 坐标 | 是 |
高程 |
ELEVATION |
Z 高程 | 是 |
总深度 |
TOTALDEPTH |
钻孔总深度 | 是 |
勘探线 |
SECTION |
所属勘探线 | 是 |
工程类型 |
工程类型 |
工程类型 | 否 |
其他 |
OTHERFIELDS |
其他扩展字段 | 否 |
from dimine_python_sdk.lib.prospecting import DrillDBManager
# 通过类属性查看完整映射
print(DrillDBManager.COLLAR_COLUMN_MAP)
# {'工程号': 'BHID', '横坐标': 'EAST', ...}
测斜表(db.survey)
| 中文列名(输入) | 英文列名(存储) | 说明 |
|---|---|---|
工程号 |
SURBHID |
钻孔编号 |
测斜深度 |
SDEPTH |
测斜深度 |
方位角 |
AZIMUTH |
方位角 |
倾角 |
DIP |
倾角 |
岩性表(db.lithology)
| 中文列名(输入) | 英文列名(存储) | 说明 |
|---|---|---|
工程号 |
LITHBHID |
钻孔编号 |
起始 |
LITHFROM |
起始深度 |
结束 |
LITHTO |
结束深度 |
岩性编号 |
ROCK-TYPE |
岩性编号 |
样品表(db.sample)
| 中文列名(输入) | 英文列名(存储) | 说明 |
|---|---|---|
工程号 |
SAMBHID |
工程编号 |
样本编号 |
SAMPLE-ID |
样品编号 |
起始 |
SAMFROM |
样品起始深度 |
结束 |
SAMTO |
样品结束深度 |
样品表除上述必选标准列外,还支持附加任意数量元素品位列(如
CU、TFE、AU、AG等)。这些非标准列会写入_sample.dmt子表文件,但不会出现在.dmd引用映射中。
# 通过类属性查看完整映射
print(DrillDBManager.SAMPLE_COLUMN_MAP)
# {'工程号': 'SAMBHID', '样本编号': 'SAMPLE-ID', ...}
列名校验规则
写入时对 DataFrame 列名进行两级校验:
| 校验层级 | 规则 | 不满足时的行为 |
|---|---|---|
| 必选标准列 | 映射字典中标记为必选的列必须全部存在 | 抛出 DrillDBError,提示缺少的列 |
| 非标准列 | 不在映射字典中的额外列(如元素品位 CU、TFE 等)不会被拒绝 |
记录 debug 日志,列会写入 .dmt 子表但不出现于 .dmd 映射 |
各表必选标准列:
| 表 | 必选列 |
|---|---|
| 孔口表 | 工程号、横坐标、纵坐标、高程、总深度、勘探线 |
| 测斜表 | 工程号、测斜深度、方位角、倾角 |
| 岩性表 | 工程号、起始、结束、岩性编号 |
| 样品表 | 工程号、样本编号、起始、结束 |
- 孔口表的
工程类型、其他为可选标准列,缺失不会报错 - 读取时,只保留映射字典中定义的列,多余列自动过滤;标准列按定义顺序排列,额外列保留在后
import pandas as pd
from dimine_python_sdk.lib.prospecting import DrillDBManager
db = DrillDBManager()
# 正确:包含所有必选标准列 + 非标准列(元素品位)
db.sample = pd.DataFrame({
"工程号": ["ZK001", "ZK001"],
"样本编号": ["S001", "S002"],
"起始": [0.0, 50.0],
"结束": [50.0, 100.0],
"CU": [0.35, 0.42], # 非标准列,写入 .dmt 但不映射到 .dmd
"AU": [1.2, 0.8],
"AG": [5.0, 3.2],
})
# 正确:孔口表可选列 '其他' 可以省略
db.collar = pd.DataFrame({
"工程号": ["ZK001"],
"横坐标": [100.0],
"纵坐标": [200.0],
"高程": [50.0],
"总深度": [150.0],
"勘探线": ["L1"],
})
# 错误:缺少必选标准列
db.collar = pd.DataFrame({"工程号": ["ZK001"], "depth": [100.0]})
# DrillDBError: 孔口表 缺少必选标准列: ['横坐标', '纵坐标', '高程', '总深度', '勘探线']
1.4 保存与重新加载
from dimine_python_sdk.lib.prospecting import DrillDBManager
db = DrillDBManager("C:/Projects/Mine/钻孔数据.dmd")
# 修改后保存(覆盖原文件)
db.save()
# 另存为新文件
db.save("C:/Projects/Mine/钻孔数据备份.dmd")
# 重新加载文件(清空缓存)
db.reload()
# 释放资源
db.close()
空对象调用
save()不指定路径会抛出DrillDBError,必须传入output_path。
1.5 钻孔数据处理
钻孔数据库模块提供三种常用数据处理方法,均通过 Pydantic 参数模型传入。
样长组合
将不等长样品按指定长度重新组合:
from dimine_python_sdk.lib.prospecting import drill_conn
from dimine_python_sdk.lib.prospecting.models import SampleLengthCombineParam
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
params = SampleLengthCombineParam(
input_file="C:/Projects/Mine/样品数据.dmg",
combine_length=1.0, # 组合长度 1m
combine_percent=0.75, # 组合百分比 75%(默认值)
# output_file 可省略,自动生成为 样品数据_combined.dmg
)
result = db.process_samples(params)
print(f"处理结果: {result}")
参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
input_file |
str | (必选) | 输入样品数据文件路径 |
combine_length |
float | 1.0 | 组合长度(m),必须 > 0 |
combine_percent |
float | 0.75 | 组合百分比,0-1 之间(传给 C++ 前自动 ×100 取整) |
output_file |
str | {input}_combined.dmg |
输出文件路径(未设置时自动从输入文件名推导) |
台阶组合
按台阶高程对样品数据进行组合:
from dimine_python_sdk.lib.prospecting import drill_conn
from dimine_python_sdk.lib.prospecting.models import StepCombineParam
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
params = StepCombineParam(
input_file="C:/Projects/Mine/样品数据.dmg",
step_height=2.0, # 台阶高度(默认 2m)
start_height=0.0, # 起始高程
end_height=100.0, # 结束高程
# calculate_model 默认 1(长度加权平均)
# low_dip 默认 0.0
# output_file 可省略,自动生成为 样品数据_step.dmg
)
result = db.process_steps(params)
print(f"处理结果: {result}")
参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
input_file |
str | (必选) | 输入 dmg 文件路径 |
step_height |
float | 2.0 | 台阶高度 |
start_height |
float | (必选) | 起始高程 |
end_height |
float | (必选) | 结束高程 |
calculate_model |
int | 1 | 计算方式:0=算术平均,1=长度加权平均 |
low_dip |
float | 0.0 | 忽略的最小倾角,即忽略倾角 ≤ ±该值的钻孔 |
output_file |
str | {input}_step.dmg |
输出文件路径(未设置时自动从输入文件名推导) |
特高品位处理
对超过阈值的特高品位样品进行处理:
from dimine_python_sdk.lib.prospecting import drill_conn
from dimine_python_sdk.lib.prospecting.models import HighGradeProcessParam
with drill_conn("C:/Projects/Mine/钻孔数据.dmd") as db:
params = HighGradeProcessParam(
input_file="C:/Projects/Mine/样品数据.dmg",
grade_field="Cu", # 品位字段
process_mode=0, # 0:国内标准
average_multiple=6, # 平均值倍数
frequency=0.95, # 累积频率阈值
replace_method=2, # 2:相邻样品平均值
assign_value=2.5, # 替换给定值
result_field="Cu_processed", # 结果字段名
)
result = db.process_high_grade(params)
print(f"处理结果: {result}")
参数说明:
| 参数 | 类型 | 默认值 | 说明 |
|---|---|---|---|
input_file |
str | (必选) | 输入 dmg 文件路径 |
grade_field |
str | (必选) | 品位字段名(如 Cu、Au) |
process_mode |
int | 0 | 处理模式:0=国内标准,1=国外标准 |
average_multiple |
int | 6 | 平均值倍数(仅 6/7/8) |
frequency |
float | 0.95 | 累积频率阈值,0-1 之间 |
replace_method |
int | 2 | 替换方式(见下表) |
assign_value |
float | 0.0 | 给定值(replace_method=1 时生效) |
adjoin_average |
float | 2 | 相邻样品平均值 |
average_method |
int | 1 | 平均值计算方式:0=算数平均,1=长度加权平均 |
contain_mode |
int | 0 | 包含模式:0=包含特高品位,1=不包含 |
result_field |
str | {grade_field}_processed |
结果字段名(未设置时默认为品位字段名 + "_processed") |
replace_method 枚举:
| 值 | 说明 |
|---|---|
| 0 | 剔除法 |
| 1 | 给定值 |
| 2 | 相邻样品平均值 |
| 3 | 矿体平均品位法 |
| 4 | 单一工程法 |
| 5 | 截止品位法 |
1.6 异常处理
from dimine_python_sdk.lib.prospecting import drill_conn
from dimine_python_sdk.lib.prospecting import (
DrillDBError,
DrillDBLoadError,
DrillDBProcessError,
)
try:
with drill_conn("不存在的文件.dmd") as db:
print(db.collar.head())
except DrillDBLoadError as e:
print(f"加载失败: {e}")
# 处理异常
try:
from dimine_python_sdk.lib.prospecting.models import SampleLengthCombineParam
params = SampleLengthCombineParam(
input_file="无效路径.dmf",
combine_length=1.0,
output_file="输出.dmf",
)
result = db.process_samples(params)
except DrillDBProcessError as e:
print(f"处理失败: {e}")
print(f"原始响应: {e.response}")
except DrillDBError as e:
print(f"数据库错误: {e}")
二、完整示例
示例一:读取并分析已有钻孔数据库
from dimine_python_sdk.lib.prospecting import drill_conn
from dimine_python_sdk.lib.prospecting.models import SampleLengthCombineParam
def main():
file_path = "C:/Projects/Mine/钻孔数据.dmd"
with drill_conn(file_path) as db:
# 1. 打印数据库概况
print("=" * 40)
print("钻孔数据库概况")
print("=" * 40)
print(f"文件路径: {db.file_path}")
print(f"孔口表记录数: {len(db.collar)}")
# 2. 查看孔口表结构
print("\n" + "=" * 40)
print("孔口表信息")
print("=" * 40)
print(f"字段: {db.collar.columns.tolist()}")
print(f"记录数: {len(db.collar)}")
# 3. 查看前3条孔口记录
print("\n前3条孔口记录:")
print(db.collar.head(3))
# 4. 提取所有孔号
hole_ids = db.collar["工程号"]
print(f"\n所有钻孔: {hole_ids.tolist()}")
# 5. pandas 分析
print(f"\npandas DataFrame 形状: {db.collar.shape}")
print(db.collar.describe())
# 6. 样长组合示例
print("\n" + "=" * 40)
print("样长组合处理")
print("=" * 40)
params = SampleLengthCombineParam(
input_file="C:/Projects/Mine/样品数据.dmf",
combine_length=1.0,
combine_percent=1.0,
output_file="C:/Projects/Mine/组合后样品.dmf",
)
result = db.process_samples(params)
print(f"处理结果: {result}")
if __name__ == "__main__":
main()
示例二:从 DataFrame 创建新的钻孔数据库
import pandas as pd
from dimine_python_sdk.lib.prospecting import DrillDBManager
def create_drill_db():
# 1. 创建空对象
db = DrillDBManager()
# 2. 准备孔口表
df_collar = pd.DataFrame({
"工程号": ["ZK001", "ZK002", "ZK003"],
"横坐标": [100.0, 200.0, 300.0],
"纵坐标": [400.0, 500.0, 600.0],
"高程": [700.0, 750.0, 800.0],
"总深度": [150.0, 200.0, 180.0],
"勘探线": ["L1", "L2", "L3"],
"其他": ["备注1", "备注2", "备注3"],
})
# 3. 准备测斜表
df_survey = pd.DataFrame({
"工程号": ["ZK001", "ZK001", "ZK002", "ZK002"],
"测斜深度": [0.0, 50.0, 0.0, 80.0],
"方位角": [30.0, 32.0, 45.0, 47.0],
"倾角": [-60.0, -62.0, -55.0, -58.0],
})
# 4. 准备岩性表
df_lithology = pd.DataFrame({
"工程号": ["ZK001", "ZK001", "ZK002"],
"起始": [0.0, 50.0, 0.0],
"结束": [50.0, 150.0, 200.0],
"岩性编号": ["花岗岩", "砂岩", "页岩"],
})
# 5. 准备样品表(可选;除标准列外可附加元素品位等非标准列)
df_sample = pd.DataFrame({
"工程号": ["ZK001", "ZK001", "ZK002"],
"样本编号": ["S001", "S002", "S003"],
"起始": [0.0, 50.0, 0.0],
"结束": [50.0, 100.0, 80.0],
"CU": [0.35, 0.42, 0.28], # 非标准列:铜品位
"AU": [1.2, 0.8, 2.1], # 非标准列:金品位
})
# 6. 赋值到数据库
db.collar = df_collar
db.survey = df_survey
db.lithology = df_lithology
db.sample = df_sample
# 7. 保存
db.save("C:/Projects/Mine/新钻孔数据.dmd")
print("数据库已保存")
if __name__ == "__main__":
create_drill_db()
示例三:从 CSV 导入数据并保存为钻孔数据库
从外部系统导出的 CSV 文件,通过列名映射转换为标准格式后,可直接保存为 .dmd 钻孔数据库,在 Dimine 中打开使用。
完整代码见 examples/import_csv_to_drill_db.md,核心步骤如下:
import pandas as pd
from dimine_python_sdk.lib.prospecting import DrillDBManager
# 1. 读取外部 CSV,映射为中文标准列名
df_collar = pd.read_csv("raw_collar.csv").rename(columns={
"HoleID": "工程号",
"X": "横坐标",
"Y": "纵坐标",
"Z": "高程",
"Depth": "总深度",
"Line": "勘探线",
})
# 2. 同理导入测斜表、岩性表
df_survey = pd.read_csv("raw_survey.csv").rename(columns={
"HoleID": "工程号",
"Depth": "测斜深度",
"Azimuth": "方位角",
"Dip": "倾角",
})
df_lithology = pd.read_csv("raw_lithology.csv").rename(columns={
"HoleID": "工程号",
"From": "起始",
"To": "结束",
"Rock": "岩性编号",
})
# 3. 赋值并保存
db = DrillDBManager()
db.collar = df_collar
db.survey = df_survey
db.lithology = df_lithology
db.save("钻孔数据.dmd")
print("已保存为钻孔数据库,可在 Dimine 中直接打开")
后续步骤:钻孔数据库准备好后,可进入 储量估算 流程—— 样品组合 → 特高品位处理 → 创建块段模型 → 搜索椭球体参数计算 → 估值 → 储量计算。