
简介这是一份河海大学水利水电工程专业的水利工程地质野外认识实习报告面向地质学、水利工程相关专业的学生及需要撰写同类实习报告的学习者可用于梳理实习路线、地质现象观察要点与基础技能训练内容。压缩包内为1个doc文档大小约1.86MB完整收录绪言、地质实习内容与结束语等章节并附参考文献目录结构规整便于按章节查阅。报告以汤山湖山、阳山碑材公园、汤山猿人洞、六合瓜埠山及地质博物馆为考察线索详细记录了岩溶地质、沉积岩地层与古生物化石、孔山背斜与火石峰褶皱断层构造、猿人洞碳酸盐岩溶洞及钟乳石、玄武岩柱状节理与火山集块岩等观察内容还包含罗盘测量岩层走向、倾向、倾角的具体操作步骤以及下蜀黄土、浦口组、雨花台组沉积物与河流地质作用的分析。目前已有104人学习适合作为野外实习参考、报告写作范本与工程地质入门复习材料。1. 从野外记录本到「水利工程地质实习报告.doc」卡点从来不在画图两周野外跑坝址、库区、渠道边坡和滑坡点量几十组岩层与节理产状编录钻孔岩芯测地下水位回来要交一份带图带表的 Word 报告。多数人以为最费时间的是画地质剖面图真正拖到交稿前一晚的是记录本上那些自然语言——灰白色中厚层砂岩产状 135∠28节理密集充填方解石——一旦要统计节理优势方位、要按桩号排列剖面、要让正文里的图号和数据对得上就只能人工翻页重抄。把这件事工程化思路和整理一份勘察数据集没有区别先定字段再定编码然后用脚本做产状换算、统计成图最后把数据、图件、文字装配成文档。水利工程地质实习报告里真正难复现的部分是数据口径和换算过程不是排版。适合水利、土木、地质方向的在校生也适合带队老师和做勘察资料归档的工程师。只要能写几十行 Python整份报告的返工率会明显下降。2. 水利工程地质实习记录表怎么设计字段、编码与岩性描述规范野外记录本再详细只要没按字段写回到室内就得重抄一遍。这一步做扎实后面的产状统计、剖面投影、柱状图都只是读同一份 CSV。2.1 野外最容易丢的三类信息第一类是点位身份。同一个滑坡点记录本上写公路拐弯处照片叫 IMG_2043钻孔编录里写 ZK03三套编号互不对应最后对图时没人说得清是哪个点。点位编号必须在现场就写进记录本、照片文件名和样品袋格式统一成线路号-序号例如 K03-07。第二类是产状的方向基准。倾向写 135 却没写是不是磁方位和地形图上的真北方位差几度剖面投影就会偏。记录时统一用真北并在表头注明倾向为真北方位0~359°。第三类是接触关系。地层是整合、平行不整合还是角度不整合界线在哪个点位上观察到这类定性信息一旦漏记剖面图上的界线只能靠猜而界线恰恰是水利工程地质里判断坝基稳定性的关键内容。2.2 一张能直接喂给脚本的点表把记录本上的内容整理成下面这张表列名固定后续所有脚本都读它。字段类型示例必填说明point_id文本K03-07是线路号-序号与照片名对应point_type枚举露头/钻孔/泉/滑坡是控制后续绘图方式lon / lat浮点118.7321 / 32.0615是WGS84 十进制度elev浮点42.6否高程米lithology文本Ss-2是岩性编码见 2.3stratum文本N2是地层代号dip_dir整数135是倾向0~359dip_angle整数28是倾角0~90joint_count整数12否该点实测节理条数photo_no文本IMG_2043否原始照片文件名note文本层面有擦痕否自由描述不做统计结构面节理、断层单独一张表用 point_id 关联一条节理一行这样统计优势方位时不需要再去拆字符串。2.3 岩性编码把灰白色中厚层砂岩压成可统计的字符串主岩类用两字母码颜色和层厚用数字后缀描述词统一从固定词表里选避免灰白浅灰白灰白色三种写法并存。常见对照如下编码岩性编码岩性Ss砂岩Ls石灰岩St粉砂岩Dl白云岩Sh页岩Mb大理岩Gr花岗岩Gn片麻岩Q第四系松散层F断层带颜色用 1~3 表示浅、中、深层厚用 1~3 表示薄层、中厚层、厚层。于是灰白色中厚层砂岩写成Ss-21剖面填色和柱状图花纹都能按前两位字母自动匹配。2.4 用 pandas 做录入校验回到室内第一件事不是画图是校验。下面这段脚本把最常犯的四类错误一次性筛出来。import pandas as pd REQUIRED [point_id, point_type, lon, lat, lithology, stratum, dip_dir, dip_angle] # utf-8-sig 兼容 Excel 另存 CSV 时带上的 BOM df pd.read_csv(field_points.csv, dtype{point_id: str}, encodingutf-8-sig) errors [] for idx, row in df.iterrows(): pid row[point_id] if pd.notna(row[point_id]) else f第{idx 2}行 # 1) 必填字段是否为空 for col in REQUIRED: if pd.isna(row.get(col)): errors.append(f{pid}: 必填字段 {col} 缺失) # 2) 倾角与倾向的取值范围 if pd.notna(row.get(dip_angle)) and not 0 row[dip_angle] 90: errors.append(f{pid}: 倾角 {row[dip_angle]} 超出 0~90) if pd.notna(row.get(dip_dir)) and not 0 row[dip_dir] 360: errors.append(f{pid}: 倾向 {row[dip_dir]} 超出 0~359) # 3) 经纬度包络框按实习区实际范围调整 if pd.notna(row.get(lon)) and not 118.0 row[lon] 119.5: errors.append(f{pid}: 经度 {row[lon]} 不在预设范围内) print(\n.join(errors) if errors else 校验通过) print(f共 {len(df)} 条记录{len(errors)} 个问题)逻辑上分三层先做空值检查因为后面所有数值比较遇到 NaN 都会静默失效再做区间检查倾角 0~90、倾向 0~359 是产状本身的定义域越界基本是手写笔误最后用经纬度包络框兜底能抓出定位时误抄一位数字的点位。参数方面dtype{point_id: str}必须显式指定否则K03-07会被 pandas 当字符串没问题但纯数字编号007会被读成整数 7和照片文件名对不上。包络框的四个数值要按实习区实际情况改不能直接照抄。encodingutf-8-sig是给 Excel 导出的 CSV 兜底纯 UTF-8 文件读它也不会出错。提示校验脚本输出的错误清单建议直接贴回记录本核对改完再跑一次两次都通过才进入统计环节。带错误数据做统计错误会被平均掉肉眼反而看不出来。3. 岩层产状换算与节理统计倾向倾角怎么算视倾角、怎么画玫瑰花图产状数据本身是三个数字但用在报告里要变成视倾角、走向、极点方位、优势方位四种形式每种对应一段换算逻辑。3.1 走向、倾向、倾角三者的换算关系走向是岩层面与水平面的交线方向与倾向垂直所以走向 倾向 − 90结果对 180 取模因为走向有两个方向。倾角是层面与水平面的最大夹角方向沿倾向。这三者的关系决定了报告里凡是写走向 NE30等价于倾向 120°两者不必都列但换算过程要在附录里说明否则评阅时无法复核。视倾角是另一个维度。剖面线方向很少正好垂直于走向画在剖面上的岩层倾角会比真倾角小这个角度叫视倾角。设剖面方向与倾向的夹角为 δ真倾角为 α则tan β tan α × cos δδ 0 时剖面沿倾向切视倾角等于真倾角δ 90° 时剖面沿走向切视倾角为 0剖面上岩层呈水平线。3.2 剖面方向定了视倾角才算得对import numpy as np def apparent_dip(true_dip, dip_dir, section_azimuth): 真倾角换算为视倾角 true_dip: 真倾角度 dip_dir: 倾向度真北起算顺时针 section_azimuth: 剖面线方向度 返回视倾角度 # 剖面方向与倾向的夹角折到 0~180 delta abs(((dip_dir - section_azimuth 180) % 360) - 180) # 夹角超过 90 度时取补角余弦值相同结果不受影响 return np.rad2deg(np.arctan(np.tan(np.deg2rad(true_dip)) * np.cos(np.deg2rad(delta)))) # 示例倾向 135真倾角 28剖面方向 90东西向 print(round(apparent_dip(28, 135, 90), 1)) # 约 20.2关键在delta的计算。((x 180) % 360) - 180是标准的角度归一化写法把任意角度折到 −180~180再取绝对值得到 0~180 的夹角。剖面方向与倾向夹角超过 90° 时余弦取负但视倾角只关心大小实际制图时按地层倾向的相对关系决定画在哪一侧所以这里不做符号处理。剖面方向的选择有个经验原则坝址、隧洞这类线性工程剖面线沿建筑物轴线方向布算出该方向的视倾角直接填图区域地质剖面则尽量垂直于主要构造线走向让 δ 接近 0视倾角接近真倾角图面看起来更直观。3.3 节理玫瑰花图每 10 度一个扇区的分箱节理统计的输入是逐条产状输出是一张玫瑰花图加一组优势方位数字。走向在 0~180° 内对称所以统计走向比统计倾向更省事180° 的分布折到 90° 范围里画。import numpy as np import pandas as pd import matplotlib.pyplot as plt joints pd.read_csv(joints.csv) # 列point_id, dip_dir, dip_angle strike (joints[dip_dir] 90) % 180 # 倾向转走向取 0~180 counts, _ np.histogram(strike, binsnp.arange(0, 181, 10)) # 18 个 10 度区间 half counts[:9] counts[9:][::-1] # 0~90 与 90~180 镜像相加 angles np.deg2rad(np.arange(5, 95, 10)) # 9 个扇区中心角 fig plt.figure(figsize(4, 4)) ax fig.add_subplot(111, projectionpolar) ax.set_theta_zero_location(N) # 0 度朝北 ax.set_theta_direction(-1) # 顺时针为正 ax.bar(angles, half, widthnp.deg2rad(10), color#8ab4d8, edgecolork, linewidth0.4) fig.savefig(joint_rose.png, dpi300, bbox_inchestight)np.histogram返回每 10° 区间的条数half把第 i 个区间和第 17−i 个区间相加得到的 9 个值对应 0~10°、10~20°……80~90°。set_theta_zero_location(N)加set_theta_direction(-1)是地质图的常规朝向正北在上、顺时针增角跟产状记录习惯一致。扇区中心角取 5、15、……85 是为了让柱体居中偏移半格画出来的图更规整。3.4 极点方位与优势组数的判断节理分组的通常做法是把每组产状换成极点再按极点方位分箱找峰值。极点的方位换算很直接极点倾向 倾向 180°极点倾伏角 90° − 倾角。输出项计算方式报告里的用途极点倾向(dip_dir 180) % 360极点图与等密度图坐标极点倾伏角90 − dip_angle判断结构面陡缓优势倾向同一组内倾向的圆均值描述主要结构面方位优势倾角同一组内倾角的算术均值边坡与坝基稳定性评价组数极点方位分箱后的峰值个数判断有几组控制性结构面倾向是角度数据取均值不能直接算算术平均135° 和 345° 的算术平均是 240°实际它们只差 30°。正确做法是转成单位向量求分量平均再反算角度np.rad2deg(np.arctan2(np.mean(np.sin(np.deg2rad(d)), np.mean(np.cos(np.deg2rad(d))))))结果再归一化到 0~359。注意极点等密度图如果用手写核函数带宽选得太大所有点会糊成一团选得太小只剩孤立峰值。一般按每个点覆盖 10~15° 范围内其他点来累加具体数值用几组已知分组的数据回测一下再定。4. 地质剖面图和钻孔柱状图的自动绘制报告里的图分两类沿剖面线的地质剖面图和单孔的钻孔柱状图。两者都是输入一维数据、输出二维图形用 matplotlib 画完直接存 PNG交给文档装配环节引用。4.1 剖面线怎么定投影才不出错剖面图有三个坐标系要统一沿剖面线的水平距离桩号、高程、地层界线。定剖面线时先在地形图上量出起点和终点的坐标算出方位角这个方位角就是 3.2 节里算视倾角用的section_azimuth。所有地表点和钻孔位置都垂直投影到这条线上投影后的桩号作为横坐标。投影时注意投影带宽度。剖面线两侧 50~100 米内的点通常可以垂直投影进图超出这个范围的点投进来会让图面严重失真应该单独出一条辅助剖面。投影带宽度按图件比例尺定1:2000 的剖面一般取 50 米。4.2 用 matplotlib 画地形线与地层界线import numpy as np import matplotlib.pyplot as plt # 沿剖面桩号与地面高程来自地形图切剖面或实测点 x np.array([0, 50, 120, 200, 280, 360, 440]) ground np.array([42.5, 44.1, 46.8, 45.2, 41.0, 38.6, 39.4]) # 地层界线的高程控制点每个代号一条折线视倾角换算后按桩号展开 boundaries { N2: np.array([35.0, 36.2, 37.4, 36.0, 32.5, 30.0, 30.8]), E1: np.array([28.0, 29.0, 30.1, 29.2, 26.0, 23.5, 24.0]), } fig, ax plt.subplots(figsize(9, 4)) ax.plot(x, ground, colork, lw1.2, label地面线) for name, y in boundaries.items(): ax.plot(x, y, color#5a5a5a, lw0.8, ls--, labelf界线 {name}) # 按地层自上而下填色颜色与 2.3 节的岩性编码对应 layers [(Q 第四系, ground, boundaries[N2], #e8dfc8), (N2 砂岩, boundaries[N2], boundaries[E1], #c9b98f), (E1 泥岩, boundaries[E1], np.full_like(x, 20.0), #a9b0c0)] for name, top, bot, color in layers: ax.fill_between(x, bot, top, colorcolor, edgecolor#444, lw0.5, labelname) ax.set_xlabel(沿剖面桩号 / m) ax.set_ylabel(高程 / m) ax.set_aspect(equal) # 保证水平与垂直比例尺一致 ax.legend(locupper right, fontsize8, framealpha0.9) fig.savefig(profile_A-A.png, dpi300, bbox_inchestight)set_aspect(equal)是剖面图的硬要求比例尺失真会让倾角看起来不对评阅时一眼就能发现。填色顺序必须自上而下先画最上层再画下面否则下层会把上层覆盖掉。boundaries里的高程值应当由实测界线点在剖面上的投影高程得到而不是为了图面好看随手改的数。4.3 钻孔柱状图与岩性花纹柱状图是逐层画矩形深度向下递增所以纵轴取负值。import matplotlib.pyplot as plt # (顶深, 底深, 岩性名称, 填充色)深度单位 m hole [(0.0, 2.4, 第四系松散层, #e8dfc8), (2.4, 8.6, N2 砂岩, #c9b98f), (8.6, 15.0, E1 泥岩, #a9b0c0), (15.0, 22.3, E1 泥岩夹石膏, #8fa8c0)] fig, ax plt.subplots(figsize(2.6, 7)) for top, bot, name, color in hole: ax.add_patch(plt.Rectangle((0, -bot), 1, bot - top, facecolorcolor, edgecolork, lw0.6)) ax.text(1.1, -(top bot) / 2, name, vacenter, fontsize8) ax.set_ylim(-24, 1) ax.set_xlim(0, 3.2) ax.set_ylabel(孔深 / m) ax.axis(off) fig.savefig(borehole_ZK03.png, dpi300, bbox_inchestight)矩形左下角坐标写(0, -bot)高度写bot - top这是向下生长的画法。岩性名称文字放在矩形右侧纵坐标取层中点。柱状图一般不需要坐标轴axis(off)关掉更接近印刷样式但孔深刻度要另画一条标尺实际交付时按报告模板补。岩性填充色建议全篇统一成一张表剖面图和柱状图共用避免同一层砂岩在两张图里颜色不一样。岩性编码填充色花纹建议Q#e8dfc8点纹Ss#c9b98f细点加点线Sh#a9b0c0密集水平线Ls#b8d0e0砖块纹F#d08a8a粗斜线4.4 出图参数中文字体、DPI 和图幅matplotlib 默认字体不含中文图上的高程桩号会显示成方框。开始画图前统一设置import matplotlib # 按系统已装字体依次回退Linux 与 Windows 通用写法 matplotlib.rcParams[font.sans-serif] [SimHei, Noto Sans CJK SC, Microsoft YaHei] matplotlib.rcParams[axes.unicode_minus] False # 负号正常显示axes.unicode_minus关掉是必须的否则纵轴负深度会变成方框。DPI 设 300 是印刷可接受的下限图幅宽度按报告正文宽度给A4 页面去掉页边距后正文宽约 15.9 厘米出图时figsize的宽度乘 2.54 后不要超过这个值插入 Word 后就不用再缩放。提示图件文件名里的撇号如profile_A-A.png在部分命令行环境下会被 shell 截断转 doc 之前先重命名成profile_A_A.png这类纯 ASCII 名字能省掉一批莫名其妙的报错。5. 用 python-docx 装配报告并做交付前校验数据、图、统计表齐了最后一步是把它们塞进 Word 模板。这一步能自动化的部分比想象中多。5.1 模板占位符替换的坑在 Word 里做好report_template.docx需要填内容的地方写{{TITLE}}、{{DATE}}、{{POINT_COUNT}}这类标记。from docx import Document from docx.shared import Cm doc Document(report_template.docx) replace_map {{{TITLE}}: 水利工程地质实习报告, {{DATE}}: 2024-07, {{POINT_COUNT}}: str(len(df))} # 占位符可能被 Word 拆进多个 run按段落整体判断后重写 for p in doc.paragraphs: if any(k in p.text for k in replace_map): text p.text for k, v in replace_map.items(): text text.replace(k, v) for i, run in enumerate(p.runs): run.text text if i 0 else # 内容压到第一个 run doc.add_picture(profile_A_A.png, widthCm(15.9)) doc.save(水利工程地质实习报告.docx)只对单个 run 做replace是常见的失败点Word 在拼写检查或格式变化时会静默拆分 run{{TITLE}}可能变成{{TITLE}}两个 run逐个替换永远匹配不上。稳妥做法是取整段文本替换后写回第一个 run其余 run 清空段落的样式和字体由模板控制不受影响。add_picture的width用Cm(15.9)和 4.4 节的出图宽度对齐图就不会被自动缩放线宽和字号才保得住。5.2 交付格式与一致性检查标题写的是.doc而 python-docx 只能输出 docx。需要真.doc时用 LibreOffice 命令行转换比手工另存可靠soffice --headless --convert-to doc --outdir out/ 水利工程地质实习报告.docx转换前先跑一遍一致性检查正文里提到的点名是否都在点表里、图号顺序是否与add_picture的调用顺序一致、统计表里的节理总条数是否等于joints.csv的行数、剖面图桩号范围是否覆盖正文描述的所有点位。这几项用 pandas 和正则各写十几行就能自动比对比通读一遍全文快得多而且能抓住图 3-2 说倾向 135、正文写 130这类只有逐字比对才会发现的矛盾。最后一项技巧是把整套流程固化成三个脚本01_check.py校验录入数据02_plot.py生成全部图件03_build_docx.py装配文档。数据一改从第二行命令开始重跑三分钟出新的 doc带队老师让你补两个点位的产状时你只需要在 CSV 里加两行。本文还有配套的精品资源点击获取