elsiwaveQI 2024-10-07 17:37 采纳率: 64%
浏览 23
已结题

python写segy数据出错

#遇到问题的现象描述
使用pyside2写一段代码,任务是读一个segy文件并写到指定目录。构造了segyio要求的spec,也读取了相关的必要信息如samples,interval, tracecount等,并构建了一个local_f_data字典,包含了必须的关键字如text、bin等。程序执行时运行到要写segy文件时发生错误。没有执行打印语句: print('开始写文本头')

#问题相关代码片,运行结果,报错内容
相关代码片:

        try:    
            # Create SEGY file with spec
            with segyio.create(self.output_file, self.spec) as w:
                print('开始写文本头')
                w.text[0] = self.local_f_data['text'][0]

                print('开始写二进制头')
                for key, value in self.local_f_data['bin'].items():
                    w.bin[key] = value

......
        try:
            #read segy file
            with segyio.open(filename, mode='r', ignore_geometry = False) as f:
                # 读取必要的信息
                text = f.text  # 文本头部
                tracecount = f.tracecount  # 地震道数量
                samples = f.samples  # 样本数组
                interval = f.bin[segyio.BinField.Interval]
                dataformat = f.bin[segyio.BinField.Format]
                
                #print(samples)
                
                #header = list(f.header)  # 地震道头部信息
                trace = list(f.trace)    # 地震道数据

                print(f"Number of traces: {len(trace)}")
                
                # 使用 f.ilines 和 f.xlines 提取 iline 和 xline
                iline = f.ilines.tolist()  # 转换为列表
                xline = f.xlines.tolist()  # 转换为列表

                iline = np.array(iline)
                xline = np.array(xline)

            print("开始创建字典")
            local_f_data = {
                'text': text,
                'bin':{
                    segyio.BinField.Samples: samples,
                    segyio.BinField.Traces: trace,
                    segyio.BinField.Interval: interval,  # Sampling interval (milliseconds)
                    segyio.BinField.Format: dataformat
                },
                'tracecount': tracecount, #len(self.traces), 确保你在这里计算 trace 的数量
                'iline': iline,  
                'xline': xline
                   # 'filehandle': filehandle     
            }
                
            print("构建spec")
            spec = segyio.spec()
            spec.samples = samples  # 样本点数量
            spec.format = dataformat #已经修改为常量或枚举
            spec.tracecount = tracecount  # 确保 tracecount 是整数
            spec.iline = np.unique(iline).astype(np.int32) if iline is not None else None
            spec.xline = np.unique(xline).astype(np.int32) if xline is not None else None      
            # Create FileWriteThread instance
            self.file_write_thread = FileWriteThread(output_file, local_f_data, spec)

运行结果如下:
===================== RESTART: D:\ML\mldata\plot_project\deeplearning\segy_loading.py =====================
MainWindow initialized
Application started
Save button clicked
Number of traces: 9911
开始创建字典
构建spec
Thread started
Attempting to open SEGY file: D:/ML/mldata/plot_project/deeplearning/output.sgy
Error while writing SEGY file: only length-1 arrays can be converted to Python scalars
Thread finished

错误信息:Error while writing SEGY file: only length-1 arrays can be converted to Python scalars

#我的初步解答思路是
在ChatGppt4o帮助下重点检查修改了local_f_data和spec,因为执行到写segy数据时发生错误,那推断这行语句没有执行with segyio.open(filename, mode='r', ignore_geometry = False) as f:
但经过修改后再运行还是不行,也找不出问题所在。请检查代码并给出修改的正确代码,谢谢!

#操作环境、软件版本等相关信息
win2011, python3.10, segyio1.9.12

  • 写回答

19条回答 默认 最新

  • bug菌¹ 优质创作者: Java、算法与数据结构技术领域 2024-10-07 20:05
    关注

    该回答引用ChatGPT-4o,望对题主有所帮助/启发;若有帮助,还望采纳🤝🤝🤝


    根据你提供的错误信息“only length-1 arrays can be converted to Python scalars”,这个错误通常与数据类型不匹配有关,特别是在将数组的值赋给一个期望标量的地方。

    在这段代码中,可能的问题出现在你对 local_f_data 的构建和 segyio.spec() 的配置上。具体地,samplestrace 可能是多维数组,而 segyio.BinField.Samplessegyio.BinField.Traces 可能期望标量值或特定维度的数组。让我们详细检查并修改。

    初步修改

    1. 确保 samplestrace 处理正确:

      • samples 可能是一个数组,需要确保其是一个一维数组。
      • trace 是所有地震道的数据的列表,如果你是直接将列表赋值给二进制头部,可能会导致类型错误。
    2. 修改 local_f_dataspec 构造逻辑:

      • 在二进制头部中,某些字段可能需要标量而不是数组,因此需要逐步检查和处理。

    修改后的代码

    import numpy as np
    import segyio
    
    try:    
        # 创建SEGY文件并构建spec
        with segyio.create(self.output_file, self.spec) as w:
            print('开始写文本头')
            w.text[0] = self.local_f_data['text'][0]
     
            print('开始写二进制头')
            for key, value in self.local_f_data['bin'].items():
                if isinstance(value, (list, np.ndarray)):  # 检查是否是数组或列表
                    value = np.asscalar(np.array(value).flatten()[0])  # 转换为标量
                w.bin[key] = value
     
            print('开始写地震道数据')
            for i, trace_data in enumerate(self.local_f_data['traces']):
                w.trace[i] = trace_data  # 将地震道数据逐个写入
                
    except Exception as e:
        print(f"Error while writing SEGY file: {e}")
    

    重点说明:

    1. **np.asscalar()**:这是用于将单个值的数组转换为标量。这个在某些字段中如 BinField.Samples 等地方可能需要。
    2. 逐个写入地震道:如果 traces 是一个多维数组或列表,需要将其逐个写入文件,不能直接赋给二进制头部。

    检查 samplestrace

    samples = np.array(f.samples)  # 确保 samples 是一维数组
    trace = [np.array(t) for t in f.trace]  # 将每个地震道转换为 numpy 数组
    

    调整 spec

    确保在 spec 中正确设置 samplestracecount,例如:

    spec.samples = len(samples)  # 样本点数量
    spec.tracecount = tracecount  # 地震道数量
    

    小结:

    请确保你正确理解 samplestrace 在 SEGY 文件中的作用,并为需要标量的字段提供单个值。如果继续遇到问题,建议逐步调试 local_f_data 中每个字段的格式和类型,确保其符合 segyio 的要求。

    可以通过这个方式逐步检查问题。如果需要进一步的帮助或有新的错误信息,请随时分享。

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(18条)

报告相同问题?

问题事件

  • 系统已结题 10月16日
  • 已采纳回答 10月8日
  • 创建了问题 10月7日