Данные из файла MATLAB .fig с использованием Python? - PullRequest
8 голосов
/ 17 ноября 2011

Кто-нибудь знает какие-либо методы извлечения данных из фигового файла MATLAB с использованием Python?Я знаю, что это двоичные файлы, но методы в Python Cookbook для файлов .mat http://www.scipy.org/Cookbook/Reading_mat_files, похоже, не работают для файлов .fig ...

Заранее благодарен за любую помощь, Дэн

Ответы [ 6 ]

10 голосов
/ 18 ноября 2011

.fig - это файлы .mat (содержащие структуру), см. http://undocumentedmatlab.com/blog/fig-files-format/

В качестве ссылки, которую вы указываете состояния, структуры поддерживаются только до версии 7.1: http://www.scipy.org/Cookbook/Reading_mat_files

Итак, в MATLAB я сохраняю, используя -v7:

plot([1 2],[3 4])
hgsave(gcf,'c','-v7');

Затем в Python 2.6.4 я использую:

>>> from scipy.io import loadmat
>>> x = loadmat('c.fig')
>>> x
{'hgS_070000': array([[<scipy.io.matlab.mio5.mat_struct object at 0x1500e70>]], dtype=object), '__version__': '1.0', '__header__': 'MATLAB 5.0 MAT-file, Platform: MACI64, Created on: Fri Nov 18 12:02:31 2011', '__globals__': []}
>>> x['hgS_070000'][0,0].__dict__
{'handle': array([[1]], dtype=uint8), 'children': array([[<scipy.io.matlab.mio5.mat_struct object at 0x1516030>]], dtype=object), '_fieldnames': ['type', 'handle', 'properties', 'children', 'special'], 'type': array([u'figure'], dtype='<U6'), 'properties': array([[<scipy.io.matlab.mio5.mat_struct object at 0x1500fb0>]], dtype=object), 'special': array([], shape=(1, 0), dtype=float64)}

Где я использовал .__dict__, чтобы увидеть, как пройти через структуру. Например. чтобы получить XData и YData я могу использовать:

>>> x['hgS_070000'][0,0].children[0,0].children[0,0].properties[0,0].XData
array([[1, 2]], dtype=uint8)
>>> x['hgS_070000'][0,0].children[0,0].children[0,0].properties[0,0].YData
array([[3, 4]], dtype=uint8)

Показывает, что я использовал plot([1 2],[3 4]) в MATLAB (ребенок - это ось, а внук - серия строк).

7 голосов
/ 21 февраля 2013

Я нашел ответ Алекса очень привлекательным, но немного расширил его код.Прежде всего, я включил преамбулу, чтобы показать, откуда взялась фигура, илабел и т. Д.Во-вторых, я включил легенду!Я довольно новичок в Python, поэтому любые предложения по улучшению приветствуются.

def plotFig(filename,fignr=1):
   from scipy.io import loadmat
   from numpy import size
   from matplotlib.pyplot import plot,figure,hold,xlabel,ylabel,show,clf,xlim,legend
   d = loadmat(filename,squeeze_me=True, struct_as_record=False)
   ax1 = d['hgS_070000'].children
   if size(ax1) > 1:
       legs= ax1[1]
       ax1 = ax1[0]
   else:
        legs=0
   figure(fignr)
   clf()
   hold(True)
   counter = 0    
   for line in ax1.children:
       if line.type == 'graph2d.lineseries':
           if hasattr(line.properties,'Marker'):
               mark = "%s" % line.properties.Marker
               mark = mark[0]
           else:
               mark = '.'
           if hasattr(line.properties,'LineStyle'):
               linestyle = "%s" % line.properties.LineStyle
           else:
               linestyle = '-'
           if hasattr(line.properties,'Color'):
               r,g,b =  line.properties.Color
           else:
               r = 0
               g = 0
               b = 1
           if hasattr(line.properties,'MarkerSize'):
               marker_size = line.properties.MarkerSize
           else:
               marker_size = 1                
           x = line.properties.XData
           y = line.properties.YData
           plot(x,y,marker=mark,linestyle=linestyle,\
           color(r,g,b),markersize=marker_size)
       elif line.type == 'text':
           if counter < 1:
               xlabel("%s" % line.properties.String,fontsize =16)
               counter += 1
           elif counter < 2:
               ylabel("%s" % line.properties.String,fontsize = 16)
               counter += 1        
   xlim(ax1.properties.XLim)
   if legs:        
       leg_entries = tuple(legs.properties.String)
       py_locs = ['upper center','lower center','right','left','upper right','upper left','lower right','lower left','best']
       MAT_locs=['North','South','East','West','NorthEast', 'NorthWest', 'SouthEast', 'SouthWest','Best']
       Mat2py = dict(zip(MAT_locs,py_locs))
       location = legs.properties.Location
       legend(leg_entries,loc=Mat2py[location])
    hold(False)
    show()
6 голосов
/ 28 апреля 2016

Вот мое обновление из поста Саши. Теперь он может:

  • дисплей повернут, надписи текс
  • Отображение xticks и yticks
  • улучшенная обработка маркеров
  • сетка вкл / выкл
  • улучшенная обработка перечисления осей и легенд
  • сохранить размер фигуры

Код ниже:

from scipy.io import loadmat
import numpy as np
import matplotlib.pyplot as plt

def plotFig(filename,fignr=1):
   d = loadmat(filename,squeeze_me=True, struct_as_record=False)
   matfig = d['hgS_070000']
   childs = matfig.children
   ax1 = [c for c in childs if c.type == 'axes']
   if(len(ax1) > 0):
       ax1 = ax1[0]
   legs = [c for c in childs if c.type == 'scribe.legend']
   if(len(legs) > 0):
       legs = legs[0]
   else:
       legs=0
   pos = matfig.properties.Position
   size = np.array([pos[2]-pos[0],pos[3]-pos[1]])/96
   plt.figure(fignr,figsize=size)
   plt.clf()
   plt.hold(True)
   counter = 0    
   for line in ax1.children:
       if line.type == 'graph2d.lineseries':
           if hasattr(line.properties,'Marker'):
               mark = "%s" % line.properties.Marker
               if(mark != "none"):
                   mark = mark[0]
           else:
               mark = '.'
           if hasattr(line.properties,'LineStyle'):
               linestyle = "%s" % line.properties.LineStyle
           else:
               linestyle = '-'
           if hasattr(line.properties,'Color'):
               r,g,b =  line.properties.Color
           else:
               r = 0
               g = 0
               b = 1
           if hasattr(line.properties,'MarkerSize'):
               marker_size = line.properties.MarkerSize
           else:
               marker_size = -1                
           x = line.properties.XData
           y = line.properties.YData
           if(mark == "none"):
               plt.plot(x,y,linestyle=linestyle,color=[r,g,b])
           elif(marker_size==-1):
               plt.plot(x,y,marker=mark,linestyle=linestyle,color=[r,g,b])
           else:
               plt.plot(x,y,marker=mark,linestyle=linestyle,color=[r,g,b],ms=marker_size)
       elif line.type == 'text':
           if counter == 0:
               plt.xlabel("$%s$" % line.properties.String,fontsize =16)
           elif counter == 1:
               plt.ylabel("$%s$" % line.properties.String,fontsize = 16)
           elif counter == 3:
               plt.title("$%s$" % line.properties.String,fontsize = 16)
           counter += 1        
   plt.grid(ax1.properties.XGrid)

   if(hasattr(ax1.properties,'XTick')):
       if(hasattr(ax1.properties,'XTickLabelRotation')):
           plt.xticks(ax1.properties.XTick,ax1.properties.XTickLabel,rotation=ax1.properties.XTickLabelRotation)
       else:
           plt.xticks(ax1.properties.XTick,ax1.properties.XTickLabel)
   if(hasattr(ax1.properties,'YTick')):
       if(hasattr(ax1.properties,'YTickLabelRotation')):
           plt.yticks(ax1.properties.YTick,ax1.properties.YTickLabel,rotation=ax1.properties.YTickLabelRotation)
       else:
           plt.yticks(ax1.properties.YTick,ax1.properties.YTickLabel)
   plt.xlim(ax1.properties.XLim)
   plt.ylim(ax1.properties.YLim)
   if legs:        
       leg_entries = tuple(['$' + l + '$' for l in legs.properties.String])
       py_locs = ['upper center','lower center','right','left','upper right','upper left','lower right','lower left','best','best']
       MAT_locs=['North','South','East','West','NorthEast', 'NorthWest', 'SouthEast', 'SouthWest','Best','none']
       Mat2py = dict(zip(MAT_locs,py_locs))
       location = legs.properties.Location
       plt.legend(leg_entries,loc=Mat2py[location])
   plt.hold(False)
   plt.show()
2 голосов
/ 10 сентября 2012

Это гораздо более простой способ. Он основан на более новых Scipy и loadmat:

http://answerpot.com/showthread.php?3707193-loadmat+and+figure

И мое небольшое расширение для простых 2D линий:

from scipy.io import loadmat



d = loadmat('../impulse_all.fig',squeeze_me=True, struct_as_record=False)
# d = loadmat('R11_resuspension.fig',squeeze_me=True, struct_as_record=False)
ax1 = d['hgS_070000'].children
if size(ax1) > 1:
    ax1 = ax1[0]

figure
hold(True)
counter = 0
for line in ax1.children:
    if line.type == 'graph2d.lineseries':
        marker = "%s" % line.properties.Marker
        linestyle = "%s" % line.properties.LineStyle
        r,g,b =  line.properties.Color
        marker_size = line.properties.MarkerSize
        x = line.properties.XData
        y = line.properties.YData
        plot(x,y,marker,linestyle=linestyle,color = (r,g,b),markersize=marker_size)
    elif line.type == 'text':
        if counter < 1:
            xlabel("%s" % line.properties.String,fontsize =16)
            counter += 1
        elif counter < 2:
            ylabel("%s" % line.properties.String,fontsize = 16)
            counter += 1



hold(False)
2 голосов
/ 18 ноября 2011

Когда вы сохраняете фигуру MATLAB, она выгружает иерархию Handle Graphics в структуру, сохраняет ее в файл .mat и изменяет расширение на .fig. Таким образом, файлы .fig - это просто файлы .mat, и если искомые данные были сохранены где-то на исходном рисунке, они будут там. Если вы вручную измените расширение на .mat, вы можете загрузить его в MATLAB и посмотреть.

Боюсь, я мало что знаю о чтении файлов .mat из Python, но если у вас есть способ сделать это в целом, вы также сможете читать в файле .fig.

1 голос
/ 07 ноября 2017

Используя сообщения Sascha, я просто хотел извлечь x-данные и y-данные, хранящиеся в файле .fig.

Ниже приведена моя функция python, которая является упрощением функции Sascha, направленной только на извлечение данных.Выходной словарь.Его ключи - соответствующие метки данных на рисунке.

Я положил его туда.Рад, что это может сэкономить несколько минут кому-то еще!

import numpy
from scipy.io import loadmat

def read_fig(filename):
    output = {}
    d = loadmat(filename, squeeze_me=True, struct_as_record=False)
    matfig = d['hgS_070000']
    childs = matfig.children
    ax1 = [c for c in childs if c.type == 'axes'][0]
    for line in ax1.children:
        try:
            if line.type == 'graph2d.lineseries':
                x = line.properties.XData
                y = line.properties.YData
                leg = line.properties.DisplayName
                print leg
                output[leg] = numpy.column_stack((x, y))
        except:
            print 'One children is ignored...'
    return output
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...