SR785频谱仪由于保存数据时的格式问题,所以处理数据时需要进行转换,通过下面的程序可以缩短处理数据的时间。
代码如下:
import os
import subprocess
import csv
import numpy as np
import matplotlib.pyplot as plt
def process_asc_file(asc_file_path, folder_path):
# 生成对应的 CSV 文件路径
csv_file_name = os.path.splitext(os.path.basename(asc_file_path))[0] + '.csv'
csv_file_path = os.path.join(folder_path, csv_file_name)
split_csv_file_name = os.path.splitext(os.path.basename(asc_file_path))[0] + '_split.csv'
split_csv_file_path = os.path.join(folder_path, split_csv_file_name)
print(f"尝试将 {asc_file_path} 转换为 {csv_file_path}")
try:
# 步骤 1: 按行读取 ASC 文件并写入 CSV 文件
with open(asc_file_path, 'r', encoding='utf-8') as asc_file, open(csv_file_path, 'w', newline='',
encoding='utf-8') as csv_file:
csv_writer = csv.writer(csv_file)
for line in asc_file:
csv_writer.writerow([line.strip()])
print(f"文件 {os.path.basename(asc_file_path)} 已成功转换为 {os.path.basename(csv_file_path)}")
except FileNotFoundError:
print(f"错误:未找到文件 {asc_file_path} 或无法创建 {csv_file_path}")
except PermissionError:
print(f"错误:没有权限访问 {asc_file_path} 或写入 {csv_file_path}")
except Exception as e:
print(f"将 {os.path.basename(asc_file_path)} 转换为 {os.path.basename(csv_file_path)} 时出现未知错误: {e}")
return
# 步骤 2: 提取数据部分(从 X[Hz] 行之后的两列数值)
data = []
in_data_section = False
try:
with open(asc_file_path, 'r', encoding='utf-8') as asc_file:
for line in asc_file:
if line.strip().startswith(' X[Hz]'):
in_data_section = True
continue
if in_data_section:
parts = line.strip().split()
if len(parts) == 2:
try:
x = float(parts[0])
y = float(parts[1])
data.append([x, y])
except ValueError:
continue
except Exception as e:
print(f"从 {os.path.basename(asc_file_path)} 提取数据时出现错误: {e}")
# 步骤 3: 若提取到有效数据,计算原数据第二列的最大值
if data:
data_array = np.array(data)
max_value = np.max(data_array[:, 1])
print(f"文件 {os.path.basename(asc_file_path)} 原数据第二列的最大值是: {max_value}")
else:
print(f"文件 {os.path.basename(asc_file_path)} 未提取到有效数据,请检查文件格式。")
print(f"尝试处理 {csv_file_path} 并保存为 {split_csv_file_path}")
try:
# 步骤 4: 将 CSV 文件中第 11 行到第 812 行根据空格拆分成两列并保存到第 6、7 列
with open(csv_file_path, 'r', encoding='utf-8') as infile, \
open(split_csv_file_path, 'w', newline='', encoding='utf-8') as outfile:
reader = csv.reader(infile)
writer = csv.writer(outfile)
for i, row in enumerate(reader, start=1):
new_row = row.copy()
if 11 <= i <= 812:
line_content = row[0]
parts = line_content.split()
if len(parts) == 2:
# 确保新行有足够的列数
while len(new_row) < 7:
new_row.append('')
new_row[5] = parts[0]
new_row[6] = parts[1]
writer.writerow(new_row)
print(f"文件 {os.path.basename(csv_file_path)} 已成功处理并保存为 {os.path.basename(split_csv_file_path)}")
except FileNotFoundError:
print(f"错误:未找到文件 {csv_file_path} 或无法创建 {split_csv_file_path}")
except PermissionError:
print(f"错误:没有权限访问 {csv_file_path} 或写入 {split_csv_file_path}")
except Exception as e:
print(
f"处理 {os.path.basename(csv_file_path)} 并保存为 {os.path.basename(split_csv_file_path)} 时出现未知错误: {e}")
# 步骤 5: 在 _split.csv 文件中寻找第 7 列的 3 个最大值及对应第 6 列的平均值
column_6_data = []
column_7_data = []
try:
with open(split_csv_file_path, 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for i, row in enumerate(reader, start=1):
if 11 <= i <= 812 and len(row) >= 7:
try:
freq = float(row[5])
value = float(row[6])
column_6_data.append(freq)
column_7_data.append(value)
except ValueError:
continue
except Exception as e:
print(f"从 {os.path.basename(split_csv_file_path)} 读取数据时出现错误: {e}")
if len(column_7_data) >= 3:
sorted_indices = np.argsort(column_7_data)[::-1]
selected_max_indices = []
for index in sorted_indices:
if not selected_max_indices:
selected_max_indices.append(index)
else:
# 检查间隔是否至少为 50Hz
is_valid = True
for selected_index in selected_max_indices:
if abs(column_6_data[index] - column_6_data[selected_index]) < 50:
is_valid = False
break
if is_valid:
selected_max_indices.append(index)
if len(selected_max_indices) == 3:
break
if len(selected_max_indices) == 3:
max_values = [column_7_data[i] for i in selected_max_indices]
corresponding_freqs = [column_6_data[i] for i in selected_max_indices]
avg_freq = np.mean(corresponding_freqs)
print(f"文件 {os.path.basename(split_csv_file_path)} 第 7 列的 3 个最大值是: {max_values}")
print(f"对应的第 6 列频率的平均值是: {avg_freq}")
else:
print(f"文件 {os.path.basename(split_csv_file_path)} 未找到满足间隔至少 50Hz 的 3 个最大值。")
else:
print(f"文件 {os.path.basename(split_csv_file_path)} 第 7 列数据不足,无法找到 3 个最大值。")
# 步骤 6: 若提取到有效数据,根据第 6 列和第 7 列的数据画图
if data:
plot_data = []
try:
with open(split_csv_file_path, 'r', encoding='utf-8') as csvfile:
reader = csv.reader(csvfile)
for i, row in enumerate(reader, start=1):
if 11 <= i <= 812 and len(row) >= 7:
try:
x = float(row[5])
y = float(row[6])
plot_data.append([x, y])
except ValueError:
continue
except Exception as e:
print(f"从 {os.path.basename(split_csv_file_path)} 读取绘图数据时出现错误: {e}")
if plot_data:
plot_array = np.array(plot_data)
plt.plot(plot_array[:, 0], plot_array[:, 1])
plt.xlabel('Column 6 Data')
plt.ylabel('Column 7 Data')
plt.title(f'Plot for {os.path.basename(asc_file_path)}')
plt.grid(True)
plt.show()
# 定义要检索的文件夹路径
folder_path = r"C:\SRTRANS"
# 用于存储符合条件的文件名
file_list = []
# 检查指定的文件夹是否存在
if os.path.exists(folder_path):
# 遍历文件夹及其子文件夹,找出所有 .78D 文件
for root, dirs, files in os.walk(folder_path):
for file in files:
if file.lower().endswith('.78d'):
file_list.append(file)
print("找到的 .78D 文件列表:", file_list)
print("找到的 .78D 文件个数:", len(file_list))
# srtrans 可执行文件的完整路径
srtrans_path = os.path.join(folder_path, "srtrans.exe")
# 检查 srtrans 可执行文件是否存在
if not os.path.exists(srtrans_path):
print(f"srtrans 可执行文件 {srtrans_path} 不存在,请检查。")
else:
for file in file_list:
try:
# 构造完整的文件路径
full_file_path = os.path.join(folder_path, file)
# 构造转换命令
command = [srtrans_path, '/Oasc', full_file_path]
# 执行命令
result = subprocess.run(command, capture_output=True, text=True, check=True)
output = result.stdout
# 修正判断条件
if "Finished" in output:
print(f"文件 {file} 转换完成。")
asc_file_path = os.path.splitext(full_file_path)[0] + '.asc'
process_asc_file(asc_file_path, folder_path)
else:
print(f"文件 {file} 转换可能出现问题,输出信息:{output}")
except subprocess.CalledProcessError as e:
print(f"处理文件 {file} 时出现错误,错误信息:{e.stderr}")
except Exception as e:
print(f"处理文件 {file} 时出现未知错误:{e}")
else:
print(f"指定的文件夹 {folder_path} 不存在。")
print("运行结束")
编写过程中的注意事项:
1. 转换完成判断条件拼写错误
在判断 .78D
文件是否成功转换为 .asc
文件时,代码里用的判断条件是 if "Finshed" in output:
,然而 srtrans
工具输出的完成信息里 “Finished” 拼写正确,所以原代码的判断条件始终为 False
,程序会误判转换可能出现问题,进而不执行后续对 .asc
文件的处理操作。
# 原错误代码
if "Finshed" in output:
print(f"文件 {file} 转换完成。")
asc_file_path = os.path.splitext(full_file_path)[0] + '.asc'
process_asc_file(asc_file_path, folder_path)
# 修正后的代码
if "Finished" in output:
print(f"文件 {file} 转换完成。")
asc_file_path = os.path.splitext(full_file_path)[0] + '.asc'
process_asc_file(asc_file_path, folder_path)
- 条件判断:检查字符串
"Finished"
是否存在于变量output
中。由于修正了拼写错误,只要srtrans
工具输出的信息里包含 “Finished”,就表示.78D
文件成功转换为.asc
文件。 - 转换成功处理:若
"Finished"
存在于output
中,程序会打印一条消息,表明文件file
转换完成。 - 生成
.asc
文件路径:和原错误代码一样,使用os.path.splitext
函数生成转换后的.asc
文件路径asc_file_path
。 - 处理
.asc
文件:调用process_asc_file
函数对生成的.asc
文件进行处理。
2. 异常处理不够细致
虽然原代码有异常处理逻辑,但不够细致,对于文件操作时可能出现的 FileNotFoundError
和 PermissionError
没有单独处理,这使得在出现这些错误时,难以精准定位问题。
# 原代码异常处理
try:
with open(asc_file_path, 'r', encoding='utf-8') as asc_file, open(csv_file_path, 'w', newline='',
encoding='utf-8') as csv_file:
csv_writer = csv.writer(csv_file)
for line in asc_file:
csv_writer.writerow([line.strip()])
except Exception as e:
print(f"将 {os.path.basename(asc_file_path)} 转换为 {os.path.basename(csv_file_path)} 时出现未知错误: {e}")
return
# 修正后代码异常处理
try:
with open(asc_file_path, 'r', encoding='utf-8') as asc_file, open(csv_file_path, 'w', newline='',
encoding='utf-8') as csv_file:
csv_writer = csv.writer(csv_file)
for line in asc_file:
csv_writer.writerow([line.strip()])
except FileNotFoundError:
print(f"错误:未找到文件 {asc_file_path} 或无法创建 {csv_file_path}")
except PermissionError:
print(f"错误:没有权限访问 {asc_file_path} 或写入 {csv_file_path}")
except Exception as e:
print(f"将 {os.path.basename(asc_file_path)} 转换为 {os.path.basename(csv_file_path)} 时出现未知错误: {e}")
return
try
块:- 运用
with
语句同时打开两个文件,一个是以只读模式('r'
)打开的asc_file_path
对应的.asc
文件,另一个是以写入模式('w'
)打开的csv_file_path
对应的.csv
文件。 - 借助
csv.writer
创建一个 CSV 写入器对象csv_writer
。 - 逐行读取
.asc
文件的内容,对每行内容去除首尾空白字符后,以列表形式写入.csv
文件。
- 运用
except
块:
except FileNotFoundError
:专门捕获文件未找到的异常。当尝试打开的.asc
文件不存在或者无法创建.csv
文件时,会触发该异常,接着打印一条包含文件路径的错误信息。except PermissionError
:专门捕获权限错误异常。当没有足够权限访问.asc
文件或者写入.csv
文件时,会触发该异常,然后打印一条包含文件路径的错误信息。except Exception as e
:捕获除了FileNotFoundError
和PermissionError
之外的其他异常,打印错误信息并执行return
语句,终止后续操作。
3. 缺乏详细日志输出
原代码在文件操作过程中缺乏详细的日志输出,当出现问题时,难以知晓程序具体执行到哪一步,无法快速定位问题。修正后的代码添加了详细的日志输出,比如在尝试转换 .asc
为 .csv
文件以及处理 .csv
文件生成 _split.csv
文件时,都会输出相应的提示信息,方便排查问题。
# 修正后添加的日志输出
print(f"尝试将 {asc_file_path} 转换为 {csv_file_path}")
print(f"尝试处理 {csv_file_path} 并保存为 {split_csv_file_path}")