Skip to content

Fix default zoom when user has set XLim/Ylim to Inf #492

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Aug 4, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Fix default zoom when user has set XLim/Ylim to Inf
  • Loading branch information
robertoffmoura committed Aug 4, 2024
commit d26df7a21fa786d29a364d5c765cb64a14b94e35
230 changes: 84 additions & 146 deletions plotly/plotlyfig_aux/helpers/extractAxisData.m
Original file line number Diff line number Diff line change
@@ -1,36 +1,37 @@
function [axis, exponentFormat] = extractAxisData(obj,axisData,axisName)
% extract information related to each axis
% axisData is the data extrated from the figure, axisName take the
% values 'x' 'y' or 'z'
% values "x" "y" or "z"

%=========================================================================%
%=====================================================================%
%
% AXIS INITIALIZATION
%
%=========================================================================%
%=====================================================================%

%-general axis settings-%
axisColor = 255 * eval(sprintf('axisData.%sColor', axisName));
axisColor = sprintf('rgb(%f,%f,%f)', axisColor);
lineWidth = max(1,axisData.LineWidth*obj.PlotlyDefaults.AxisLineIncreaseFactor);
axisColor = 255 * axisData.(axisName + "Color");
axisColor = sprintf("rgb(%f,%f,%f)", axisColor);
lineWidth = max(1, ...
axisData.LineWidth*obj.PlotlyDefaults.AxisLineIncreaseFactor);

try
exponentFormat = eval(sprintf('axisData.%sAxis.Exponent', axisName));
exponentFormat = axisData.(axisName + "Axis").Exponent;
catch
exponentFormat = 0;
end

axis.side = eval(sprintf('axisData.%sAxisLocation', axisName));
axis.side = axisData.(axisName + "AxisLocation");
axis.zeroline = false;
axis.autorange = false;
axis.linecolor = axisColor;
axis.linewidth = lineWidth;
axis.exponentformat = obj.PlotlyDefaults.ExponentFormat;

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-general tick settings-%
tickRotation = eval(sprintf('axisData.%sTickLabelRotation', axisName));
tickRotation = axisData.(axisName + "TickLabelRotation");
tickLength = min(obj.PlotlyDefaults.MaxTickLength,...
max(axisData.TickLength(1)*axisData.Position(3)*obj.layout.width,...
axisData.TickLength(1)*axisData.Position(4)*obj.layout.height));
Expand All @@ -45,121 +46,113 @@
axis.tickangle = -tickRotation;

switch axisData.TickDir
case 'in'
axis.ticks = 'inside';
case 'out'
axis.ticks = 'outside';
case "in"
axis.ticks = "inside";
case "out"
axis.ticks = "outside";
end

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-set axis grid-%
isGrid = eval(sprintf('axisData.%sGrid', axisName));
isMinorGrid = eval(sprintf('axisData.%sMinorGrid', axisName));
isGrid = axisData.(axisName + "Grid");
isMinorGrid = axisData.(axisName + "MinorGrid");

if strcmp(isGrid, 'on') || strcmp(isMinorGrid, 'on')
if strcmp(isGrid, "on") || strcmp(isMinorGrid, "on")
axis.showgrid = true;
axis.gridwidth = lineWidth;
else
axis.showgrid = false;
end

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-axis grid color-%
try
gridColor = 255*axisData.GridColor;
gridAlpha = axisData.GridAlpha;
axis.gridcolor = sprintf('rgba(%f,,%f,%f,%f)', gridColor, gridAlpha);
axis.gridcolor = sprintf("rgba(%f,%f,%f,%f)", gridColor, gridAlpha);
catch
axis.gridcolor = axisColor;
end

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-axis type-%
axis.type = eval(sprintf('axisData.%sScale', axisName));
axis.type = axisData.(axisName + "Scale");

%=========================================================================%
%=====================================================================%
%
% SET TICK LABELS
%
%=========================================================================%
%=====================================================================%

%-get tick label data-%
tickLabels = eval(sprintf('axisData.%sTickLabel', axisName));
tickValues = eval(sprintf('axisData.%sTick', axisName));
tickLabels = axisData.(axisName + "TickLabel");
tickValues = axisData.(axisName + "Tick");

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-there is not tick label case-%
if isempty(tickValues)

axis.ticks = '';
axis.ticks = "";
axis.showticklabels = false;
axis.autorange = true;

switch axisData.Box
case 'on'
case "on"
axis.mirror = true;
case 'off'
case "off"
axis.mirror = false;
end

%-------------------------------------------------------------------------%

%-there is tick labels case-%
else

else %-there is tick labels case-%
%-set tick values-%
axis.showticklabels = true;
axis.tickmode = 'array';
axis.tickmode = "array";

if ~iscategorical(tickValues)
axis.tickvals = tickValues;
end

%-set axis limits-%
axisLim = eval( sprintf('axisData.%sLim', axisName) );
axisLim = axisData.(axisName + "Lim");

if isnumeric(axisLim)
if strcmp(axis.type, 'linear')
if any(~isfinite(axisLim))
axis.range = shrinkInfLimits(axisData, axisLim, axisName);
elseif strcmp(axis.type, "linear")
axis.range = axisLim;
elseif strcmp(axis.type, 'log')
elseif strcmp(axis.type, "log")
axis.range = log10(axisLim);
end

elseif isduration(axisLim)
[temp,type] = convertDuration(axisLim);
if (~isduration(temp)) % duration class has specified .Format
axis.range = temp;
axis.type = 'duration';
axis.type = "duration";
axis.title = type;
axis.tickvals = convertDuration(axis.tickvals);
else
nticks = eval(['length(axisData.' axisName 'Tick)-1;']);
nticks = length(axisData.(axisName + "Tick"))-1;
delta = 0.1;
axis.range = [-delta nticks+delta];
axis.type = 'duration - specified format';
axis.type = "duration - specified format";
end

elseif isdatetime(axisLim)
axis.range = axisLim;
axis.type = 'date';

axis.type = "date";
elseif iscategorical(axisLim)
axis.autorange = true;
axis.type = 'category';

axis.type = "category";
else
axis.autorange = true;
end

%-box setting-%
switch axisData.Box
case 'on'
axis.mirror = 'ticks';
case 'off'
case "on"
axis.mirror = "ticks";
case "off"
axis.mirror = false;
end

Expand All @@ -171,132 +164,77 @@

%---------------------------------------------------------------------%

%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
%
% TODO: determine if following code piece is necessary. For this we need
% to test fig2plotly with more examples
%
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%

% %-LOG TYPE-%
% if strcmp(axis.type,'log')

% axis.range = log10(axisLim);
% axis.autotick = true;
% axis.nticks = eval(['length(axisData.' axisName 'Tick) + 1;']);

% %---------------------------------------------------------------------%

% %-LINEAR TYPE-%
% elseif strcmp(axis.type,'linear')

% %-----------------------------------------------------------------%

% % %-get tick label mode-%
% % tickLabelMode = eval(['axisData.' axisName 'TickLabelMode;']);

% % %-----------------------------------------------------------------%

% % %-AUTO MODE-%
% % if strcmp(tickLabelMode,'auto')

% %-------------------------------------------------------------%

% if isnumeric(axisLim)
% %-axis range-%
% axis.range = axisLim;
% %-axis tickvals-%
% axis.tickvals = tick;

% %-------------------------------------------------------------%

% elseif isduration(axisLim)
% [temp,type] = convertDuration(axisLim);

% if (~isduration(temp))
% axis.range = temp;
% axis.type = 'duration';
% axis.title = type;
% else
% nticks = eval(['length(axisData.' axisName 'Tick)-1;']);
% delta = 0.1;
% axis.range = [-delta nticks+delta];
% axis.type = 'duration - specified format';
% end

% %-------------------------------------------------------------%

% elseif isdatetime(axisLim)
% axis.range = convertDate(axisLim);
% axis.type = 'date';
% else
% % data is a category type other then duration and datetime
% end

% %-------------------------------------------------------------%

% if ~isnumeric(axisLim)
% %-axis autotick-%
% axis.autotick = true;
% %-axis numticks-%
% axis.nticks = eval(['length(axisData.' axisName 'Tick)+1']);
% end
% end
% end

%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%

%-------------------------------------------------------------------------%

%-axis direction-%
axisDirection = eval(sprintf('axisData.%sDir', axisName));
axisDirection = axisData.(axisName + "Dir");

if strcmp(axisDirection,'reverse')
if strcmp(axisDirection, "reverse")
axis.range = [axis.range(2) axis.range(1)];
end

%=========================================================================%
%=====================================================================%
%
% SET AXIS LABEL
%
%=========================================================================%
%=====================================================================%

%-get label data-%
label = eval(sprintf('axisData.%sLabel', axisName));
label = axisData.(axisName + "Label");
labelData = label;

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-STANDARDIZE UNITS-%
fontunits = label.FontUnits;
set(label,'FontUnits','points');
label.FontUnits = "points";

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-title label settings-%
if ~isempty(labelData.String)
axis.title = parseString(labelData.String,labelData.Interpreter);
end

axis.titlefont.color = sprintf('rgb(%f,%f,%f)', 255*labelData.Color);
axis.titlefont.color = sprintf("rgb(%f,%f,%f)", 255*labelData.Color);
axis.titlefont.size = labelData.FontSize;
axis.titlefont.family = matlab2plotlyfont(labelData.FontName);

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-REVERT UNITS-%
set(label,'FontUnits',fontunits);
label.FontUnits = fontunits;

%-------------------------------------------------------------------------%
%---------------------------------------------------------------------%

%-set visibility conditions-%
if strcmp(axisData.Visible,'on')
if strcmp(axisData.Visible, "on")
axis.showline = true;
else
axis.showticklabels = false;
axis.showline = false;
axis.ticks = '';
axis.ticks = "";
end
end

%-------------------------------------------------------------------------%
function lim = shrinkInfLimits(axis, lim, axisName)
arguments
axis
lim
axisName (1,1) string {mustBeMember(axisName,["Y" "X"])}
end
plots = axis.Children;
plots = plots(~arrayfun( ...
@(x) isa(x,"matlab.graphics.chart.decoration.ConstantLine"), ...
plots));
if ~isempty(plots)
dataRange = [Inf -Inf];
for i = 1:numel(plots)
dataRange(1) = min(dataRange(1),min(plots(i).(axisName+"Data")));
dataRange(2) = max(dataRange(2),max(plots(i).(axisName+"Data")));
end
dataRange = dataRange + [-1 1]*diff(dataRange)/8; % add some margin
else
dataRange = [0 1]; % matches default y-axis from `figure; xline(1)`
end
toShrink = ~isfinite(lim);
lim(toShrink) = dataRange(toShrink);
end