Найти все различия между файлами .mat

Я ищу способ перечислить различия между двумя файлами .mat, что может быть полезно для многих людей.

Хотя я искал везде, где только мог, я не нашел ничего, что соответствовало бы моим требованиям:

  1. Выберите 2 матовых файла
  2. Найти различия
  3. Сохраните их правильно

Ближе всего я подошёл к visdiff. Пока я остаюсь в Matlab, это позволит мне просматривать различия, но когда я сохраняю результат, он показывает мне только верхний уровень.


Вот упрощенный пример того, как обычно выглядят мои файлы:

a = 6;
b.c.d = 7;
b.c.e = 'x';
save f1
f = a;
clear a
b.c.e = 'y';
save f2
visdiff('f1.mat','f2.mat')

Если я нажму здесь на b, я смогу найти разницу. Однако, если я запущу это и использую «файл> сохранить», я не смогу нажать b. Таким образом, я до сих пор не знаю, что было изменено.

Примечание: у меня нет Simulink


Отсюда мой вопрос:

Как я могу показать все различия между двумя файлами mat кому-то без Matlab


Вот ответы, которые лично я считаю наиболее подходящими для разных ситуаций:


person Dennis Jaheruddin    schedule 02.10.2013    source источник
comment
Я предполагаю, что Файл -> Сохранить как, о котором вы упоминаете, относится к функции «Сохранить как HTML» (mathworks.co.uk/help/matlab/matlab_env/). Разве это не позволяет детализировать структуры и тому подобное?   -  person am304    schedule 02.10.2013
comment
@ am304 am304 Пробовали, но в результате получается просто «картинка» в формате html, которая не позволяет вам щелкнуть и развернуть.   -  person Dennis Jaheruddin    schedule 02.10.2013
comment
Хорошо, вероятно, стоит сообщить об этом как о запросе на улучшение для будущей версии, даже если это не поможет вам прямо сейчас.   -  person am304    schedule 02.10.2013
comment
Вы можете использовать Simulink.saveVarsвместо save. посмотри мой ответ   -  person Mohsen Nosratinia    schedule 02.10.2013
comment
Обновил вопрос, так как у меня нет Simulink.   -  person Dennis Jaheruddin    schedule 02.10.2013
comment
Я не знаю, но, возможно, visdiff можно использовать с компилятором MATLAB.   -  person BHF    schedule 12.10.2013
comment
@BHF Это было бы неплохо, но, к сожалению, это не сработает. Протестировал его и обнаружил, что возможно, он тоже не работает .   -  person Dennis Jaheruddin    schedule 16.10.2013


Ответы (7)


Простой общий ответ, без отображения различий в значениях

Благодаря пониманию, которое я получил из ответов @BHF, @Daniel R и @Dennis Jaheruddin, мне удалось найти простое масштабируемое решение:

[fs1, fs2, er] = comp_struct(load('f1.mat'),load('f2.mat'))

Обратите внимание, что это работает для .mat, содержащего произвольное количество переменных.

Для этого используется Сравнить структуры — отправка файлов для обмена.

person user2987828    schedule 03.05.2016
comment
Не могу проверить это сейчас, но действительно ли это работает? А что может быть внутри файлов сохранения, ровно по 1 struct или произвольные переменные? Убедитесь, что этот ответ можно прочитать сам по себе (например, людям не нужно искать подготовку в моем существующем ответе). - person Dennis Jaheruddin; 03.05.2016
comment
myStruct1=load('f1.mat'); создает переменную myStruct1 с тем же содержимым, что и у вас, и ничего больше. Это эффект знака равенства, а также эффект использования результата загрузки в качестве аргумента для comp_struct. - person user2987828; 03.05.2016
comment
Лучше всего было бы отредактировать свой ответ, но рецензент научил меня на french.stackexchange.com/review/suggested- edits/8954, чтобы предпочесть отдельный ответ. - person user2987828; 03.05.2016
comment
Это работает для .mat, содержащего произвольное количество переменных. - person user2987828; 03.05.2016

Найти все различия между файлами матов без MATLAB?

Вы можете найти различия между HDF5 на основе файлы .mat с Инструменты HDF5.

Пример

Позвольте мне сократить ваш пример MATLAB и предположить, что вы создаете два матовых файла с

clear ; a = 6 ; b.c = 'hello' ; save -v7.3 f1
clear ; a = 7 ; b.e = 'world' ; save -v7.3 f2

Использование вне MATLAB

h5ls -v -r f1.mat

чтобы получить список данных, включенных в f1.mat:

Opened "f1.mat" with sec2 driver.
/                        Group
    Location:  1:96
    Links:     1
/a                       Dataset {1/1, 1/1}
    Attribute: MATLAB_class scalar
        Type:      6-byte null-terminated ASCII string
        Data:  "double"
    Location:  1:2576
    Links:     1
    Storage:   8 logical bytes, 8 allocated bytes, 100.00% utilization
    Type:      native double
/b                       Group
    Attribute: MATLAB_class scalar
        Type:      6-byte null-terminated ASCII string
        Data:  "struct"
    Location:  1:800
    Links:     1
/b/c                     Dataset {5/5, 1/1}
    Attribute: H5PATH scalar
        Type:      2-byte null-terminated ASCII string
        Data:  "/b"
    Attribute: MATLAB_class scalar
        Type:      4-byte null-terminated ASCII string
        Data:  "char"
    Attribute: MATLAB_int_decode scalar
        Type:      native int
        Data:  2
    Location:  1:1832
    Links:     1
    Storage:   10 logical bytes, 10 allocated bytes, 100.00% utilization
    Type:      native unsigned short

Использование

h5ls -d -r f1.mat

возвращает значения сохраненных данных:

/                        Group
/a                       Dataset {1, 1}
    Data:
        (0,0) 6
/b                       Group
/b/c                     Dataset {5, 1}
    Data:
        (0,0) 104, 101, 108, 108, 111

Данные 104, 101, 108, 108, 111 представляют слово hello, которое можно увидеть с помощью

h5ls -d -r f1.mat | tail -1 | awk '{FS=",";printf("%c%c%c%c%c \n",$2,$3,$4,$5,$6)}'

Вы можете получить тот же список для f2.mat и сравнить два вывода с помощью инструмента по вашему выбору.

Сравнение также работает напрямую с инструментами HDF5. Чтобы сравнить два числа a из обоих файлов, используйте

h5diff -r f1.mat f2.mat /a

который покажет вам значения и их разницу

dataset: </a> and </a>
size:           [1x1]           [1x1]
position        a               a               difference          
------------------------------------------------------------
[ 0 0 ]          6               7               1              
1 differences found
attribute: <MATLAB_class of </a>> and <MATLAB_class of </a>>
0 differences found

Примечания

В инструментах HDF5 есть еще несколько команд и параметров, которые может помочь решить вашу настоящую проблему.

Двоичные дистрибутивы для Linux и Windows доступны в группе HDF. Для OS X их можно установить через MacPorts. При необходимости есть также графический интерфейс: HDFView.

person BHF    schedule 11.10.2013
comment
Любопытно посмотреть, работает ли это для нетривиальных мат-файлов, пока я настроен оптимистично. - person Dennis Jaheruddin; 14.10.2013
comment
Если вам не удается использовать инструменты HDF5, вы можете попытаться связаться со службой поддержки из Mathworks. и/или группа HDF. Или попробуйте написать код самостоятельно, используя любой язык, который читает файлы HDF5 (например, python с h5py). - person BHF; 16.10.2013
comment
Я пробовал h5diffdll и h5lsdll, но для нетривиальных файлов результат слишком велик, чтобы его можно было отобразить в cmd. Не могли бы вы подсказать, как мне получить результаты в текстовом файле, чтобы я мог их немного очистить? - person Dennis Jaheruddin; 16.10.2013
comment
Похоже, вы работаете в Windows, извините, я не знаю, как перенаправить вывод. Для unix-подобных систем это будет YOUR_COMMAND > YOUR_FILE. - person BHF; 16.10.2013
comment
К счастью, это работает и в Windows, а также сокращает время обработки с полминуты до доли секунды! - person Dennis Jaheruddin; 16.10.2013

Если у вас есть Simulink, вы можете использовать Simulink.saveVars для создания m -файл, который при выполнении создает такие же переменные в рабочей области:

a = 6;
b.c.d = 7;
b.c.e = 'x';
Simulink.saveVars('f1');
f = a;
clear a
b.c.e = 'y';
Simulink.saveVars('f2');
visdiff('f1.m','f2.m')

как показано на этом скриншоте

введите здесь описание изображения

Обратите внимание, что по умолчанию он ограничивает количество элементов в массивах до 1000, и вы можете увеличить его до 10000. Массивы больше этого ограничения будут сохранены в отдельном мат-файле.

ОБНОВЛЕНИЕ: Начиная с R2014a в MATLAB добавлена ​​новая функция, похожая на Simulink.saveVars. см. matlab.io.saveVariablesToScript

person Mohsen Nosratinia    schedule 02.10.2013
comment
Я упомянул об отсутствии Simulink только после прочтения этого ответа. Так что не минусуйте только по этой причине. - person Dennis Jaheruddin; 02.10.2013

Это только часть ответа, но, возможно, это поможет.

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

Затем вы используете стандартный инструмент сравнения текстов (может быть, даже visdiff) для сравнения .m-файлов.

person A. Donda    schedule 02.10.2013
comment
Я попытался реализовать ваше решение, однако все еще сталкиваюсь с некоторыми трудностями. Смотрите мой ответ. - person Dennis Jaheruddin; 02.10.2013

Есть несколько хороших инструментов для сравнения XML-файлов, я бы поступил так:

  1. Загрузите struct2xml.m
  2. Загрузите оба матфайла
  3. Экспорт каждого с помощью struct2xml
  4. сравнить, используя XMLSpy или аналогичный
person Daniel    schedule 16.10.2013
comment
Я еще не проверил это, но пока это выглядит так, как будто это может быть наиболее удобным. - person Dennis Jaheruddin; 17.10.2013
comment
в File Exchange есть много функций для преобразования переменных MATLAB в текстовое представление (XML, JSON, ..). Их вывод можно сравнить с помощью любого обычного инструмента сравнения. - person Amro; 17.10.2013
comment
Хотя это представление не будет работать для моих структур (или даже для скаляров), оно указало мне правильное направление. Прочитав этот ответ в сочетании с предложением @Amro, я понял, что сохранение моих данных в виде простого текста (и, таким образом, потеря структурного характера) сделает любое сравнение непрактичным. Я скоро опубликую решение, которое я нашел. - person Dennis Jaheruddin; 18.10.2013

Ответ для небольших файлов с отображением всех различий в значениях

По предложению @A. Donda Я пытался использовать gencode для создания переменной для всего.

Хотя это работает для моего игрушечного примера, это довольно медленно и говорит мне, что я превышаю допустимое количество переменных для моих реальных файлов .mat.

Так или иначе, для тех, кто ищет что-то работающее с небольшими файлами, выложу этот вариант:

wList=who;
for iLoop = 1:numel(wList)
    eval(['generated_' wList{iLoop} '= gencode(' wList{iLoop} ');'])
    for jLoop = 1:numel(eval(['generated_' wList{iLoop}]))
        eval(['generated_' wList{iLoop} '_' num2str(jLoop) '= generated_' wList{iLoop} '(' num2str(jLoop) ');' ])
    end
end

Хотя это может сработать, я не чувствую, что это лучший способ.

person Dennis Jaheruddin    schedule 02.10.2013
comment
Да, я думаю, этот способ имеет смысл только тогда, когда сгенерированные m-файлы имеют разумный размер. Единственное, что я могу придумать, это изменить генкод, чтобы, если в структуру данных вовлечены большие матрицы данных, не генерировать код для их воссоздания, а сделать своего рода сводку их содержимого, например. используя контрольную сумму. - person A. Donda; 04.10.2013

Общий ответ, без отображения различий в значениях

Благодаря пониманию, которое я получил из ответов @BHF и @Daniel R, мне удалось найти достаточно масштабируемое решение.

Шаг 1. Сохраните все переменные из каждого файла в виде единой структуры

При этом используется Сохранить рабочую область в структуру — Отправка файлового обмена .

Вот шаги, которые необходимо предпринять, если вы хотите сравнить f1.mat и f2.mat:

clear
load f1
myStruct1 = ws2struct;
save myStruct1 myStruct1 
clear
load f2
myStruct2 = ws2struct;
save myStruct2 myStruct2 
clear                    
load myStruct1
load myStruct2

Шаг 2. Сравните структуры

Для этого используется Сравнить структуры – отправка файлов в обмен.

Учитывая, что вы хотите сравнить myStruct1 и myStruct2, вы можете просто позвонить:

[fs1, fs2, er] = comp_struct(myStruct1,myStruct2)

Я был приятно удивлен тем, насколько удобочитаемым является список различий в er, вот вывод для примера, который использовался в вопросе:

er =

's2 is missing field a'
's1(1).b(1).c(1).e and s2(1).b(1).c(1).e do not match'

Обратите внимание, что он не будет отображать значения, с технической точки зрения, вероятно, не так уж сложно изменить файл m, если желательны отображения разницы значений. Однако, особенно если есть большие матрицы, я полагаю, это может привести к проблематичному выводу.

person Dennis Jaheruddin    schedule 18.10.2013
comment
Принятый ответ упрощает это. Я оставлю этот ответ здесь, так как не уверен, что принятый ответ действителен для более старых версий Matlab. - person Dennis Jaheruddin; 03.05.2016