Как декодировать сжатые двоичные файлы .RAW из LTspice с помощью python - PullRequest
0 голосов
/ 16 октября 2019

Я пытаюсь читать из .raw LTSPice файлов. На панели управления LTSPice есть возможность переключения между ASCII и двоичным сжатием. ASCII читается без проблем, но имеет недостатки в размере и производительности, и именно поэтому я хочу использовать двоичное сжатие. Есть возможность выбрать сжатие 2-го порядка, и это цель. LTSpice выдает в качестве выходных файлов .raw, а файл ASCII имеет значения напряжений и токов, но в двоичном файле есть символы, которые я не могу декодировать.

Сначала я попытался открыть файлы .raw с помощью notepad ++,Notpad ++ показывает в левом нижнем углу UTF-8, когда я открываю файлы ASCII .raw, и UCS-2 Little Endian, когда открываю двоичные распакованные файлы .raw. Я пробовал с другой кодировкой, такой как UTF-16le, ISO-8859-1 ... фактически я печатаю все кодеки и пробовал с ними:

import codecs
print(dir(codecs))

Кроме того, я пробовал без спецификации. Я нашел это, и он не дал результатов для меня:

import codecs
encoded_text = open('Circuit_binary_Transient.raw', 'rb').read()    #should read in binary mode to get the BOM correctly
bom= codecs.BOM_UTF16_LE                                      #print dir(codecs) for other encodings
assert encoded_text.startswith(bom)                           
encoded_text= encoded_text[len(bom):]                         #strip away 
decoded_text= encoded_text.decode('utf-16le')
print(decoded_text)

Я обнаружил, что Zlib - обычное сжатие, и я попытался выяснить, на каких позициях в моем файле происходит сжатие, но без результатов. Я использовал:

import zlib
from glob import glob

def zipstreams(filename):
    """Return all zip streams and their positions in file."""
    with open(filename, 'rb') as fh:
        data = fh.read()
    i = 0
    while i < len(data):
        try:
            zo = zlib.decompressobj()
            yield i, zo.decompress(data[i:])
            i += len(data[i:]) - len(zo.unused_data)
        except zlib.error:
            i += 1

for i, data in zipstreams("Circuit_binary_Transient.raw.raw"):
    print (i, len(data))

Я всегда получаю 0 для len (data).

Я нашел этот скрипт, но без реализации декодирования двоичных .raw файлов: http://www2.ee.unsw.edu.au/~tlehmann/ltspy.py
Кроме того, я нашел решение для Matlab, LTSpice2Matlab, Пола Вагнера (ltspice reader for Matlab), но оно мне нужно для python, и из этого конкретного сценария я не могу найти, какая кодировка используется. Я обнаружил, что для двоичных распакованных файлов Пол Вагнер использовал интерполяцию, чтобы получить больше точек, а затем преобразовать в читаемый формат.

На самом деле, я использовал этот код для чтения .raw файлов:

data = fo.read() # Binary data read
fo.close()
line = str(data, encoding='utf-16le')
print(line)

Когда я использовал ASCII-файлы .raw и UTF8, у меня в конце есть текст, но когда я использовал двоичные сжатые файлы .raw, я не могу найти, как декодировать файл в читаемом формате.

Это то, что у меня сейчасв файле .raw из LTSpice (после текста «Binary:»):

栋㲚朎㲚鸞㕼鸞㕼鸞땼䕘퇠≄뻕襾㷨⁄㷨⡜㚾⡜㚾⡜뚾䕘퇠≄㻥䏨㹔ᙘ㹓㜬㜬뜬岓逇Ⳡ㻵◲㻇㯋㻃㞟㞟랟ጟ箽㼄籼㼯덌㼩Ӏ㠋Ӏ㠋Ӏ렋괄蝄㼎ڕ㽦럍㽢먵㠹먵㠹먵령귴脍侧㼑з㽴鍰㽲럜㡆럜㡆럜롆쵺튆㼒㽺땺㽹迀㡌迀㡌迀롌偵姏䰦㼔㽾枎㽽雈㡏雈㡏雈롏䰼ᬇⅤ㼖쵅㽿ᦊ㽾⢖㡐⢖㡐⢖롐暾좳죯㼗챭㽼錒㽺䕈㡍䕈㡍䕈롍얳✀礦㼚嘻㽰㽫㿃㡁㿃㡁㿃롁먬쬥㼞㽉뙵㽁낁㠞낁㠞낁렞袨�봜㼢睿㻔瘵㻄㞠㞠랠嘈䆬흞㼦㷧븥譻븠蒱뜃蒱뜃蒱㜃빝袏噥㼪뼝뼙㼆럼㼆럼㼆㟼玵嬆㼬ﵠ뽐】뽏멬렩멬렩멬㠩떋Ҕ덭㼭葔뽩뽨챢렾챢렾챢㠾넼ꧼ㼮쏐뽵뼃뽵傴롉傴롉傴㡉뮷惵㼯툡뽻뽻婇롎婇롎婇㡎�ﶻሣ㼰姢뽿ᚶ뽿롐롐㡐誔

Я ожидаю декодировать и прочитать это, и я полагаю, что я должен получить то же самое, что и в файлах .raw ASCII, таких как:

0       0.000000000000000e+000  
    1.884843971540818e-002  
    1.884796850054908e-002  
    9.423984250366810e-007  
    9.423984250274539e-007  
    -9.423984250328532e-007  
1       3.951925877448456e-008  
    1.959322256186405e-002  
    1.959271263253092e-002  
    9.796356316741367e-007  
    9.796356316265457e-007  
    -9.796356317259836e-007  
2       1.185577763234539e-007  
    2.108275522427772e-002  
    2.108216492289399e-002  
    1.054108246213077e-006  
    1.054108246144700e-006  
    -1.054108246245633e-006

Буду признателен за любую помощь. Цель - прочитать сжатый двоичный файл .raw LTSpice.

Ответы [ 2 ]

1 голос
/ 16 октября 2019

Заголовок двоичного файла .RAW из LTSpice может быть декодирован с помощью UTF-16. Если попытаться преобразовать весь двоичный файл RAW, то только заголовок будет преобразован в текст. Последними символами, успешно преобразованными в текст с UTF-16, являются «Binary:». После этого нужно получить «китайские символы» или что-то еще, что не читается.

Я использовал шестнадцатеричный редактор и сравнил оба файла - RAW ASCII и двоичный файл RAW для одной и той же электрической цепи. В файле ASCII можно найти «Значения:» вместо «Бинарный:», и после этого десятичные значения. Таким образом, можно сравнить двоичный код с помощью шестнадцатеричного редактора и реальных значений в файле RAW ASCII.

После сравнения я успешно декодировал двоичный файл RAW. Все написанное ниже в шестнадцатеричном виде. У меня было 6 переменных. Это действительно для доменов: развертка по постоянному току, операция по постоянному току, временная передача и передача по постоянному току (для анализа переменного тока и шума всегда используется декодирование с двойной точностью 2 x 8 байт).

  1. После «Binary:» отображаютсявсегда 3 байта: 00 0A 00 (0A - перевод строки);
  2. Тогда есть 8 байтов, которые дают правильное значение, если преобразовать его в двойную (float64) точность;
  3. Тогда яимеют 4 байта, которые дают правильное значение, если преобразовать его в единичную (float32) точность
  4. 4 байта, которые дают одно значение, повторяются 5 раз (у меня есть 6 переменных - заголовок "Нет. Переменные:")
  5. Пункты 2., 3. и 4. повторяются до тех пор, пока не будет выполнено число из заголовка для "№ очков:".

Я использовал LTSpice XVII. Кроме того, я использовал HxD Hex Editor https://mh -nexus.de / en / hxd /

РЕДАКТИРОВАТЬ: Очень важно: Порядок байтов - Little endian!
Это означает, что порядок байтовв шестнадцатеричном виде - AA 77 B8 A2, что его следует конвертировать в обратном порядке - A2 B8 77 AA. Таким образом, одинарная (float32) точность для AA 77 B8 A2, преобразованного в десятичную, составляет -2.2e-13, а для A2 B8 77 AA, преобразованного в десятичную, - -5e-18.

1 голос
/ 16 октября 2019

Notpad ++ показывает в левом нижнем углу UTF-8, когда я открываю файлы ASCII .raw, и UCS-2 Little Endian, когда открываю двоичные распакованные файлы .raw. "

Это нормально,UTF-8 - это кодировка text , она просто связывает последовательность байтов с каким-либо символом. Сырые двоичные файлы не имеют фиксированной структуры или кодировки, потому что они содержат двоичные данные: например,разницы между строкой "3.1415926535" (это 12 байт в UTF-8) и необработанным двоичным представлением с плавающей точкой этого значения (которое умещается в 4 байта). Если вы интерпретируете «необработанные» 4 байта с плавающей точкой как текст, выВы получите либо текстовый вывод мусора, либо ошибку декодирования в Unicode. Для необработанных файлов конкретный формат данных и значение каждого байта задается программным обеспечением, которое их генерирует.

Обычно вы должны искатьСпецификация файла LTSpice raw, поймите, как устроены данные, и напишите себе парсер для этого. Но так как это python, кто-то уже сделал это дляВы и сделали пакет, который вы можете установить через pip, посмотрите этот пакет и его примеры, он должен быть довольно простым в использовании.


Обновление

В эта ссылка они заявляют, что необработанный двоичный формат официально не раскрывается и может измениться в любое время (хотя это не произошло в течение последних 15 лет).

Сам формат представляет собой заголовок UTF-16, за которым следуетпо необработанным двоичным данным. Когда вы говорите:

Это то, что у меня есть в настоящее время в файле .raw из LTSpice (после текста «Binary:»): [...]

Этонеобработанные данные (декодированные в UTF-16, что, как вы видите, является бессмысленным текстом). Эти необработанные данные представляют собой упакованный список значений переменной в порядке, определенном в заголовке , повторяясь столько раз, сколько у вас есть в данных. Время кодируется в double (т. Е. 8 байтов), все остальное - если только вы не принудите его удвоить - находится в float (4 байта). То, что вы должны сделать, это:

1) Разобрать список переменных и вычислить, как долго будет длиться одна запись (например, 8 + 4 * num_of_variables)

2) взять байтовые данные из«двоичная» строка до конца файла и разбить ее на куски той длины, которую вы получите на шаге 1

3) интерпретировать байты в записи соответственно

...