光电效应及普朗克常数的测定数据处理 Python实现

内容仅供参考,如有错误,欢迎指正,如有疑问,欢迎交流。 

因为我不会Excel所以只能用Python来处理

祝大家早日摆脱物理实验的苦海

用到的一些方法

PCHIP (分段三次埃尔米特插值多项式)

因为实验时记录的数据比较少,记录的也比较随便,直接将这些数据连起来的话画出的图像十分的直,而伏安特性曲线顾名思义应该是一条曲线,因此我们需要进行数据拟合,但是呢我们发现直接进行数据拟合会出现下面的情况,即在某些区间内,电压上升电流反而下降了,这很不合理,所以我让AI帮我想到了PCHIP插值法进行数据点的扩展,具体是啥我也不知道,反正用就完了

利用导数找拐点

看了示范报告,一开始把零点当成拐点算了,爆炸了

找拐点的方法我试了好多种,二阶导等于零、一阶导的极值、一阶导作差、一阶导和各种阈值比较等等,最后我用的是区间斜率与整体斜率的比较,也算是一阶导和阈值比较的一种吧。

这些方法的核心思想都是在伏安特性曲线上找到电流变化陡峭的拐点,并将其对应的电压作为截止电压,关键是怎样才算陡峭。本文用到的方法中,先计算电流随电压的平均变化率(即平均斜率),作为基准值 threshold =(I_max - I_min) / (U_max - U_min),随后遍历所有插值后的数据点,利用五点差分法计算其局部斜率,如果这个局部斜率是基准斜率的1.5倍,就将其认为是拐点,记录并退出循环。但是因为找到了第一个就退出循环了并且“1.5倍”不一定是每组数据的最佳选择,所以结果可能会出现较大误差。

threshold = (max(y_dense) - min(y_dense)) / (x_max - x_min)  # 导数阈值for i in range(nums_data):if (y_dense[i + 5] - y_dense[i]) / (x_dense[i + 5] - x_dense[i]) > threshold * 1.5:cutoff_voltage = x_dense[i]break

代码

import openpyxl
import matplotlib.pyplot as plt
import numpy as np
import os
from matplotlib.ticker import FormatStrFormatter
from scipy.interpolate import PchipInterpolator
from docx import Document
from docx.shared import Inches# 设置支持中文的字体和正常显示负号
plt.rcParams['font.sans-serif'] = ['SimHei']  # 或者 ['Microsoft YaHei']
plt.rcParams['axes.unicode_minus'] = False# ------------------------------------------控制台--------------------------------------------------
N = 5  # 数据组数cutoff_voltages = [] # 截止电压 (V)
calculate = 1 # 数据计算+图片输出
save_to_word = 0 # 将图片保存到 Word 文档output_dir = r"C:\Users\86138\Desktop\这是文件夹\这是文件夹里的文件夹" # 指定图片保存目录
excel_file = r"C:\Users\86138\Desktop\这是文件夹\这是xlsx.xlsx"  # Excel 文件路径 (用于加载原始数据和储存计算后的数据)
word_file = r"C:\Users\86138\Desktop\这是文件夹\这是docx.docx"  # Word 文件路径(用于读取图片并保存)# --------------------------------------------------------------------------------------------------auto = 0 if cutoff_voltages else 1
os.makedirs(output_dir, exist_ok=True)  # 确保目标文件夹存在def Htlang():# 物理常数c = 3.0e8  # 光速,单位 m/s# 1. 加载 Excel 文件wb = openpyxl.load_workbook(excel_file)sheet = wb.active# 2. 确定数据组的行间隔(第一组从第 1 行开始,每组占 2 行)group_start_rows = [1 + i * 2 for i in range(N)]  # 生成 [1, 3, 5, 7, 9]# 3. 存储所有数据以便后续绘图wavelengths = []     # 波长 (nm)frequencies = []     # 频率 (10^-14 Hz)# 4. 处理每一组数据for group_idx, start_row in enumerate(group_start_rows, start=1):# 读取表格名称、坐标轴标签table_name = sheet.cell(row=start_row, column=1).value  # A列存储波长信息(例如 "365nm")x_label = sheet.cell(row=start_row, column=2).value       # B列第一行: 横坐标标签(电压)y_label = sheet.cell(row=start_row + 1, column=2).value     # B列第二行: 纵坐标标签(电流)# **处理 y_label,将乘方变为上标**if y_label:y_label = y_label.replace("10-10", r"$10^{-10}$") \.replace("10-11", r"$10^{-11}$") \.replace("10-12", r"$10^{-12}$")# 读取电压与电流数据(从 C 到 L 列)voltage_data = []current_data = []for col in range(3, 13):  # C(3)到L(12)v = sheet.cell(row=start_row, column=col).value  # 电压数据i = sheet.cell(row=start_row + 1, column=col).value  # 电流数据voltage_data.append(v)current_data.append(i)# 计算频率# 从 table_name 中去除末尾两个字符(例如 "nm")转换为 int 得到波长wavelength_nm = int(table_name[:-2])wavelength_m = wavelength_nm * 1e-9  # 转换为 mfrequency = c / wavelength_m  # 计算频率 (Hz)frequency_14 = frequency / 1e14  # 以 10^-14 Hz 为单位wavelengths.append(wavelength_nm)frequencies.append(frequency_14)# 过滤并排序有效数据valid_indices = [i for i, (v, i_val) in enumerate(zip(voltage_data, current_data))if v is not None and i_val is not None]x = np.array([voltage_data[i] for i in valid_indices])y = np.array([current_data[i] for i in valid_indices])# 按电压升序排列sort_idx = np.argsort(x)x_sorted = x[sort_idx]y_sorted = y[sort_idx]if auto:cutoff_voltage = Noneelse:cutoff_voltage = cutoff_voltages[group_idx - 1]try:# 使用保形插值(保证单调性)pchip = PchipInterpolator(x_sorted, y_sorted)nums_data = 300# 生成密集采样点,用于绘制曲线(扩展范围为原数据范围两侧各扩展10%)x_min, x_max = np.min(x_sorted), np.max(x_sorted)x_range = x_max - x_minx_dense = np.linspace(x_min - 0.1*x_range, x_max + 0.1*x_range, nums_data)y_dense = pchip(x_dense)if auto:threshold = (max(y_dense) - min(y_dense)) / (x_max - x_min)  # 导数阈值for i in range(nums_data):if (y_dense[i + 5] - y_dense[i]) / (x_dense[i + 5] - x_dense[i]) > threshold * 1.5:cutoff_voltage = x_dense[i]breakexcept Exception as e:print(f"[{group_idx}] 插值失败,使用线性连接: {str(e)}")cutoff_voltage = Nonex_dense = x_sortedy_dense = y_sortedif auto:if cutoff_voltage is not None:print(f"[{group_idx}] 拐点确定的截止电压: {cutoff_voltage:.3f} V")else:print(f"[{group_idx}] 未检测到拐点,截止电压无法确定")cutoff_voltages.append(cutoff_voltage)# 绘制伏安特性曲线plt.figure(figsize=(10, 7))plt.plot(x_dense, y_dense, 'b-', linewidth=2, label="拟合曲线")plt.scatter(x_sorted, y_sorted, c='red', s=50, marker='o',edgecolors='k', label="实验数据")if cutoff_voltage is not None:plt.axvline(cutoff_voltage, color='red', linestyle='--', label=f"截止电压: {cutoff_voltage:.2f} V")plt.xlabel(x_label)plt.ylabel(y_label)plt.title(f"伏安特性曲线,波长 {table_name}")plt.grid(True)plt.legend()plt.tight_layout()output_path = os.path.join(output_dir, f"output_{group_idx}.png")plt.savefig(output_path, dpi=300)plt.close()print(f"[{group_idx}] 图像已保存至: {output_path}")# 5. 线性拟合:截止电压 vs 频率(计算拟合参数及其不确定度)freq_array = np.array(frequencies)volt_array = np.array(cutoff_voltages, dtype=float)# 使用 cov=True 得到参数协方差矩阵coeffs, cov = np.polyfit(freq_array, volt_array, 1, cov=True)k, b = coeffserr_k = np.sqrt(cov[0, 0])  # 斜率 k 的标准差,即不确定度# 6. 绘制截止电压 vs 频率 图(增加数据点连接线,并设置刻度格式)plt.figure(figsize=(8, 6))plt.scatter(freq_array, volt_array, color='blue', label="实验数据")plt.plot(freq_array, volt_array, 'b-', label="数据连接线")plt.plot(freq_array, k * freq_array + b, 'r--', label=f"拟合直线: $U_s = {k:.4f}f + {b:.4f}$\n斜率不确定度: ±{err_k:.4f}")plt.xlabel(r"频率 ($10^{-14}$ Hz)")plt.ylabel("截止电压 (V)")plt.title("截止电压-频率图线")plt.grid(True)plt.legend()ax = plt.gca()ax.xaxis.set_major_formatter(FormatStrFormatter('%.3f'))  # 横轴保留三位小数ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f'))  # 纵轴保留两位小数plt.tight_layout()output_path = os.path.join(output_dir, f"output_{N + 1}.png")plt.savefig(output_path, dpi=300)plt.close()print(f"截止电压-频率图已保存至: {output_path}")# 7. 计算普朗克常数h0 = 6.64 * 10**(-34)  # 公认普朗克常数 (J·s)e = 1.6 * 10**(-19)  # 电子电荷量 (C)h = e * (-k) * 1e-14  # 计算出的普朗克常数 (J·s)_h = e * err_k * 1e-14  # 计算出的普朗克常数的不确定度 (J·s)Ep = (h - h0) * 100 / h0# 8. 写入 Excel# 将标题写入 A15, A16, A17sheet["A15"] = "波长 (nm)"sheet["A16"] = "频率 (10^-14 Hz)"sheet["A17"] = "截止电压 (V)"# 假设数据组数为 5,对应写入 B 到 F 列for i, (w, f, u) in enumerate(zip(wavelengths, frequencies, cutoff_voltages)):col_letter = chr(ord('B') + i)  # B, C, D, E, Fsheet[f"{col_letter}15"] = f"{w:.0f}"sheet[f"{col_letter}16"] = f"{f:.2f}"sheet[f"{col_letter}17"] = f"{u:.2f}"# 将计算结果写入 Excel(从 A19 开始)sheet["A19"] = "h"sheet["B19"] = f"{h * 10 ** 34:.2f} × 10^(-34) J·s"sheet["A20"] = "Δh"sheet["B20"] = f"{_h * 10 ** 34:.2f} × 10^(-34) J·s"sheet["A21"] = "h±Δh"sheet["B21"] = f"{h * 10 ** 34:.2f} ± {_h * 10 ** 34:.2f} × 10^(-34) J·s"sheet["A22"] = "Ep"sheet["B22"] = f"{Ep:.2f}%"wb.save(excel_file)print("计算结果已写入 Excel")print(f"{Ep:.2f}%")if save_to_word:from docx import Documentfrom docx.shared import Inchesdef Htlanglanglang():doc = Document()# 创建表格(3 行 2 列),确保六张图片能排在一页上table = doc.add_table(rows=3, cols=2)table.autofit = True  # 自动调整列宽img_index = 0  # 计数器for i in range(1, N + 2):  # 遍历所有图片(包括截止电压-频率图)image_path = os.path.join(output_dir, f"output_{i}.png")if os.path.exists(image_path):row = img_index // 2  # 计算行号col = img_index % 2   # 计算列号cell = table.cell(row, col)  # 获取单元格paragraph = cell.paragraphs[0]run = paragraph.add_run()run.add_picture(image_path, width=Inches(3))  # 调整宽度,确保 3 张图片一行img_index += 1doc.save(word_file)print(f"实验结果已保存至 Word: {word_file}")if calculate:Htlang()
if save_to_word:Htlanglanglang()

 操作步骤

第0步 创建所需文件

在电脑某个位置新建一个文件夹,然后在新建的文件夹里新建一个.xlsx文件、一个.py文件、一个.docx文件以及一个文件夹,完成后大概长下面这样

第1步 填入数据、粘贴代码

打开excel文件,将原始数据输入,格式如下

注意:A列的几个单元格要合并一下不然会报错(我懒的调了),电流的单位中的-11次方这些不需要在excel中就给它改为上标不然不知道会不会报错(我懒的试了)

打开Python文件,将代码粘贴进去,并在代码中注释了控制台的部分对文件路径进行修改

第2步 安装必要的Python扩展库

打开cmd,输入以下代码(二选一)

pip install scipy
pip install python-docx
pip install openpyxl
pip install matplotlib
pip install numpy
pip install openpyxl matplotlib numpy scipy python-docx

第3步 运行代码

一切顺利的话运行结果大致如下

 此外,打开excel,会发现多了一些数据

文件夹里也会多出6张图片

第4步 发现问题并稍加调整

因为找拐点的方法比较粗略,所以可能会存在较大的误差,导致算出来的百分差严重超标,所以我们需要进行手动调整,然后将五个截止电压在代码中事先输入,如下图

第5步 再次运行代码

我们需要不断的调整和尝试,直到把百分差降到10%以下

注意:运行时记得把excel关掉否则会报错

第6步 把图片保存到word中

经过不断的调整,将百分差控制在10以内之后,将代码中的save_to_word这个变量设置为1(当然一开始就设置为1也不是不行,开始教学之前我忘记改了),再次运行代码(此时可以将变量calculate设置为0,不过无所谓,数据量不大,运行也耗不了多长时间),会发现输出多了一句话

然后就可以打开word,按自己的需求调整图片的大小(代码已经初步调好了),然后去打印店打印结果了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/39890.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【日常笔记 1】 有关异常学习笔记

今天笔记内容详见 ----- C11_5 异常部分 笔记较乱 , 笔者只是为了记录重要知识点 , 想重点了解相关知识点的可关注笔者正文栏目 ~ 笔者代码仓 : C11_5 代码 异常部分学习笔记 异常基本关键字信息   throw    ----    抛出异常   try - catch ----    捕获异常 , 必须…

Linux UDP网络编程套接字sockets

目录 一、预备知识 1、IP地址 2、端口号 3、Socket网络通信 4、认识TCP/UDP协议 (1)TCP协议 (2)UDP协议 (3)网络字节序 二、socket网络套接字 1、概念 2、Socket 的地址结构和一系列转换函数 &a…

VUE3项目VITE打包优化

VUE3项目VITE打包优化 代码加密依赖配置效果对比图 自动导入依赖配置 代码压缩依赖配置效果对比图 图片压缩依赖配置效果对比图 字体压缩总结与实践运用效果 代码加密 依赖 npm install -D vite-plugin-bundle-obfuscator配置 import vitePluginBundleObfuscator from "…

NO.57十六届蓝桥杯备战|基础算法-高精度|加减乘除|模拟竖式计算(C++)

当数据的值特别⼤,各种类型都存不下的时候,此时就要⽤⾼精度算法来计算加减乘除: 先⽤字符串读⼊这个数,然后⽤数组逆序存储该数的每⼀位;利⽤数组,模拟加减乘除运算的过程。 ⾼精度算法本质上还是模拟算法…

最新DeepSeek-V3-0324:AI模型性能提升与新特性解析

文章目录 性能提升概览新特性解析1. 推理任务表现提高2. 前端开发能力增强3. 中文写作与搜索能力优化4. 模型开源 总结与展望 随着人工智能技术的快速发展,模型的迭代更新成为推动技术进步的重要力量。最近,DeepSeek团队发布了其V3模型的最新小版本更新—…

linux常用指令(7)

今天还是继续学习linux相关的指令,基础越牢固,就越有利于我们后面的学习,那么话不多说,来看. 1.head指令 功能描述:用于显示文件的开头部分内容,默认情况下head显示文件的前10行内容. 基本语法:head 文件 选项:-n nums 显示前nums行内容 …

数仓架构告别「补丁」时代!全新批流一体 Domino 架构终结“批流缝合”

在数字化转型的浪潮中,企业对数据处理的需求日益复杂多变,传统的批处理和流处理架构已难以满足日益增长的性能和时效性要求。在此背景下,YMatrix CEO 姚延栋发布了深度文章《数仓架构告别「补丁」时代!全新批流一体 Domino 架构终…

HTB 笔记 | SQL 注入基础 + 实操小练习 P2

1. 数据库类型 数据库分为两类: 关系型数据库(Relational Databases) 使用表格存储数据(行和列)。数据通过“键”连接,形成逻辑关系。示例:MySQL、PostgreSQL、SQL Server。特点:结…

MySQL 入门大全:数据类型

🧑 博主简介:CSDN博客专家,历代文学网(PC端可以访问:https://literature.sinhy.com/#/literature?__c1000,移动端可微信小程序搜索“历代文学”)总架构师,15年工作经验,…

解决 Not allowed to load local resource 问题

记录一下遇到的问题&#xff1a;html跳转本地资源&#xff0c;用相对路径 这样是不对的&#xff0c;要用 <script src"/jquery.min.js"></script> 网络路径也行&#xff0c;慢了一点 记得一定要关闭浏览器的广告屏蔽器 绝对路径也行&#xff0c;不过要…

STM32实现智能温控系统(暖手宝):PID 算法 + DS18B20+OLED 显示,[学习 PID 优质项目]

一、项目概述 本文基于 STM32F103C8T6 单片机&#xff0c;设计了一个高精度温度控制系统。通过 DS18B20 采集温度&#xff0c;采用位置型 PID 算法控制 PWM 输出驱动 MOS 管加热Pi膜&#xff0c;配合 OLED 实时显示温度数据。系统可稳定将 PI 膜加热至 40℃&#xff0c;适用于…

[深度学习]图像分类项目-食物分类

图像分类项目-食物分类(监督学习和半监督学习) 文章目录 图像分类项目-食物分类(监督学习和半监督学习)项目介绍数据处理设定随机种子读取文件内容图像增广定义Dataset类 模型定义迁移学习 定义超参Adam和AdamW 训练过程半监督学习定义Dataset类模型定义定义超参训练过程 项目介…

C++初阶入门基础二——类和对象(中)

1类的默认成员函数 默认成员函数就是用户没有显式实现&#xff0c;编译器会自动生成的成员函数称为默认成员函数。一个类&#xff0c;我们不写的情况下编译器会默认生成以下6个默认成员函数&#xff0c;需要注意的是这6个中最重要的是前4个&#xff0c;最后两个取地址重载不重…

基于SSM框架的线上甜品销售系统(源码+lw+部署文档+讲解),源码可白嫖!

摘要 网络技术和计算机技术发展至今&#xff0c;已经拥有了深厚的理论基础&#xff0c;并在现实中进行了充分运用&#xff0c;尤其是基于计算机运行的软件更是受到各界的关注。加上现在人们已经步入信息时代&#xff0c;所以对于信息的宣传和管理就很关键。因此网上销售信息的…

3.25学习总结java 接口+内部类

JDK8以后新增的方法 可以将接口中静态方法和抽象方法中重复的部分抽离出来&#xff0c;作为私有方法&#xff0c;用去private修饰&#xff0c;此方法只为接口提供服务&#xff0c;不需要外界访问。 接口的应用 接口代表规则&#xff0c;是行为的抽象&#xff0c;想让哪个类拥有…

Linux--环境变量

ok&#xff0c;今天我们来学习Linux中的环境变量、地址空间、虚拟内存 环境变量 基本概念 环境变量(environmentvariables)⼀般是指在操作系统中⽤来指定操作系统运⾏环境的⼀些参数如&#xff1a;我们在编写C/C代码的时候&#xff0c;在链接的时候&#xff0c;从来不知道我…

Java 集合 List、Set、Map 区别与应用

一、核心特性对比 二、底层实现与典型差异 ‌List‌ ‌ArrayList‌&#xff1a;动态数组结构&#xff0c;随机访问快&#xff08;O(1)&#xff09;&#xff0c;中间插入/删除效率低&#xff08;O(n)&#xff09;‌‌LinkedList‌&#xff1a;双向链表结构&#xff0c;头尾操作…

基于 arco 的 React 和 Vue 设计系统

arco 是字节跳动出品的企业级设计系统&#xff0c;支持React 和 Vue。 安装模板工具 npm i -g arco-cli创建项目目录 cd someDir arco init hello-arco-pro? 请选择你希望使用的技术栈React❯ Vue? 请选择一个分类业务组件组件库Lerna Menorepo 项目❯ Arco Pro 项目看到以…

JVM-GC(G1)实践—GC异常定位、参数调整、GC更换

前言 如SpringBoot官方介绍所说的那样&#xff0c;从SpringBoot3.x开始支持的最低JDK版本为&#xff1a;JDK17&#xff08;官方推荐使用BellSoft Liberica JDK&#xff09;&#xff0c;其对应的GC为G1。 本文笔者从应用实践的角度出发&#xff0c;记录一些关于GC的一些实践总…

吾爱出品,文件分类助手,高效管理您的 PC 资源库

在日常使用电脑的过程中&#xff0c;文件杂乱无章常常让人感到困扰。无论是桌面堆积如山的快捷方式&#xff0c;还是硬盘中混乱的音频、视频、文档等资源&#xff0c;都急需一种高效的整理方法。文件分类助手应运而生&#xff0c;它是一款文件管理工具&#xff0c;能够快速、智…