Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
  • Loading branch information
cody2 authored Jan 8, 2023
1 parent 7033560 commit 306254e
Show file tree
Hide file tree
Showing 6 changed files with 941 additions and 0 deletions.
41 changes: 41 additions & 0 deletions Analyzer/copyfields.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
% copyfields.m - copies fields from one scalar structure to another
%
% /--------------------------------------------------------------\
% | Date: 01/08/2023 |
% | Author: Jonathan Cody |
% | Affiliation: Pienaar Computational Systems Pharmacology Lab |
% | Weldon School of Biomedical Engineering |
% | Purdue University |
% \--------------------------------------------------------------/
%
% Copy field values from one scalar structure variable 'struc2' into
% another structure variable 'struc1' and return struc1. If overWrite=0,
% existing struc1 fields will not be changed, only new fields added. If a
% struc2 field is itself a structure, 'copyfields' is called again for that
% structure.
%
%% ========================================================================
% FUNCTION
% ========================================================================
function struc1 = copyfields(struc1,struc2,overWrite)

if nargin < 3 ; overWrite = 1 ; end % overwrite fields by default

if isempty(struc2) ; return ; end % do nothing if struc2 is empty

fields2 = fieldnames(struc2) ;% names of fields in struc2

for f = 1:length(fields2)
if overWrite || ~isfield(struc1,fields2{f})
if isstruct(struc2.(fields2{f}))
struc1.(fields2{f}) = copyfields...
(struc1.(fields2{f}),struc2.(fields2{f}),overWrite) ;
else
try %#ok<TRYNC> avoid errors thrown by graphics objects
struc1.(fields2{f}) = struc2.(fields2{f}) ;
end
end
end
end

end
199 changes: 199 additions & 0 deletions Analyzer/gridplot.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
% gridplot.m - creates a grid of plots (alternative to MATLAB's 'subplot')
%
% /--------------------------------------------------------------\
% | Date: 01/08/2023 |
% | Author: Jonathan Cody |
% | Affiliation: Pienaar Computational Systems Pharmacology Lab |
% | Weldon School of Biomedical Engineering |
% | Purdue University |
% \--------------------------------------------------------------/
%
%% ========================================================================
% INPUTS
% ========================================================================
%
% PROPS = cell array of scalar structures that define axis properties
% -> Index is {left-to-right,bottom-to-top}
% (EX: {2,1} is 2nd axis from the left, on the bottom)
% -> See 'Axes Properties' in MATLAB help for a list of fields
%
% LINES = cell array that defines line data and properties
% -> Index is {left-to-right,bottom-to-top} (same as 'PROPS')
% -> Each element is a cell array of scalar structures
% -> Order determines plot rank ({1} is plotted on top of other lines)
% -> See 'linemaker.m' for a description of fields in these structures

% Optional inputs are entered after 'LINES' as (string name),(value) pairs
% -> See line 44 for definitions and default values
%
%% ========================================================================
% OUTPUTS
% ========================================================================
%
% figH = figure handle
%
% AxisH = matrix of axis handles (Index is left-to-right,bottom-to-top)
%
%% ========================================================================
% FUNCTION
% ========================================================================
function [figH,AxisH] = gridplot(PROPS,LINES,varargin)

[nX,nY] = size(PROPS) ;% number of x,y axes

% Set default values for optional inputs
AxisProps = [] ;% scalar structure of properties shared by all axes
% -> see 'Axes Properties' in MATLAB help

FigColor = [1 1 1] ;% figure background color [R G B]

figName = 'figure' ;% figure name (and file name)

FigSizes = [0 0] ;% figure [horizontal,vertical] size
% -> axes will adapt to ensure figure size
% -> (ignored in that direction if zero)
% -> use 'Units' to define units

imageRes = '-r300' ;% image resolution (see MATLAB 'print' function)

imageType = '-dtiff' ;% image file type (see MATLAB 'print' function)

isBroken = [0 0] ;% treat [x,y] axes as broken axes
% -> EX: [1 0] shares lines and axis properties between
% all axes in each row and hides y-axes after column 1
% -> if 'FigSizes' is also set, axes lengths will be
% proportional to number of ticks

Gaps = [.25 .25] ;% [horizontal,vertical] gaps between axes
% -> use 'Units' to define units

LineProps = [] ;% scalar structure of properties shared by all lines
% -> see 'linemaker.m' for a descriptions of fields

Margins = [1 1 .5 .5] ;% [left,bottom,right,top] figure margins
% -> use 'Units' to define units

Units = 'inches' ;% length units for figure
% -> see 'Figure Properties' in MATLAB help for options

XLengths = ones(1,nX) ;% lengths of x-axes (left-to-right)
% -> If FigSizes(1)~=0, treated as relative size

YLengths = ones(1,nY) ;% lengths of y-axes (bottom-to-top)
% -> If FigSizes(2)~=0, treated as relative size

for n = 1:length(varargin)
if strcmp('AxisProps',varargin(n)) ; AxisProps = varargin{n+1} ; end
if strcmp('FigColor', varargin(n)) ; FigColor = varargin{n+1} ; end
if strcmp('figName', varargin(n)) ; figName = varargin{n+1} ; end
if strcmp('FigSizes', varargin(n)) ; FigSizes = varargin{n+1} ; end
if strcmp('imageRes', varargin(n)) ; imageRes = varargin{n+1} ; end
if strcmp('imageType',varargin(n)) ; imageType = varargin{n+1} ; end
if strcmp('isBroken', varargin(n)) ; isBroken = varargin{n+1} ; end
if strcmp('Gaps', varargin(n)) ; Gaps = varargin{n+1} ; end
if strcmp('LineProps',varargin(n)) ; LineProps = varargin{n+1} ; end
if strcmp('Margins', varargin(n)) ; Margins = varargin{n+1} ; end
if strcmp('Units', varargin(n)) ; Units = varargin{n+1} ; end
if strcmp('XLengths', varargin(n)) ; XLengths = varargin{n+1} ; end
if strcmp('YLengths', varargin(n)) ; YLengths = varargin{n+1} ; end
end

% If 'LINES' is not full size, make it full size
if size(LINES,1) < nX ; LINES{nX,1} = [] ; end
if size(LINES,2) < nY ; LINES{1,nY} = [] ; end

% Update axis lengths to enforce figure size
if FigSizes(1)~=0
if isBroken(1)
for x = 1:nX
XLengths(x) = length(PROPS{x,1}.XTick) ;
end
end
axisSpace = FigSizes(1) - (nX-1)*Gaps(1) - Margins(1) - Margins(3) ;
XLengths = XLengths * axisSpace / sum(XLengths) ;
end
if FigSizes(2)~=0
if isBroken(2)
for y = 1:nY
YLengths(y) = length(PROPS{1,y}.YTick) ;
end
end
axisSpace = FigSizes(2) - (nY-1)*Gaps(2) - Margins(2) - Margins(4) ;
YLengths = YLengths * axisSpace / sum(YLengths) ;
end

LongestAxis = max( [YLengths XLengths] ) ;% used for equalizing tick length

figH = figure( 'Name' , figName ...
, 'Color' , FigColor ...
, 'Units' , Units ...
, 'PaperUnits' , Units ) ;% figure handle

AxisH = gobjects(nX,nY) ;% axis handles

xPos = Margins(1) ;% distance from left of figure

for x = 1:nX

yPos = Margins(2) ;% distance from bottom of figure

for y = 1:nY

% Generate axis and define axis position
AxisH(x,y) = axes(figH,'Units',Units,...
'Position',[xPos yPos XLengths(x) YLengths(y)]) ;

% Modify axis per 'AxisProps' and 'PROPS{y,x}'
AxisH(x,y) = copyfields(AxisH(x,y),AxisProps ) ;
AxisH(x,y) = copyfields(AxisH(x,y),PROPS{x,y}) ;

% Copy x/y tick from bottom/left axis
% Hide x/y axis if y/x axis is broken
if x~=1
AxisH(x,y).YTick = AxisH(1,y).YTick ;
AxisH(x,y).YTickLabel = [] ;
if isBroken(1)
AxisH(x,y).YColor = 'none' ;
LINES{x,y} = LINES{1,y} ;
end
end
if y~=1
AxisH(x,y).XTick = AxisH(x,1).XTick ;
AxisH(x,y).XTickLabel = [] ;
if isBroken(2)
AxisH(x,y).XColor = 'none' ;
LINES{x,y} = LINES{x,1} ;
end
end

% Plot lines, modifying 'LINES' per 'LineProps'
if ~isempty(LINES{x,y})
for n = length(LINES{x,y}):-1:1
LINES{x,y}{n} = copyfields(LINES{x,y}{n},LineProps,0) ;
linemaker(LINES{x,y}{n}) ;
end
end

% Fit axis limits to tick marks
AxisH(x,y).XLim = [AxisH(x,y).XTick(1) AxisH(x,y).XTick(end)] ;
AxisH(x,y).YLim = [AxisH(x,y).YTick(1) AxisH(x,y).YTick(end)] ;

% Correct MATLAB's normalized tick lengths
AxisH(x,y).TickLength = AxisH(x,y).TickLength * ...
LongestAxis / max( [XLengths(x) YLengths(y)] ) ;

yPos = yPos + YLengths(y) + Gaps(2) ;
end
xPos = xPos + XLengths(x) + Gaps(1) ;
end

% Declare figure width and height
FigSizes = [xPos yPos] - Gaps + Margins(3:4) ;

% Print figure
figH.Position = [0 0 FigSizes] ;
figH.PaperSize = FigSizes ;
figH.InvertHardcopy = "off" ;
print(figName,imageType,imageRes)

end
105 changes: 105 additions & 0 deletions Analyzer/linemaker.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
% linemaker.m - plots lines to current axis, with a variety of options
%
% /--------------------------------------------------------------\
% | Date: 01/08/2023 |
% | Author: Jonathan Cody |
% | Affiliation: Pienaar Computational Systems Pharmacology Lab |
% | Weldon School of Biomedical Engineering |
% | Purdue University |
% \--------------------------------------------------------------/
%
%% ========================================================================
% INPUTS
% ========================================================================
%
% s = structure variable that defines line
% -> At minimum, s must contain fields 'X' and 'Y' (data)
% -> See 'Line Properties' in MATLAB help for a list of fields
% -> Additional optional fields are defined on line 35
%
%% ========================================================================
% OUTPUTS
% ========================================================================
%
% Handles = cell array of line handles
%
%% ========================================================================
% FUNCTION
% ========================================================================
function Handles = linemaker(s)
hold on

X = s.X ;% data x-values (each column is different line)
Y = s.Y ;% data y-values (each column is different line)

% Set default values for optional fields in 's'
CensorID = [] ;% index in Y to mark as censored (white marker face)
% -> use only with single line of marked data points

ColorMap = [] ;% [R1 G1 B1 ; R2 G2 B2 ; etc.] matrix of line colors
% -> similar to MATLAB's 'colormap'

ErrorBars = [] ;% vector of error bar lengths (same size as Y)
% -> using with 'CensorID' will generate a trivial warning

FillColor = [] ;% [R G B (transparency)] fill color between first two lines

GradENDS = [] ;% [R1 G1 B1 ; R2 G2 B2] corresponding to min(1) and max(2)
% of values in 'GradGuide' (alternative to 'ColorMap')

GradGuide = [] ;% interpolation vector between GradENDS(1,:) and (2,:)
% -> must be the same length as the number of lines

if isfield(s,'CensorID') ; CensorID = s.CensorID ; end
if isfield(s,'ColorMap') ; ColorMap = s.ColorMap ; end
if isfield(s,'ErrorBars') ; ErrorBars = s.ErrorBars ; end
if isfield(s,'FillColor') ; FillColor = s.FillColor ; end
if isfield(s,'GradENDS') ; GradENDS = s.GradENDS ; end
if isfield(s,'GradGuide') ; GradGuide = s.GradGuide ; end

% Plot lines and modify per 's'
if ~isempty(ErrorBars)
Handles = errorbar(X,Y,ErrorBars) ;
else
Handles = plot(X,Y) ;
end
for n = 1:length(Handles)
Handles(n) = copyfields(Handles(n),s) ;
end

% Color line based on 'ColorMap
if ~isempty(ColorMap)
for n = 1:length(Handles)
Handles(n).Color = ColorMap(n,:) ;
end
end

% Color line based on 'GradGuide' and 'GradENDS'
if ~isempty(GradGuide)
G = ( GradGuide - min(GradGuide) ) / range(GradGuide) ;
for n = 1:length(Handles)
Handles(n).Color = ...
GradENDS(1,:) + ( GradENDS(2,:) - GradENDS(1,:) )*G(n) ;
end
end

% Mark specified points as hidden
if ~isempty(CensorID)
Handles(n+1) = copyobj(Handles(n),ancestor(Handles(n),'axes')) ;
Handles(n+1).XData = Handles(n).XData(CensorID) ;
Handles(n+1).YData = Handles(n).YData(CensorID) ;
Handles(n+1).LineStyle = 'none' ;
Handles(n+1).MarkerFaceColor = [1 1 1] ;
end

% Shade region between lines
if ~isempty(FillColor)
XPATCH = [ Handles(1).XData' ; flip(Handles(2).XData') ] ;
YPATCH = [ Handles(1).YData' ; flip(Handles(2).YData') ] ;
Handles(n+1) = patch( XPATCH, YPATCH, FillColor(1:3) ...
, 'FaceAlpha' , FillColor(4) ...
, 'LineStyle' , 'none' ) ;
end

hold off
end
Loading

0 comments on commit 306254e

Please sign in to comment.