Plot data with gaps (xfig example)
Revision as of 02:31, 4 April 2019 by Stierhof (talk | contribs) (Created page with "=== Plot data over range with gaps === 600px|center <pre> %% Found yourself with data that is only interesting in some parts of the %% plot ra...")
Plot data over range with gaps
%% Found yourself with data that is only interesting in some parts of the
%% plot range? Ever wondered how you can do this with XFig? Here is your chance!
%%
%% The idea: Give the ranges of interest and the data to plot. Arrange the data
%% in subplots and add a visible marker to make the seperation clear.
require("xfig");
% Some function do demonstrate the feature
define zp (x) { return 1./sqrt(2*PI)*exp(-x*x/2.); }
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Here is where the plotting begins %%
%-----------------------
% Do a plot where the x-axis has a gap
variable x = [-20:20:0.001]; % The x-grid for the full function
variable y1 = zp(x); % Use the function, we shift it later when plotting
variable y2 = zp(.3*x)+.7*zp(x-4);
%% In xranges and yranges the plot range of interest are given. Make sure
%% they do not overlap (or the scale would be messed up).
% Environment setup
variable xranges = [{5,17},{989,1010}]; % Min and Max values for the subplots
variable yranges = [{0,.5}];
variable xlabel = "Random test [a.u.]";
variable ylabel = "Probability";
variable title = "Plot with Gaps";
%% NSUBn is the number of subplots. In XDIM, YDIM the size of the total plot
%% can be set.
variable NSUBX = length(xranges); % Number of x splittings
variable NSUBY = length(yranges); % Number of y splittings
variable XDIM = 15.; % Plots total x width
variable YDIM = 10.; % Plots total y width
%% Set some variables we use to store different stuff. xsepsize, ysepsize
%% determines how large the visible seperator should be. 0.5 is twice the
%% default major tic mark length, which seems to be a good value.
% Define the plot variables
variable P = {}; % collector for plot structures
variable i,j;
variable dx=0.,dy=0.; % Shift pannels
variable ddx, ddy; % Data of plot
variable xsepsize = 0.5; % Seperator size in x
variable ysepsize = 0.5; % Seperator size in y
variable XSEP1,XSEP2; % x seperator
variable YSEP1,YSEP2; % y seperator
%% Calculate the total x- and yrange we are covering. We need this to
%% set the plot panel size matching the relative range size.
variable sumxrange = 0.; % Total covered ranges for scaling
variable sumyrange = 0.;
foreach i (xranges) { sumxrange += _max(i[0], i[1])-_min(i[0],i[1]); }
foreach j (yranges) { sumyrange += _max(j[0], j[1])-_min(j[0],j[1]); }
%% Some more variable we need to set the spacing between panels right.
variable thisxmin, thisxmax; % Current panels min and max range
variable thisymin, thisymax;
variable xspace = 0.; % Extra space so the total size is reached
variable yspace = 0.;
%% Loop over all ranges and create a panel for each. Remove the tics in
%% between and insert the visible seperator. Finally plot the data and
%% adjust the panels.
_for j (0, NSUBY-1, 1)
{
thisymin = _min(yranges[j][0], yranges[j][1]);
thisymax = _max(yranges[j][0], yranges[j][1]);
dx = 0.;
% Set extra y space as necessary
if (NSUBY > 1) {
if (j > 0 && j < NSUBY-1)
yspace = ysepsize;
else
yspace = ysepsize/2.;
}
_for i (0, NSUBX-1, 1) {
thisxmin = _min(xranges[i][0], xranges[i][1]);
thisxmax = _max(xranges[i][0], xranges[i][1]);
% Set extra x space as necessary
if (NSUBX > 1) {
if (i > 0 && i < NSUBX-1)
xspace = xsepsize;
else
xspace = xsepsize/2.;
}
% Create plot object for each section
list_append(P, xfig_plot_new(XDIM*(thisxmax-thisxmin)/sumxrange-xspace,
YDIM*(thisymax-thisymin)/sumyrange-yspace));
% Set world according to given ranges
P[-1].world(xranges[i][0], xranges[i][1], yranges[j][0], yranges[j][1]);
% Set axis to confine plot labels so they do not overlap
%P[-1].axis(; ticlabels_confine);
% Start with top left panel and go right to bottom to remove tic marks
variable this = P[-1].plot_data;
if (j > 0) % All panels that are not the first one (y) do not need x2axis tics
P[-1].x2axis(;off);
if (i > 0) % All panels not the first (x) do not need y1axis tics
P[-1].y1axis(;off);
if (j < NSUBY-1) % All panels not the last (y) do not need x1axis tics
P[-1].x1axis(;off);
if (i < NSUBX-1) % All panels not the last (x) do not need y2axis tics
P[-1].y2axis(;off);
% Plot into panels
P[-1].plot(x+10, y1; color="#CC0033");
P[-1].plot(x+1000, y2; color="#0033CC");
% Create plot objects for seperators (unfortunately the implementation does not
% allow to reuse objects)
XSEP1 = xfig_plot_new(1,1); XSEP2 = xfig_plot_new(1,1);
XSEP1.world(-1,1,-1,1); XSEP2.world(-1,1,-1,1);
XSEP1.axis(;off); XSEP2.axis(;off);
XSEP1.plot([-1,-.25], [0,0]; width=1); XSEP2.plot([-1,-.25], [0,0]; width=1);
XSEP1.plot([.25,1], [0,0]; width=1); XSEP2.plot([.25,1], [0,0]; width=1);
XSEP1.plot([-.75,.25], [-1,1]; width=1); XSEP2.plot([-.75,.25], [-1,1]; width=1);
XSEP1.plot([-.25,.75], [-1,1]; width=1); XSEP2.plot([-.25,.75], [-1,1]; width=1);
XSEP1.axis(;off); XSEP2.axis(;off);
XSEP1.scale(xsepsize); XSEP2.scale(xsepsize);
YSEP1 = xfig_plot_new(1,1); YSEP2 = xfig_plot_new(1,1);
YSEP1.world(-1,1,-1,1); YSEP2.world(-1,1,-1,1);
YSEP1.axis(;off); YSEP2.axis(;off);
YSEP1.plot([0,0],[-1,-.25]; width=1); YSEP2.plot([0,0],[-1,-.25]; width=1);
YSEP1.plot([0,0], [.25,1]; width=1); YSEP2.plot([0,0], [.25,1]; width=1);
YSEP1.plot([-1,1], [-.75,.25]; width=1); YSEP2.plot([-1,1], [-.75,.25]; width=1);
YSEP1.plot([-1,1], [-.25,.75]; width=1); YSEP2.plot([-1,1], [-.25,.75]; width=1);
YSEP1.scale(ysepsize); YSEP2.scale(ysepsize);
% Append seperators
if (i != NSUBX-1) {
if (j == NSUBY-1)
P[-1].add_object(XSEP1, 1,0,-.5,0; world0);
if (j == 0)
P[-1].add_object(XSEP2, 1,1,-.5,0; world0);
}
if (j != NSUBY-1) {
if (i == NSUBX-1)
P[-1].add_object(YSEP1, 0,0,0,.5; world0);
if (i == 0)
P[-1].add_object(YSEP2, 1,0,0,.5; world0);
}
% Shift pannel to negative y values
if (i == 0) dy -= P[-1].plot_data.plot_height+ysepsize;
ddx = P[-1].plot_data.X;
P[-1].translate(vector(dx-ddx.x, dy-ddx.y, -ddx.z));
dx += P[-1].plot_data.plot_width+xsepsize;
}
}
%% Combine all the panels into one compound. We reverse the list to
%% keep the order from left-right top-bottom
list_reverse(P); % need to reverse to get the order right
variable PP = xfig_new_compound( __push_list(P)); % Combine panels
dy *= -1; % Set origin back to bottom left
PP.translate(vector(0, dy, 0));
variable xmin, xmax, ymin, ymax;
(xmin,xmax,ymin,ymax,,) = PP.get_bbox(); % Get total plot dimensions
%% When everything is set, add x- and y-labels and the title.
variable ptxt;
if (NSUBX == 1) % If only one use existing label
P[0].xlabel(xlabel); % Only passed by reference, so we can change label here
else {
ptxt = xfig_new_text(xlabel);
xfig_justify_object(ptxt, vector(.5*dx, ymin, 0), vector(0, 1, 0));
PP.append(ptxt);
}
if (NSUBY == 1)
P[-1].ylabel(ylabel); % Same as for xlabel
else {
ptxt = xfig_new_text(ylabel);
ptxt.rotate_pict(90);
xfig_justify_object(ptxt, vector(xmin, .5*dy, 0), vector(1, 0, 0));
PP.append(ptxt);
}
% Set title
(xmin,xmax,ymin,ymax,,) = PP.get_bbox(); % Update dimensions
if (NSUBX == 1)
P[-1].title(title);
else {
ptxt = xfig_new_text(title);
xfig_justify_object(ptxt, vector(.5*dx, ymax, 0), vector(0, -1, 0));
PP.append(ptxt);
}
%% Here you! Output the plot and enjoy it!
%%
%% One cautious note: as with xfig_multiplot it may happen that tic labels
%% are overlapping. To circumvent this either give major ticmarks or change
%% the plotting ranges.
PP.render("plot_with_gaps.pdf");
<\pre>