有没有人知道使用Python从MATLAB图文件中提取数据的任何方法?我知道这些是二进制文件,但Python Cookbook for .mat文件http://www.scipy.org/Cookbook/Reading_mat_files中的方法似乎不适用于.fig文件......
提前感谢您的帮助, 丹
答案 0 :(得分:10)
.fig文件是.mat文件(包含结构),请参阅 http://undocumentedmatlab.com/blog/fig-files-format/
作为您给出的引用状态,结构仅支持v7.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)
显示我在MATLAB中使用了plot([1 2],[3 4])
(孩子是轴,孙子是lineseries)。
答案 1 :(得分:6)
我发现Alex的答案非常吸引人,但我扩展了他的代码。首先,我在序言中加入了数字,ylabel等的来源。第二,我加入了传奇! 我对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()
答案 2 :(得分:6)
这是我在Sascha的帖子中的更新。现在它可以:
代码如下:
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()
答案 3 :(得分:2)
保存MATLAB图形时,它会将Handle Graphics层次结构转储到结构中,将其保存到.mat文件,并将扩展名更改为.fig。所以.fig文件只是.mat文件,如果你要查找的数据存储在原始图中的某个位置,它就会在那里。如果您手动将扩展名更改回.mat,您可以将其加载到MATLAB中并查看。
我担心我不太了解从Python读取.mat文件,但是如果你有办法一般这样做,你也应该能够读取.fig文件。
答案 4 :(得分:2)
这是更简单的方法。它基于较新的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)
答案 5 :(得分:1)
使用Sascha的帖子,我只想提取存储在.fig文件中的x数据和y数据。
下面是我的python函数,它是Sascha函数的简化,旨在仅提取数据。 输出是字典。其键是图中数据的相应标签。
我把它放在那里。很高兴,如果这可以节省几分钟给别人!
card.Item1