含光左卫 Publish time 2023-6-30 13:43:32

汉泰.doc=>力科.trc转换程序

第一级代码(by Python):# code by fengxh.
# transfer 汉泰.doc => Lecroy 二进制.trc格式。
# python code is created at Jun30,2023

from scipy.optimize import curve_fit
import numpy as np
import csv
import sys
import operator
import subprocess
import re


# 取csv文件的第N列,抛弃掉标题栏,返回数组
def load_csv_data(filename, idxBase0):
    data = []# 存放结果的数组

# 打开CSV文件,并读取数据
    flagDataStart = False;
    with open(filename, 'r') as f:
      reader = csv.reader(f)
      i = 0;
      for row in reader:
            i = i+1;
            #print(i);
            if len(row) == 0:
                if(not flagDataStart):
                  flagDataStart = True;
                  continue;
                else:
                  break; #done!
            if(not flagDataStart): continue;
            try:
               data.append(float(row))# 取第一列数据,并转为float类型
            except:
                continue;
    return data;

# 取csv文件的第N列,抛弃掉标题栏,返回数组
def get_time_scale(filename):
    flagDataStart = False;
    #string = "#CLOCK=0.004000000S"
    pattern = r"CLOCK=(\d+\.\d+)S"
    with open(filename, 'r') as f:
      reader = csv.reader(f)
      for row in reader:
            match = re.search(pattern, str(row))
            if match:
                result = float(match.group(1));
                return result;
    return 100e-6;


def getRmsOfFreq(arFreq, arRms, freq):
    for i in range(0, len(arFreq)):
      if(arFreq == freq): return arRms;

def csv2trc(csvfile, trcfile, ratio):
# 要执行的命令
#Usage: Csv2Trc <src.csv> <tgt.trc> [<sample_rate=100e-6> <volPerAd>=1]   
    command = r"C:\Users\fengxh\Desktop\工具集\dumb\Csv2Trc_V1.0.20230531\SampleData_CSV2LecoryTrc";
    command = command + " " +csvfile + ' ' + trcfile + ' ' + str(ratio);
    # 执行命令并获取输出
    output = subprocess.check_output(command, shell=True)
    output = output.decode()# 如果你想要将输出作为字符串处理,可以解码为返回的字节字符串
    print(output)

def toInteger(rms):
    vals = [];
    for i in rms:
      if(not i in vals):
            vals.append(i);

    sorted_vals = sorted(vals);

    my_dict = {sorted_vals:1};
    idx = 1;
    for v in sorted_vals:
      my_dict = idx;
      idx = idx +1;

    ret = [];
    for i in rms:
      ret.append(my_dict);
            
    return ret;


def zoom_out_lecory_wave_data(filename, ratio=10):
    rms = load_csv_data(filename, 0);#rms
    dt = get_time_scale(filename);
    print("数据的时间跨度", dt, "秒, 数据点数:", len(rms));
    rms = toInteger(rms);
    data = rms[:];
    for i in range(0, len(rms)):
      data = rms;

    data_2d = [ for element in data]
    filename = filename + '.zoom_out' + str(ratio) + ".csv";
    with open(filename, 'w', newline='') as csvfile:
      writer = csv.writer(csvfile)
      writer.writerows(data_2d)
    csv2trc(filename, filename+".trc", dt*ratio/len(rms));
    print("done!");

#调用示例
filename = "35.25_40K.doc";
zoom_out_lecory_wave_data(filename,1);
第二级代码,SampleData_CSV2LecoryTrc,writened in C#, build by VS2022
/*
*lecroy_trc.cs
*
*A csv to lecory .trc bin file format helper modules.
*
*thanks to Lecroy, for its powerful offline wavefrom analyse tools.
*and Surrea1@CSDN for provide the .trc file format.
*
*----
*V1.0.20230530 by twicave
*          created. the first verison, coding in vs2022(c#)
*
*/

using System;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Diagnostics.SymbolStore;
using System.Linq;
using System.Reflection.PortableExecutable;
using System.Security.Cryptography;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Runtime.InteropServices;
using static System.Net.Mime.MediaTypeNames;
using System.ComponentModel;

namespace SampleData_CSV2LecoryTrc
{

    internal class lecroy_trc
    {
      static byte[] lecroy_trc_header = new byte[]{
      0x23,0x39,0x30,0x30,0x32,0x30,0x30,0x30,0x31,0x34,0x34,0x57,0x41,0x56,0x45,0x44,
      0x45,0x53,0x43,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0x45,0x43,0x52,0x4F,
      0x59,0x5F,0x32,0x5F,0x33,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x01,0x00,0x5A,
      0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB6,0x83,0x1E,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4C,0x45,0x43,0x52,0x4F,0x59,0x57,0x53,0x34,
      0x32,0x34,0x00,0x00,0x00,0x00,0x00,0x4B,0x45,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xDB,0x41,0x0F,0x00,0xDB,
      0x41,0x0F,0x00,0x40,0x42,0x0F,0x00,0x00,0x00,0x00,0x00,0xDA,0x41,0x0F,0x00,0x00,
      0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x01,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x0D,0x00,0x80,0x39,0x00,0x00,0x00,0xBF,0x00,
      0x00,0xFE,0x46,0x00,0x00,0x00,0xC7,0x0B,0x00,0x01,0x00,0xBD,0x37,0x06,0x35,0x1E,
      0xF4,0xC8,0xB6,0x68,0x78,0xD1,0xBF,0x46,0xB6,0xF3,0xFD,0xD4,0x78,0xD1,0xBF,0x56,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x53,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
      0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,
      0xEB,0xAF,0x2C,0x99,0xBC,0x0B,0xD8,0x31,0x27,0x39,0x40,0x02,0x0F,0x1A,0x04,0xE7,
      0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x20,
      0x00,0x02,0x00,0x00,0x00,0x80,0x3F,0x13,0x00,0x00,0x00,0x00,0x00,0x80,0x3F,0x00,
      0x00,0x00,0xBF,0x00,0x00 };

      public class trc_field_define
      {
            public string standardName;
            public string field_name;
            public int offetIdxbase0;
            public int len;
            public string type;
            public string memo;
            public string example;
            public trc_field_define(string standardName, string field_name, int offsetIdxbase0, int len, string type, string memo, string example)
            {
                this.standardName = standardName;
                this.field_name = field_name;
                this.offetIdxbase0 = offsetIdxbase0;
                this.len = len;
                this.type = type;
                this.memo = memo;
                this.example = example;
            }
      };

      static List<trc_field_define> trc_header_fields = new List<trc_field_define>{
            new trc_field_define("totalLength","文件总长字段", 0, 11, "string", "%文件头,主要用于指示文件大小,数值为9e10+文件字节长度(不包括此文件头的11个字节)", "#9020000350"),
            new trc_field_define("no_use","大小端", 11+34, 2, "u16", "数据大小端", "=1小端"),
            new trc_field_define("no_use", "文件头长", 11+36, 4, "u32", "%文件头WAVEDSEC块的长度,4B, long, 36-39", "可认为定长:346,+11字节头部=0x165 == sizeof(lecroy_trc_header)"),
            new trc_field_define("allDataLength","波形数据总长", 11+60, 4, "u32", "WAVE_ARRAY_1,%4B,long,60-63,数据列1长度", "20000004,一般是采样点数总长=时间+数据"),
            new trc_field_define("timeDataLength","时间数据总长", 11+112, 4, "u32", "", "10000002, 为波形数据总长/2"),
            new trc_field_define("sampleDataLength","采样数据总长", 11+116, 4, "u32", "", "10000002,为波形数据总长/2"),
            new trc_field_define("pntsPerScreen","PNTS_PER_SCREEN", 11+120, 4, "u32", "区间数", "为波形数据总长/2-2"),
            new trc_field_define("lastvalidPnts","LAST_VALID_PNT", 11+128, 4, "u32", "区间最后一个数据点", "为波形数据总长/2-1"),
            new trc_field_define("vertical_gain","VERTICAL_GAIN", 11+156, 4, "float", "最终的数值=采样值*Gain+offset", "1.373120030621067e-04"),
            new trc_field_define("vertical_offset","VERTICAL_OFFSET", 11+160, 4, "float", "垂直零点", "0"),
            new trc_field_define("max","MAX_VALUE", 11+164, 4, "u32", "最大值", "28875"),
            new trc_field_define("min","MIN_VALUE", 11+168, 4, "u32", "最小值", "-29131"),
            new trc_field_define("horizInterval","HORIZ_INTERVAL", 11+176, 4, "float", "采样率", "1e-10"),
            new trc_field_define("horizOffset","HORIZ_OFFSET", 11+180, 8, "double", "水平偏移", "-5e-4"),
            new trc_field_define("pixelOffset","PIXEL_OFFSET", 11+188, 8, "u32", "屏幕当前偏移?", "-5e-4"),
            new trc_field_define("horiz_uncertainty","HORIZ_UNCERTAINTY", 11+292, 4, "float", "区间数", "1e-12,采样率的1%"),
            new trc_field_define("timeBase","TIMEBASE", 11+324, 2, "u16", "水平栅格时长?这是enum", "24"),
            new trc_field_define("fixed_Vert_Gain","FIXED_VERT_GAIN", 11+332, 2, "u16", "垂直固定增益?enum", "18")
      };

      public struct trcHeaderFields
      {
            public string totalLength; //0x9e10+0x0b+lenOfAd*2 "#...."
            public int allDataLength; //2*lenOfAd(bytes)
            public int timeDataLength; //lenOfAd;
            public int sampleDataLength; //lenOfAd;
            public int pntsPerScreen; //lenfOfAd-2;
            public int lastvalidPnts; //lenOfAd-1
            public float vertical_gain; //垂直增益
            public UInt32 vertical_offset; //垂直偏移
            public UInt32 max;
            public UInt32 min;
            public float horizInterval; //采样率
            public double horizOffset; //中心点
            public double pixelOffset; //又一个水平偏移
            public float horiz_uncertainty; //samplerate/4
            public UInt16 timeBase; //水平档位
            public UInt16 fixed_Vert_Gain; //垂直档位
      };

      public static Dictionary<string, trc_field_define> dicOfFields = new Dictionary<string, trc_field_define>() { };


      static public bool WriteTrcFromCsv(float sampleRate, float volPerAd, uint[] sampleData, FileInfo fi)
      {
            bool ret= false;

            /*
             * %Header
               %用户文本块
                  TEXT % 视上面定义的长度而定
               % TRIGTIME
                  TRIGGER_T % 8B f 原名结尾是TIME,但与前面定义重复,故改为T
                  TRIGGER_OFFSET % 8B f
               % RISTIME
                  RIS_OFFSET % 8B f
               % DATA_ARRAY_1
                  DATA_ARRAY_1
               % DATA_ARRAT_2
                  DATA_ARRAY_2
               % SIMPLE
                  SIMPLE int16模式
               % DUAL
                  版权声明:本文为CSDN博主「Surrea1」的原创文章,遵循CC 4.0 BY - SA版权协议,转载请附上原文出处链接及本声明。
                  原文链接:https://blog.csdn.net/Surrea1/article/details/126807087
            */
            try
            {
                int totallength = lecroy_trc_header.Length + 2 * sampleData.Length - 11; //no 11 more
                StringBuilder sb = new StringBuilder();
                sb.AppendFormat("#9{0:000000000}", totallength);

                trcHeaderFields headerFields;
                headerFields.totalLength = sb.ToString();
                headerFields.timeDataLength = sampleData.Length;
                headerFields.sampleDataLength = sampleData.Length;
                headerFields.allDataLength = sampleData.Length * 2; //in bytes.
                headerFields.horizInterval = sampleRate;
                headerFields.horizOffset = 0;
                headerFields.horiz_uncertainty = sampleRate / 4;
                headerFields.pixelOffset = 0;
                headerFields.pntsPerScreen = sampleData.Length;
                headerFields.lastvalidPnts = sampleData.Length-1;
                headerFields.vertical_gain = volPerAd; //垂直增益
                headerFields.vertical_offset = 0; //垂直偏移
                headerFields.timeBase = 15;
                headerFields.fixed_Vert_Gain = 1; //垂直增益

                byte[] header = new byte;
                for (int i = 0; i < header.Length; ++i)
                {
                  header = 0;
                }
                lecroy_trc_header.CopyTo(header, 0);


                if (dicOfFields.Count == 0)
                {
                  foreach (trc_field_define i in trc_header_fields)
                  {
                        if (dicOfFields.ContainsKey(i.standardName)) continue;
                        dicOfFields.Add(i.standardName, i);
                  }
                }
                Encoding.ASCII.GetBytes(headerFields.totalLength).CopyTo(header, dicOfFields["totalLength"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.timeDataLength).CopyTo(header, dicOfFields["timeDataLength"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.sampleDataLength).CopyTo(header, dicOfFields["sampleDataLength"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.allDataLength).CopyTo(header, dicOfFields["allDataLength"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.horizInterval).CopyTo(header, dicOfFields["horizInterval"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.horizOffset).CopyTo(header, dicOfFields["horizOffset"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.horiz_uncertainty).CopyTo(header, dicOfFields["horiz_uncertainty"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.pixelOffset).CopyTo(header, dicOfFields["pixelOffset"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.pntsPerScreen).CopyTo(header, dicOfFields["pntsPerScreen"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.lastvalidPnts).CopyTo(header, dicOfFields["lastvalidPnts"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.vertical_gain).CopyTo(header, dicOfFields["vertical_gain"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.vertical_offset).CopyTo(header, dicOfFields["vertical_offset"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.timeBase).CopyTo(header, dicOfFields["timeBase"].offetIdxbase0);
                BitConverter.GetBytes(headerFields.fixed_Vert_Gain).CopyTo(header, dicOfFields["fixed_Vert_Gain"].offetIdxbase0);

                FileStream fs = new FileStream(fi.FullName, FileMode.OpenOrCreate, FileAccess.Write);
                BinaryWriter bw = new BinaryWriter(fs);

                /*(byte[] zero24 = new byte;
                for (int i = 0; i < zero24.Length; ++i)
                {
                  zero24 = 0;
                }
                bw.Write(zero24);*/
               
                UInt16 min = UInt16.MaxValue;
                UInt16 max = UInt16.MinValue;
                foreach (uint data in sampleData)
                {
                  UInt16 d16 = (UInt16)data;
                  if(min>d16) min = d16;
                  if(max<d16) max = d16;
                }
                BitConverter.GetBytes((float)min).CopyTo(header, dicOfFields["min"].offetIdxbase0);
                BitConverter.GetBytes((float)max).CopyTo(header, dicOfFields["max"].offetIdxbase0);
                bw.Write(header);
                foreach (uint data in sampleData)
                {
                  UInt16 d16 = (UInt16)data;
                  bw.Write(BitConverter.GetBytes(d16));
                }

                bw.Flush();
                fs.Close();
                ret = true;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
                return false;
            }

            return ret;

      }
    }
}

python代码中,波形抽样,扩容的代码是第一版的代码,后续改进的部分欠奉。
C#代码中.csv的读取代码欠奉。

最终在力科分析软件中运行的效果如下:

时基的部分做了调整,但是ad值部分,没有对照档位做适配。有兴趣的同志可以在这些代码的基础上继续工作。

Pages: [1]
View full version: 汉泰.doc=>力科.trc转换程序