Чтение данных из файла.hpf
Я использую Quickdaq
получать данные от моего датчика; выход является .hpf
файл
Я хочу прочитать данные из этого файла в python
& matplotlib
применить некоторый анализ сигналов.
Как я могу читать (или конвертировать в .csv
) .hpf
файл с питоном (или любым другим языком)?
Я нашел это в Интернете, но я не знаю, как его использовать, если это последнее решение?
2 ответа
Я предполагаю, что это немного устарело для исходного плаката, однако, если у кого-то еще возникнет эта проблема, я только что написал сценарий для извлечения информации и данных из этих файлов, однако он тестируется только на данных одного канала, я нет многоканальных данных для тестирования.
https://github.com/jogrundy/Read_QuickDAQ_.hpf
Это началось как перевод кода MATLAB с https://www.datatranslation.de/Download/Demos/Hpf2Matlab_Rev2_0.m
Надеюсь это поможет.
Разработчики программного обеспечения QuickDAQ, похоже, предоставили решение, см. Этот скрипт Python в разделе загрузок на домашней странице QuickDAQ .
Точные спецификации для
.hpf
Тип файла предоставлен компанией Data Translation по этой ссылке в формате pdf .
В случае, если ссылка на скрипт python в будущем станет неработоспособной, скрипт преобразования, написанный Майклом Бюргином, воспроизводится ниже.
###########################################################################
#
# Author: Measurement Computing GmbH
# Michael Buergin
# Date: 02.11.2017
# Version: 1.0
# Description:
# Python Converter for Data Translation's HPF-file format.
# Can convert a single file or a complete directory
# REMARKS:
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Changes: --
#
#
# ConvertHPFData_Folder
# Input Parameter :
# folder_in = Complete path to the folder with HPF-file
# folder_out = Complete path to store ASCII-files (if None; new "ASCII"-folder is created in folder_in)
# suppress_print = suppress print of hpf-file-data
#
# WARNING: existing txt-files will be overwritten!
#
# ConvertHPFData
# Input Parameter :
# InputFile = Complete path to the input HPF-file.
# OutputFile = Complete path to the output ASCII-file.
# SelectedChannel = Channel to read from the HPF-file. 1 as first channel.
# suppress_print = suppress print of hpf-file-data
# Output Data:
# ReturnData = Matrix with all Data for the selected channel
# OutputFile = ASCII-file with all Data for the selected channel
###########################################################################
import numpy as np
import struct
import os
def ConvertHPFData_Folder(folder_in=None, folder_out=None, suppress_print=True, SelectedChannel=None):
if folder_out == None: folder_out=folder_in + '\\ASCII'
all_hpf_files = [fn for fn in os.listdir(folder_in)
if any(fn.endswith(ext) for ext in 'hfp')]
if not os.path.isdir(folder_out): os.mkdir(folder_out)
i_file = 1
for file in all_hpf_files:
ConvertHPFData(SelectedChannel='all',
InputFile=folder_in+'\\'+file,
OutputFile=folder_out+'\\'+file[:-3]+'txt',
suppress_print=suppress_print)
print('last file: %s (%i/%i)' % (file, i_file, len(all_hpf_files)))
i_file +=1
print('all done :)')
def ConvertHPFData(InputFile=None,OutputFile=None,SelectedChannel=None,suppress_print=False):
if not suppress_print: print('-- Start')
ReturnData=[]
with open(InputFile, mode='rb') as in_file: # b -> binary
fileContent = in_file.read()
if OutputFile!=None: out_file = open(OutputFile, 'w')
if SelectedChannel == 'all':
SelectedChannelAll = 1
ChannelError = False
while ChannelError == False:
[result_tmp, result_name_tmp, ChannelError] = ReadHPFData(SelectedChannel=SelectedChannelAll,
fileContent=fileContent,
out_file=out_file,
OutputFile=OutputFile,
AllCh=True,
suppress_print=True)
if ChannelError == False:
if SelectedChannelAll==1:
ReturnData = result_tmp
Result_Name = [result_name_tmp]
else:
ReturnData = np.append(np.array(ReturnData), np.array([result_tmp[1,:]]), axis=0)
Result_Name.append(result_name_tmp)
if not suppress_print: print(Result_Name)
SelectedChannelAll += 1
else:
[ReturnData, Result_Name, ChannelError] = ReadHPFData(SelectedChannel=SelectedChannel,
fileContent=fileContent,
out_file=out_file,
OutputFile=OutputFile,
AllCh=False)
Result_Name = [Result_Name]
in_file.close()
if OutputFile!=None:
if SelectedChannel != 'all' and ChannelError: out_file.close()
else:
out_file.write('time\t')
for i_channel in range(len(Result_Name)):
out_file.write(Result_Name[i_channel]+'\t')
out_file.write('\n')
for i_ReturnData in range(len(ReturnData[0, :])):
for i_channel in range(len(ReturnData[:, 0])):
out_file.write(('%f\t') % (ReturnData[i_channel, i_ReturnData]))
out_file.write('\n')
out_file.close()
if not suppress_print: print('-- Finish')
return ReturnData
def char_tuple_2_str(tuple):
string = ""
for chars in tuple:
string = string + chars.decode('utf-8')
return string
def find_all_str(string,sub):
index = string.find(sub)
if index == -1: return [-1]
indices = [index]
while True:
index = string.find(sub, index+1)
if index == -1: return indices
indices.append(index)
return indices
def ReadHPFData(SelectedChannel=None,fileContent=None, out_file=None, OutputFile=None, AllCh=None, suppress_print=False):
if AllCh and SelectedChannel == 1:
flag_write = True
else:
flag_write = False
ReturnData=[]
pos = 0
off = 0
i_line = 0
while i_line <= len(fileContent) - 1:
in_chunkID = struct.unpack('q', fileContent[i_line:i_line + 8])[0];
i_line = i_line + 8
off = struct.unpack('q', fileContent[i_line:i_line + 8])[0];
i_line = i_line + 8
if i_line == len(fileContent) or off == 0:
break
if 4096 == in_chunkID:
if not suppress_print: print('- Parsing Header Chunk')
in_ChratorID = char_tuple_2_str(struct.unpack('c' * 4, fileContent[i_line:i_line + 4]));
i_line = i_line + 4
in_fileVersion = struct.unpack('q', fileContent[i_line:i_line + 8])[0];
i_line = i_line + 8
in_indexChunkOffset = struct.unpack('q', fileContent[i_line:i_line + 8])[0];
i_line = i_line + 8
len_in_XMLdata = off - (i_line - pos)
in_XMLdata = char_tuple_2_str(
struct.unpack('c' * len_in_XMLdata, fileContent[i_line:i_line + len_in_XMLdata]));
i_line = i_line + len_in_XMLdata
start = in_XMLdata.find('<RecordingDate>')
stop = in_XMLdata.find('</RecordingDate>')
Information = in_XMLdata[start + 15:stop - 1]
if not suppress_print: print('RecordingDate: ' + Information)
if OutputFile != None and flag_write: out_file.write('RecordingDate: ' + Information + '\n')
Result_RecordingDate = Information
else:
if 8192 == in_chunkID:
if not suppress_print: print('- Parsing Channel Information Chunk')
in_groupID = struct.unpack('l', fileContent[i_line:i_line + 4])[0];
i_line = i_line + 4
in_numberOfChannals = struct.unpack('l', fileContent[i_line:i_line + 4])[0];
i_line = i_line + 4
len_in_XMLdata = off - (i_line - pos)
in_XMLdata = char_tuple_2_str(
struct.unpack('c' * len_in_XMLdata, fileContent[i_line:i_line + len_in_XMLdata]));
i_line = i_line + len_in_XMLdata
start = find_all_str(in_XMLdata, ('<Name>'))
stop = find_all_str(in_XMLdata, ('</Name>'))
if len(start) < SelectedChannel or SelectedChannel<=0:
if AllCh == False:
if not suppress_print: print('\nWrong channel selected!')
if not suppress_print: print('\npossible channels: %i ... %i' % (1, len(start)))
if OutputFile != None:
out_file.write('\nWrong channel selected!')
out_file.write('\npossible channels: %i ... %i' % (1, len(start)))
return 0, 0, True
if OutputFile != None: out_file.write('Total Channel: ' + str(len(start)) + '\n')
if not suppress_print: print('Total Channel: ', str(len(start)))
Ch_offset = np.zeros(len(start))
Ch_length = np.zeros(len(start))
# Store Channel in return struct
Result_Channel = SelectedChannel
if not suppress_print: print('Selected Channel Information:')
if OutputFile != None: out_file.write('Selected Channel Information:\n')
Information = in_XMLdata[start[SelectedChannel - 1] + 6:stop[SelectedChannel - 1]]
if not suppress_print: print('Name: ', Information)
if OutputFile != None: out_file.write('Name: ' + Information + '\n')
Result_Name = Information
start = find_all_str(in_XMLdata, ('<Unit>'))
stop = find_all_str(in_XMLdata, ('</Unit>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 6:stop[SelectedChannel - 1]]
if not suppress_print: print('Unit: ', Information)
if OutputFile != None: out_file.write('Unit: ' + Information + '\n')
Result_Unit = Information
start = find_all_str(in_XMLdata, ('<ChannelType>'))
stop = find_all_str(in_XMLdata, ('</ChannelType>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 13:stop[SelectedChannel - 1]]
if not suppress_print: print('ChannelType: ', Information)
if OutputFile != None: out_file.write('ChannelType: ' + Information + '\n')
Result_ChannelType = Information
start = find_all_str(in_XMLdata, ('<AssignedTimeChannelIndex>'))
stop = find_all_str(in_XMLdata, ('</AssignedTimeChannelIndex>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 26:stop[SelectedChannel - 1]]
if not suppress_print: print('AssignedTimeChannelIndex: ', Information)
if OutputFile != None: out_file.write('AssignedTimeChannelIndex: ' + Information + '\n')
Result_AssignedTimeChannelIndex = Information
start = find_all_str(in_XMLdata, ('<DataType>'))
stop = find_all_str(in_XMLdata, ('</DataType>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 10:stop[SelectedChannel - 1]]
if not suppress_print: print('DataType: ', Information)
if OutputFile != None: out_file.write('DataType: ' + Information + '\n')
Result_DataType = Information
start = find_all_str(in_XMLdata, ('<DataIndex>'))
stop = find_all_str(in_XMLdata, ('</DataIndex>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 11:stop[SelectedChannel - 1]]
if not suppress_print: print('DataIndex: ', Information)
if OutputFile != None: out_file.write('DataIndex: ' + Information + '\n')
Result_DataIndex = float(Information)
start = find_all_str(in_XMLdata, ('<StartTime>'))
stop = find_all_str(in_XMLdata, ('</StartTime>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 11:stop[SelectedChannel - 1]]
if not suppress_print: print('StartTime: ', Information)
if OutputFile != None: out_file.write('StartTime: ' + Information + '\n')
Result_StartTime = Information
start = find_all_str(in_XMLdata, ('<TimeIncrement>'))
stop = find_all_str(in_XMLdata, ('</TimeIncrement>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 15:stop[SelectedChannel - 1]]
if not suppress_print: print('TimeIncrement: ', Information)
if OutputFile != None: out_file.write('TimeIncrement: ' + Information + '\n')
Result_TimeIncrement = float(Information)
start = find_all_str(in_XMLdata, ('<RangeMin>'))
stop = find_all_str(in_XMLdata, ('</RangeMin>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 10:stop[SelectedChannel - 1]]
if not suppress_print: print('RangeMin: ', Information)
if OutputFile != None: out_file.write('RangeMin: ' + Information + '\n')
Result_RangeMin = float(Information)
start = find_all_str(in_XMLdata, ('<RangeMax>'))
stop = find_all_str(in_XMLdata, ('</RangeMax>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 10:stop[SelectedChannel - 1]]
if not suppress_print: print('RangeMax: ', Information)
if OutputFile != None: out_file.write('RangeMax: ' + Information + '\n')
Result_RangeMax = float(Information)
start = find_all_str(in_XMLdata, ('<DataScale>'))
stop = find_all_str(in_XMLdata, ('</DataScale>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 11:stop[SelectedChannel - 1]]
if not suppress_print: print('DataScale: ', Information)
if OutputFile != None: out_file.write('DataScale: ' + Information + '\n')
Result_DataScale = float(Information)
start = find_all_str(in_XMLdata, ('<DataOffset>'))
stop = find_all_str(in_XMLdata, ('</DataOffset>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 12:stop[SelectedChannel - 1]]
if not suppress_print: print('DataOffset: ', Information)
if OutputFile != None: out_file.write('DataOffset: ' + Information + '\n')
Result_DataOffset = float(Information)
start = find_all_str(in_XMLdata, ('<SensorScale>'))
stop = find_all_str(in_XMLdata, ('</SensorScale>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 13:stop[SelectedChannel - 1]]
Sens_Scale = Information
if not suppress_print: print('SensorScale: ', Information)
if OutputFile != None: out_file.write('SensorScale: ' + Information + '\n')
Result_SensorScale = float(Sens_Scale)
start = find_all_str(in_XMLdata, ('<SensorOffset>'))
stop = find_all_str(in_XMLdata, ('</SensorOffset>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 14:stop[SelectedChannel - 1]]
SensorOffset = Information
if not suppress_print: print('SensorOffset: ', Information)
if OutputFile != None: out_file.write('SensorOffset: ' + Information + '\n')
Result_SensorOffset = float(SensorOffset)
start = find_all_str(in_XMLdata, ('<PerChannelSampleRate>'))
stop = find_all_str(in_XMLdata, ('</PerChannelSampleRate>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 22:stop[SelectedChannel - 1]]
if not suppress_print: print('PerChannelSampleRate: ', Information)
if OutputFile != None: out_file.write('PerChannelSampleRate: ' + Information + '\n')
Result_PerChannelSampleRate = Information
start = find_all_str(in_XMLdata, ('<PhysicalChannelNumber>'))
stop = find_all_str(in_XMLdata, ('</PhysicalChannelNumber>'))
Information = in_XMLdata[start[SelectedChannel - 1] + 23:stop[SelectedChannel - 1]]
if not suppress_print: print('PhysicalChannelNumber: ', Information)
if OutputFile != None: out_file.write('PhysicalChannelNumber: ' + Information + '\n\n')
Result_PhysicalChannelNumber = Information
else:
if 12288 == in_chunkID:
if not suppress_print: print('- Parsing Data Chunk')
in_chunksize = off
in_groupID = struct.unpack('l', fileContent[i_line:i_line + 4])[0];
i_line = i_line + 4
in_dataStartIndex = struct.unpack('q', fileContent[i_line:i_line + 8])[0];
i_line = i_line + 8
in_chanalDataCount = struct.unpack('l', fileContent[i_line:i_line + 4])[0];
i_line = i_line + 4
for count in range(in_chanalDataCount):
if count + 1 == (SelectedChannel):
Ch_offset[count] = int(struct.unpack('l', fileContent[i_line:i_line + 4])[0]);
i_line = i_line + 4
Ch_length[count] = int(struct.unpack('l', fileContent[i_line:i_line + 4])[0]);
i_line = i_line + 4
else:
i_line = i_line + 8
ignoreCount = 0
for count in range(in_chanalDataCount):
if count + 1 == (SelectedChannel):
divider = 8
i_line = i_line + int(Ch_offset[count]) - int(32 + (in_chanalDataCount * 8))
tmpData = list(struct.unpack('d' * int(Ch_length[count] / divider),
fileContent[int(i_line):int(i_line + Ch_length[count])]));
i_line = i_line + int(Ch_length[count])
# Append Data
ReturnData.extend(tmpData)
else:
ignoreCount = ignoreCount + 1
else:
if 28672 == in_chunkID:
if not suppress_print: print('- Parsing Undocumented Part')
i_line = i_line + 8
Position = off - (i_line - pos)
i_line = i_line + Position
pos = i_line
ReturnData = np.array(ReturnData) * Result_SensorScale + Result_SensorOffset
Result_Time = np.array(float(Result_TimeIncrement)*(np.array(range(0,len(ReturnData)))))
ReturnData = np.append([Result_Time], [ReturnData], axis=0)
return ReturnData, Result_Name, False
if __name__ == '__main__':
ConvertHPFData_Folder(folder_in=r"C:\Users\mbuergin\AppData\Local\Data Translation\QuickDAQ\Data",
folder_out=r"C:\Users\mbuergin\AppData\Local\Data Translation\QuickDAQ\Data",
SelectedChannel='all')