2013-07-02 1 views
1

У меня есть очень большое количество файлов, которые были сохранены в двоичном виде в Labview, где каждый столбец является кластером временной метки, за которым следует вектор синглов.Как LabView сохраняет данные кластера в двоичном файле и как его читать в MATLAB?

Я прочитал каждый файл данных в Matlab с использованием r2013a

fid = fopen(filename); 
data = fread(fid,[N M],'*single',0,'b'); 
fclose(fid); 

где я предварительно рассчитать размер входного массива N, M. Так как я знаю, что эти данные должны выглядеть, я понял, что data(1:5,:) где спрятана данные метки времени, но, похоже, что-то подобное для M = 1:

[0 -842938.0625 -1.19209289550781e-07 0 4.48415508583941e-42] 

Первый элемент всегда 0, второй элемент монотонно уменьшается с постоянным размером шага, третий, по-видимому, является бистабильным, переворачивается назад и вперед между двумя очень маленькими значениями, четвертый всегда равен 0, а пятый также постоянный.

Я предполагаю, что это связано с тем, как Labview кодирует даты, но мой google-fu не помог мне понять это.

Чтобы сделать это более общий вопрос, то:

Как Labview кодирует временную метку кластера, когда он сохраняет в двоичный файл, и как я могу прочитать его и перевести его в соответствующее число в другом программировании язык, такой как Matlab?

EDIT: Для потомков, вот мой окончательный код (прилагается к коду выше):

datedata = data(5:-1:1,:); 
data(1:5,:) = []; 

dms = typecast(reshape(datedata(2:3,:),[],1),'uint64'); 
dsecs = typecast(reshape(datedata(4:5,:),[],1), 'int64'); 

timestamp = datenum(1904,1,1) + (double(dsecs) + double(dms)*2^-64)/(3600*24); 

В коде @Floris размещены от Mathworks, они типаж прямо в два раза, но когда я Пробовал, я получил мусор. Чтобы получить правильную дату, мне пришлось сначала преобразовать в целое число, а затем удвоить. Так как мое узкое место находится в линии fread (0,3 секунды для считывания с внешнего диска), дополнительный шаг по типу незначителен в великой схеме вещей.

Дополнительный столбец 4.5e-42 преобразует в целочисленное значение 3200, количество значений в последующем векторе синглов.

+0

Если у вас есть доступ к коду LabVIEW, вы можете попытаться сохранить эти кластеры в файл как строку или как XML. Я не знаю, насколько велики файлы, но эти форматы будут намного проще читать MATLAB. –

+1

Индивидуальные файлы не такие большие (~ 14 Мб каждый), но их очень много. У меня есть один полностью полный привод 1 ТБ, и я работаю над вторым. Даже если я решил изменить код, эта кошка хорошо вышла из сумки. – craigim

+0

Справа. Похоже, вы застряли с тем, что у вас есть. Для справок в будущем: полезно как можно больше репетировать миграцию данных, когда это возможно, поскольку это такая склонная к ошибкам и трудная операция. –

ответ

2

Это не полный ответ, но он должен помочь (у меня нет ни Labview, ни Matlab, доступных дома, поэтому я не могу проверить это прямо сейчас).

Существует статья в http://www.mathworks.com/matlabcentral/newsreader/view_thread/292060, которая описывает аналогичный вопрос. Пара полезных битов информации, я извлек из этого:

  1. Отметка времени является двойной (не одного)
  2. нужно перевернуть порядок байтов (мало по сравнению с обратным порядком байтов), чтобы иметь смысл вещей

Существует полезный комментарий:

Обратите внимание, что время конвенции LabView является милисекунд с 1 января 1904 года. Вот один подход (может содержать ошибки, но будет указывать вам в правильном направлении ),

Следующий фрагмент кода также Дано:

%% Read in date information 
[ fid, msg ] = fopen(FileName, 'r') ; 
NColumns = 60 ; % Number of data columns - probably different for your 
dataset! 
[a, count] = fread(fid, [ NColumns Inf], '*single') ; % Force data to 
be read into Matlab workspace as singles 
a = a' ; % Convert to data in columns not rows 
% The last two columns of a are the timestamp 
b = fliplr(a(:, end-1:end)) ; % Must swap the order of the columns 
d = typecast(reshape(b',[],1), 'double') ; % Now we can can convert to 
double 
time_local = datenum(1904, 1, 1) + d/(24*3600) ; % Convert from 
seconds to matlab time format 
fclose(fid) ; 

Это выглядит правдоподобно для меня. Дайте мне знать, если это сработает - если нет, я могу помочь отлаживать утром ...

+0

Я отдам это сегодня утром. – craigim

+0

Я не мог заставить его работать, прибегая к стиранию прямо от одного до двойного, мне пришлось сделать single-> int64/uint64-> double. В противном случае это сработало. – craigim

+0

Полезно знать - рад, что это помогло! – Floris

1

Временная метка LabVIEW представляет собой 128-битный тип, состоящий из подписанного 64-битного целого числа, измеряющего смещение за считанные секунды эпоху LabVIEW (1 января 1904 00: 00: 00.00 UTC) и 64-битное целое число без знака, измеряющее дробную секунду. Источник: ni.com.

Порядок байтов файла может зависеть от платформы. Например, время 8: 02: 58,147 AM 3 июля 2013 EDT могут быть сохранены как:

0x 00000000CDF9C372 25AA100000000000 (большой/сети)

или как

0x 000000000010AA25 72C3F9CD00000000 (маленький)

+0

Labview - большой эндиан на всех платформах, но это была полезная находка, так как решение @ Floris не включало второе поле с дробными секундами. – craigim

Смежные вопросы