首页 > 解决方案 > 如何在 python 中打开 .ProcSpec 文件?

问题描述

我有从 SpectraSuite 软件(已处理光谱,OOI 二进制文件)获得的数据,我尝试使用

f = open(r'C:\Users\path/file.ProcSpec', 'rb')
    file_content = f.read()
f.close()

但 file_content 是类似“b'PK\x03\x04\x14\x00\x08\x00\x08\x007t\x...”的数据。如何将这种类型的文件作为表格数据打开?

标签: python

解决方案


方法一

在 Spectra Suite 中,您可以再次打开并导出它们,同时将文件类型设置为Tab Delimited. 然后您应该能够使用 csv lib 导入它们。

在此处输入图像描述

在此处查看如何打开 csv 文件。

直接从 Python

是一个 Matlab 代码,它可以满足您的需求。

从 Matlab 代码中,我们看到 OOI 格式是一个压缩的 xml。此外,似乎有些字符无法被 XML 解析器解析。

知道了这一点,可以使用以下代码打开文件。请注意,这是一种无需错误处理或彻底测试的快速实现。

import os
import shutil
import glob
import xml.etree.ElementTree as ET
import numpy as np

def parseNodeText(node):
        # bool
        nodeText = node.text
        if 'true' == nodeText or 'false' == nodeText:
            return nodeText == 'true'
        # int
        try:
            return int(nodeText)
        except:
            pass
        # float
        try:
            return float(nodeText)
        except:
            pass
        # text
        return nodeText

def extractArrayFromNode(node):
    arr = []
    for val in node:
        arr.append(parseNodeText(val))
    if 'double' in node[0].tag:
        dt = np.float32
    elif 'int' in node[0].tag:
        dt = np.int32
    else:
        dt = np.float32
    return np.array(arr,dtype=dt)
    

def readProcSpecFile(filePath):
    
    dirName = os.path.dirname(filePath)
    
    tmpdir = os.path.join(dirName,'tmp')
    os.makedirs(tmpdir, exist_ok=True)
    tmpFile= os.path.join(tmpdir,'tmp.zip')
    shutil.copy(filePath, tmpFile)
    shutil.unpack_archive(tmpFile, tmpdir)
    
    for f in glob.glob(tmpdir+r'\*.xml'):
        if 'OOISignatures.xml' in f:
            continue
        
        with open(f,"rb") as fi:
            s = fi.read()
       
        badChars = [b'\xa0',b'\x89',b'\x80'] 
        for c in badChars:
            s = s.replace(c,b' ')
            
        with open(f,"wb") as fi:
            fi.write(s)
        
        tree = ET.parse(f.encode("utf-8"))
        root = tree.getroot()
          
        result = [] 
        for spectra in root[0]:
            s = spectra[0]
            spect = {}
            for node in spectra:
                t = node.tag
                n = parseNodeText(node)
                if t == 'pixelValues':
                    spect[t] = extractArrayFromNode(node)
                elif t == 'channelWavelengths':
                    spect[t] = extractArrayFromNode(node)
                elif t == 'acquisitionTime':
                    times =  {}
                    for val in node:
                        times[val.tag] =  parseNodeText(val)
                    spect[t] = times
                    
                elif t == 'certificates':
                    pass
                elif t == 'channelCoefficients':
                    pass
                
                else:
                    spect[t] = n
            result.append(spect)  
        shutil.rmtree(tmpdir)
        return result

下面是一个关于如何使用它的例子:

iFile = r'your\path\file.ProcSpec'
spects = readProcSpecFile(iFile)
spect = spects[0]  
print(spect.keys())
wavelength = spect['channelWavelengths']
pixelValues = spect['pixelValues']

这是输出:

dict_keys(['saturated', 'integrationTime', 'strobeEnabled', 'strobeDelay', 'pixelValues', 'acquisitionTime', 'boxcarWidth', 'scansToAverage', 'correctForElectricalDark', 'correctForNonLinearity', 'correctForStrayLight', 'rotationEnabled', 'userName', 'channelWavelengths', 'channelNumber', 'channelStabilityScanEnabled', 'channelExternalTriggerEnabled', 'laserWavelength', 'interlock', 'numberOfPixels', 'numberOfDarkPixels', 'spectrometerSerialNumber', 'spectrometerFirmwareVersion', 'spectrometerClass', 'spectrometerPlugins', 'spectrometerNumberOfChannels', 'spectrometerMaximumIntensity', 'spectrometerMinimumIntegrationTime', 'spectrometerMaximumIntegrationTime', 'spectrometerIntegrationTimeStep', 'spectrometerIntegrationTimeBase', 'spectrometerNumberOfPixels', 'spectrometerNumberOfDarkPixels'])

In [2]:wavelength
Out[2]:array([ 199.51251,  199.98462,  200.4567 , ..., 1116.266  , 1116.6813 ,
       1117.0964 ], dtype=float32)

In [3]:pixelValues
Out[3]:array([64000. ,  1958.1,  1958.1, ...,  1957.1,  1957.1,  1957.5],
      dtype=float32)

这是wavelengthvalues数组的图:

在此处输入图像描述


推荐阅读