以前Matlab作图时,要设置好多的变量, 如标题,x轴,y轴间隔, 字体,线条等等特性的设置。这些在写的时候比较麻烦, 今天写了一个集成的函数,直接包含了一个基本的特性,只要用结构体包含进来就可以了。非常的方便。
例子1
代码
% Demo shows how to: % 1. use cell arrays when lines have different length % 2. use repeating sequence of markers/colors/lineStyles % 3. truncate axes to partially-specified limits clear all close all %% Generate some data maxIter = 200; optTol = 1e-6; err0 = 10000; rho = .04; rho2 = .04:.005:1; for k = 1:maxIter err1(k) = err0/sqrt(k); if err1(k) < optTol break; end end for k = 1:maxIter err2(k) = err0/k; if err2(k) < optTol break; end end for k = 1:maxIter err3(k) = err0/k^2; if err3(k) < optTol break; end end for k = 1:maxIter err4(k) = err0*(1-rho)^k; if err4(k) < optTol break; end end for k = 1:maxIter err5(k) = err0*(1-sqrt(rho))^k; if err5(k) < optTol break; end end for k = 1:maxIter err6(k) = err0*prod(1-rho2(1:k)); if err6(k) < optTol break; end end % Note: yData does not have same length, and is stored as cell array xData = 1:maxIter; yData{1} = err1; yData{2} = err2; yData{3} = err3; yData{4} = err4; yData{5} = err5; yData{6} = err6; legendStr = {'Sublinear1','Sublinear2','Sublinear3','Linear1','Linear2','Superlinear'}; %% Pretty Plot figure; options.logScale = 2; % Note: prettyPlot will cycle through the given colors/lineStyles/markers options.colors = [1 0 0 0 1 0 0 0 1]; options.lineStyles = {':','--','-'}; options.markers = {'o','s'}; % Note: we will truncate the lower y-axis limit but not the upper limit options.ylimits = [1e-6 inf]; options.markerSpacing = [25 1 25 11 25 21 25 5 25 15 25 8]; options.xlabel = 'Iteration Number'; %% 设置的坐标 options.ylabel = 'Error'; options.legend = legendStr; %% 设置Graph legend options.legendLoc = 'SouthWest'; %% 位置 %% 另外自己也可以写好多的函数。。。。。。很方便。 prettyPlot(xData,yData,options); print -dpdf prettyPlot2.pdf
效果图:
关于preetyplot函数:
function [] = prettyPlot(xData,yData,options) % prettyPlot(xData,yData,options) % % available options: % legend - cell array containing legend entries (default = []) % title - string containing plot title (default = []) % xlabel - string containing x-axis label (default = []) % ylabel - string containing y-axis label (default = []) % lineWidth - width of lines (default = 3) % colors - cell array or (n by 3) matrix containing line colors (default = 'b') % lineStyles - cell array containing line styles (default = '-') % markerSize - size of markers (default = []) % markers - cell array containing markers (default = []) % markerSpacing - (n by 2) matrix containing spacing between markers and offset for first marker % xlimits - 2-vector containing lower and upper limits for x-axis (can be inf to show full range) % ylimits - 2-vector containing lower and upper limits for y-axis (can be inf to show full range) % logScale - can be 0 (regular scale), 1 (semilogx), or 2 (semilogy) % legendLoc - location of legend (default = 'Best') % useLines - whether to use lines (default = 1) % fillFace - whether to fill markers (default = 1) % errors - (n by p by 2) array containing upper and lower error lines % errorStyle - line style for error bars if nargin < 3 options = []; end [legendStr,plotTitle,plotXlabel,plotYlabel,lineWidth,colors,lineStyles,... markerSize,markers,markerSpacing,xlimits,ylimits,logScale,legendLoc,... useLines,fillFace,errors,errorStyle,errorColors] = ... myProcessOptions(options,'legend',[],'title',[],'xlabel',[],'ylabel',[],... 'lineWidth',3,'colors',[],'lineStyles',[],... 'markerSize',12,'markers',[],'markerSpacing',[],... 'xlimits',[],'ylimits',[],... 'logScale',0,'legendLoc','Best','useLines',1,'fillFace',1,... 'errors',[],'errorStyle',{'--'},'errorColors',[]); if logScale == 1 plotFunc = @semilogx; elseif logScale == 2 plotFunc = @semilogy; else plotFunc = @plot; end if useLines == 0 defaultStyle = 'b.'; else defaultStyle = 'b'; end if iscell(yData) nLines = length(yData); else nLines = size(yData,1); end for i = 1:nLines % Get yData for line if iscell(yData) y{i} = yData{i}; else y{i} = yData(i,:); end % Get xData for line if isempty(xData) x{i} = 1:length(y); elseif iscell(xData) x{i} = xData{i}; elseif size(xData,1) == 1 x{i} = xData(1:length(y{i})); else x{i} = xData(i,:); end % Plot h(i) = plotFunc(x{i},y{i},defaultStyle); hold on; end if isempty(markerSpacing) for i = 1:length(h) h(i) = applyStyle(h(i),i,lineWidth,colors,lineStyles,markers,markerSpacing); end else for i = 1:length(h) h(i) = applyStyle(h(i),i,lineWidth,colors,lineStyles,markers,markerSpacing); if ~isempty(markers) && ~isempty(markers{1+mod(i-1,length(markers))}) hM = plotFunc(x{i}(markerSpacing(i,2):markerSpacing(i,1):end),y{i}(markerSpacing(i,2):markerSpacing(i,1):end),'b.'); applyStyle(hM,i,lineWidth,colors,[],markers,[]); hM = plotFunc(x{i}(markerSpacing(i,2)),y{i}(markerSpacing(i,2)),defaultStyle); h(i) = applyStyle(hM,i,lineWidth,colors,lineStyles,markers,[]); end end end if ~isempty(errors) if isempty(errorColors) errorColors = colors+.75; errorColors(:) = min(errorColors(:),1); end for i = 1:length(h) hL = plotFunc(x{i},errors{i,1},defaultStyle); hU = plotFunc(x{i},errors{i,2},defaultStyle); applyStyle(hL,i,lineWidth,errorColors,errorStyle,[],markerSpacing); applyStyle(hU,i,lineWidth,errorColors,errorStyle,[],markerSpacing); end end set(gca,'FontName','AvantGarde','FontWeight','normal','FontSize',12); if ~isempty(legendStr) h = legend(h,legendStr); set(h,'FontSize',10,'FontWeight','normal'); set(h,'Location','Best'); set(h,'Location',legendLoc); end if ~isempty(plotTitle) h = title(plotTitle); set(h,'FontName','AvantGarde','FontSize',12,'FontWeight','bold'); end if ~isempty(plotXlabel) || ~isempty(plotYlabel) h1 = xlabel(plotXlabel); h2 = ylabel(plotYlabel); set([h1 h2],'FontName','AvantGarde','FontSize',12,'FontWeight','normal'); end set(gca, ... 'Box' , 'on' , ... 'TickDir' , 'out' , ... 'TickLength' , [.02 .02] , ... 'XMinorTick' , 'off' , ... 'YMinorTick' , 'off' , ... 'LineWidth' , 1 ); if ~isempty(xlimits) xl = xlim; xlimits(xlimits == -inf) = xl(1); xlimits(xlimits == inf) = xl(2); xlim(xlimits); end if ~isempty(ylimits) yl = ylim; ylimits(ylimits == -inf) = yl(1); ylimits(ylimits == inf) = yl(2); ylim(ylimits); end set(gcf, 'PaperPositionMode', 'auto'); function [h] = applyStyle(h,i,lineWidth,colors,lineStyles,markers,markerSpacing) hold on; set(h,'LineWidth',lineWidth); if ~isempty(colors) if iscell(colors) set(h,'Color',colors{1+mod(i-1,length(colors))}); else set(h,'Color',colors(1+mod(i-1,size(colors,1)),:)); end end if ~isempty(lineStyles) && useLines if isempty(lineStyles) set(h,'LineStyle','-'); else if ~isempty(lineStyles{1+mod(i-1,length(lineStyles))}) set(h,'LineStyle',lineStyles{1+mod(i-1,length(lineStyles))}); end end end if ~isempty(markers) if ~isempty(markers{1+mod(i-1,length(markers))}) if isempty(markerSpacing) set(h,'Marker',markers{1+mod(i-1,length(markers))}); set(h,'MarkerSize',markerSize); if fillFace set(h,'MarkerFaceColor',[1 1 .9]); end end end end end end
非常的方便啦。。可以直接调用。
例子 2:
clear all; close all; figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]); xlabel('x');ylabel('y');title('a family plot with nice legend'); x = (1:1000); xMid = (x(1)+2*x(end))/3; parVals = [1 1.5 2 3]; num_Markers = 8; %<-------- LineTypes = {'-.','-','--'}; MarkerTypes = {'h','o','s','d','^','v','>','<','p'}; colors = {'m','r','b',[1 1 1]*0.5}; for ip=1:length(parVals) col = colors{1+mod(ip,length(colors))}; ls = LineTypes{1+mod(ip,length(LineTypes))}; lm = MarkerTypes{1+mod(ip,length(MarkerTypes))}; g = parVals(ip); y = 1 + 1/g*abs(1e4./(xMid + (x-xMid/g).^(2-0.2*g))); % a function that changes with parameter g legCell{ip} = ['fA, g=',num2str(g)]; %legend text [p1,p2,p3] = line_fewer_markers(x,y,num_Markers,'color',col,'linestyle',ls, 'linewidth',2, 'marker', lm, 'markerfacecolor',col,'LockOnMax',1,'Spacing','curve','parent',gca); end lh = legend(legCell,'Location','NorthWest');
效果:
clear all; close all; figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]); xlabel('x');ylabel('y');title('a family plot with nice legend'); t = 0:0.005:pi; line_fewer_markers(t*180/pi,cos(t) ,9, '--bs','spacing','curve'); line_fewer_markers(t*180/pi,sin(t) ,9, '-.ro','MFC','g','Mks',6,'linewidth',2); grey1 = [1 1 1]*0.5; line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1); leg = legend('cos','sin','sin*cos','location','best');
效果:
clear all; close all; figure; hold on; set(gca,'FontSize',16); set(gca,'FontName','Times'); set(gcf,'Color',[1,1,1]); xlabel('x');ylabel('y');title('a family plot with nice legend'); t = 0:0.005:pi; grey1 = [1 1 1]*0.5; % line_fewer_markers(t*180/pi,cos(t) ,9, '--bs','spacing','curve'); % line_fewer_markers(t*180/pi,sin(t) ,9, '-.ro','MFC','g','Mks',6,'linewidth',2); % line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1); line_fewer_markers(t*180/pi,cos(t) ,9, '--bs','spacing','curve','LegendLine','off'); line_fewer_markers(t*180/pi,sin(t) ,9, '-.ro','MFC','g','Mks',6,'linewidth',2,'LegendLine','off'); line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','Mk','p','color',grey1,'MFC',grey1,'linewidth',2,'LockOnMax',1,'LegendLine','off'); leg = legend('cos','sin','sin*cos','location','best');
效果:
% line_fewer_markers 函数:
% line_fewer_markers - line with controlled amount of markers and correct legend behaviour % % LINE_FEWER_MARKERS(X,Y,NUM_MARKERS) adds the line in vectors X and Y to the current axes % with exactly NUM_MARKERS markers drawn. % % LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...) plots the data % stored in the vectors X and Y. % % LINE_FEWER_MARKERS returns handles to LINE/MARKER objects. % % [H1,H2,H3] = LINE_FEWER_MARKERS(X,Y,NUM_MARKERS,'PropertyName',PropertyValue,...) % performs the actions as above and returns the handles of all the plotted lines/markers. % H1 = handle to the main marker(1 point); it may be put in array and used with legend % H2 = handle to the continuous line (as in H2=plot()) % H3 = handle to all other markers % % Property/Value pairs and descriptions: % % Spacing - 'x' : ordinary uniform along x % - 'curve' : equal lengths along curve y(x) % % LockOnMax - 0 : first marker on 1st data point % - 1 : offset all markers such that one marker on first max of y(x) % % LegendLine - 'on' : default, reproduce linestyle also in legend % - 'off' : shows only marker in legend % % LineSpec: same as for LINE: LineStyle,LineWidth,Marker,MarkerSize,MarkerFaceColor... % % % Example: plot 3 curves with 9,9, and 15 markers each, using different input styles % % figure; hold on; % t = 0:0.005:pi; % line_fewer_markers(t*180/pi,cos(t) ,9, '--bs','spacing','curve'); % line_fewer_markers(t*180/pi,sin(t) ,9, '-.ro','MarkerFaceColor','g', ... % 'markersize',6,'linewidth',2); % grey1 = [1 1 1]*0.5; % line_fewer_markers(t*180/pi,sin(t).*cos(t) ,15, ':','marker','h','color',grey1, ... % 'markerfacecolor',grey1,'linewidth',2,'LockOnMax',1); % leg = legend('cos','sin','sin*cos','location','best'); % % Inspired by Ioannis Filippidis's answer: % http://www.mathworks.com/matlabcentral/answers/2165-too-many-markers % % rev.3, Massimo Ciacci, August 19, 2013 % function [H1,H2,H3] = line_fewer_markers(x,y,num_Markers, varargin) %% find marker spec in varargin and remove it; extract special params: LockOnMax,Spacing if mod(length(varargin),2) if ischar(varargin{1}) linspec = varargin{1}; extraArgs = varargin(2:end); [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec,extraArgs); else error('odd sized [param | val] list, missing one param ?'); end else [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin{:}); end %% input size check if isvector(x) && isvector(y) % make x,y row vectors if iscolumn(x), x = x.'; end if iscolumn(y), y = y.'; end else error('line_fewer_markers: input arguments must be 1D vectors'); end % How the method works: plots 3 times: % a) once only the line with all points with the style 'r--' and invisible handle, % b) last time the markers, using fewer points with style 'ro' and again invisible handle. % c) once with a visible handle, only the first point, using the complete style you specified (e.g. 'r--o') %% a) once only the line with all points with the style H2 = line(x ,y ,varargInNoMk{:}); %no markers here hasbehavior(H2,'legend',0); %prevent to appear in legends! %% b) last time the markers, using fewer points with style if (strcmp(Spacing,'x') || strcmp(Spacing,'X')) ti = round(linspace(1,length(x),num_Markers)); elseif (strcmp(Spacing,'curve') || strcmp(Spacing,'Curve')) scaleY = 3/4; % 1/1 figure aspect ratio yNrm = (y-min(y))./(max(y)-min(y))*scaleY; %NORMALIZE y scale in [0 1], height of display is prop to max(abs(y)) xNrm = (x-min(x))./(max(x)-min(x)); %NORMALIZE x scale in [0 1] if (sum(isinf(yNrm))>0) || sum(isinf(x))>0 %spacing along curve not possible with infinites ti = round(linspace(1,length(x),num_Markers)); else t = 1:length(x); s = [0 cumsum(sqrt(diff(xNrm).^2+diff(yNrm).^2))]; %measures length along the curve si = (0:num_Markers-1)*s(end)/(num_Markers-1); %equally spaced lengths along the curve si(end) = s(end); %fix last point to be within the curve ti = round(interp1(s,t,si)); %find x index of markers end else error('invalid spacing parameter'); end if LockOnMax %set one ti on max if found [Mv,idx] = max(y); idx=idx(1); [mv,idxti] = min(abs(idx-ti)); deltati = ti(idxti)-idx; ti = max(1,min(ti-deltati,length(y))); end xi = x(ti); yi = y(ti); H3 = line(xi,yi,varargInNoMkNoLn{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc,'LineStyle','none'); %plot markers only hasbehavior(H3,'legend',0); %prevent to appear in legends! %% c) once with a visible handle, only the first point, using the complete style you specified if strcmp(LegendLine,'on') H1 = line(xi(1),yi(1),varargInNoMk{:},'Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc); else H1 = line(xi(1),yi(1),varargInNoMk{:},'linestyle','none','Marker',lm,'MarkerSize',ms,'MarkerFaceColor',mfc); end %------------------------------------------------------------- % PARSE FUNCTIONS %------------------------------------------------------------- % varargInNoMk = list of property pairs, marker specs removed % varargInNoMkNoLn = list of property pairs, marker specs and line specs removed function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(varargin) lm =[]; ms =[]; mfc=[]; LockOnMax=[]; Spacing=[]; LegendLine=[]; varargInNoMk = {}; varargInNoMkNoLn = {}; arg_index = 1; while arg_index <= length(varargin) arg = varargin{arg_index}; % extract special params and marker specs from arg list if strcmp(arg,'marker') || strcmp(arg,'Marker') || strcmp(arg,'Mk') || strcmp(arg,'mk') lm = varargin{arg_index+1}; elseif strcmp(arg,'MarkerSize') || strcmp(arg,'markersize') || strcmp(arg,'Mks') || strcmp(arg,'mks') ms = varargin{arg_index+1}; elseif strcmp(arg,'MarkerFaceColor') || strcmp(arg,'markerfacecolor')||strcmp(arg,'MFC')||strcmp(arg,'mfc') mfc = varargin{arg_index+1}; elseif strcmp(arg,'LockOnMax') || strcmp(arg,'lockonmax') LockOnMax = varargin{arg_index+1}; elseif strcmp(arg,'Spacing') || strcmp(arg,'spacing') Spacing = varargin{arg_index+1}; elseif strcmp(arg,'LegendLine') || strcmp(arg,'legendline') LegendLine = varargin{arg_index+1}; else % keep other params in arg list for line command varargInNoMk = {varargInNoMk{:}, varargin{arg_index}, varargin{arg_index+1}}; if ~strcmp(arg,'LineStyle') && ~strcmp(arg,'linestyle') % exclude line params for marker only plot varargInNoMkNoLn = {varargInNoMkNoLn{:}, varargin{arg_index}, varargin{arg_index+1}}; end end arg_index = arg_index + 2; end %EXTRA DEFAULTS ARE SET HERE if isempty(lm), lm = 'o' ; end if isempty(ms), ms = 10 ; end if isempty(mfc), mfc = 'none'; end if isempty(LockOnMax), LockOnMax = 1 ; end if isempty(Spacing), Spacing = 'x' ; end %%'x' -> marker delta-x constant; 'curve' : spacing constant along the curve length if isempty(LegendLine), LegendLine = 'on' ; end %------------------------------------------------------------- % Parse LineSpec string and other arguments % varargInNoMk = list of property pairs, marker specs removed % varargInNoMkNoLn = list of property pairs, marker specs and line specs removed function [varargInNoMk,varargInNoMkNoLn,lm,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargsLineSpec(linspec, extraArgs) % b blue . point - solid % g green o circle : dotted % r red x x-mark -. dashdot % c cyan + plus -- dashed % m magenta * star (none) no line % y yellow s square % k black d diamond % w white v triangle (down) % ^ triangle (up) % < triangle (left) % > triangle (right) % p pentagram % h hexagram varargInNoMk = {}; varargInNoMkNoLn = {}; foundLine = false; stringSearch = {'-.','--','-',':'}; for ii=1:4 if strfind(linspec, stringSearch{ii}) foundLine = true; ls = stringSearch{ii}; linspec = setdiff(linspec,ls); break end end if foundLine varargInNoMk = {varargInNoMk{:},'lineStyle',ls}; else varargInNoMk = {varargInNoMk{:},'lineStyle','-'}; end if ~isempty(linspec) foundCol = false; stringSearch = {'b','g','r','c','m','y','k','w'}; for ii=1:8 if strfind(linspec, stringSearch{ii}) foundCol = true; colspec = stringSearch{ii}; linspec = setdiff(linspec,colspec); break end end if foundCol varargInNoMk = {varargInNoMk{:},'color',colspec}; varargInNoMkNoLn = {varargInNoMkNoLn{:},'color',colspec}; end end if ~isempty(linspec) foundMk = false; stringSearch = {'.','o','x','+','*','s','d','v','^','<','>','p','h'}; for ii=1:13 if strfind(linspec, stringSearch{ii}) foundMk = true; mkspec = stringSearch{ii}; break end end if foundMk, lm = mkspec; else lm = 'none'; end else lm = 'none'; end [extraArgs1,unused,lm2,ms,mfc,LockOnMax,Spacing,LegendLine] = parseargs(extraArgs{:}); if strcmp(lm,'none') && ~strcmp(lm2,'none') %if other marker specified in Property Pairs take that one lm = lm2; end varargInNoMk = {varargInNoMk{:},extraArgs1{:}}; varargInNoMkNoLn = {varargInNoMkNoLn{:},extraArgs1{:}};