Skip to content

Commit 9e42cfb

Browse files
Merge pull request #492 from plotly/fix-inf-xlim-zoom
Fix default zoom when user has set XLim/Ylim to Inf
2 parents f54933b + d26df7a commit 9e42cfb

File tree

1 file changed

+84
-146
lines changed

1 file changed

+84
-146
lines changed
Lines changed: 84 additions & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,37 @@
11
function [axis, exponentFormat] = extractAxisData(obj,axisData,axisName)
22
% extract information related to each axis
33
% axisData is the data extrated from the figure, axisName take the
4-
% values 'x' 'y' or 'z'
4+
% values "x" "y" or "z"
55

6-
%=========================================================================%
6+
%=====================================================================%
77
%
88
% AXIS INITIALIZATION
99
%
10-
%=========================================================================%
10+
%=====================================================================%
1111

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

1718
try
18-
exponentFormat = eval(sprintf('axisData.%sAxis.Exponent', axisName));
19+
exponentFormat = axisData.(axisName + "Axis").Exponent;
1920
catch
2021
exponentFormat = 0;
2122
end
2223

23-
axis.side = eval(sprintf('axisData.%sAxisLocation', axisName));
24+
axis.side = axisData.(axisName + "AxisLocation");
2425
axis.zeroline = false;
2526
axis.autorange = false;
2627
axis.linecolor = axisColor;
2728
axis.linewidth = lineWidth;
2829
axis.exponentformat = obj.PlotlyDefaults.ExponentFormat;
2930

30-
%-------------------------------------------------------------------------%
31+
%---------------------------------------------------------------------%
3132

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

4748
switch axisData.TickDir
48-
case 'in'
49-
axis.ticks = 'inside';
50-
case 'out'
51-
axis.ticks = 'outside';
49+
case "in"
50+
axis.ticks = "inside";
51+
case "out"
52+
axis.ticks = "outside";
5253
end
5354

54-
%-------------------------------------------------------------------------%
55+
%---------------------------------------------------------------------%
5556

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

60-
if strcmp(isGrid, 'on') || strcmp(isMinorGrid, 'on')
61+
if strcmp(isGrid, "on") || strcmp(isMinorGrid, "on")
6162
axis.showgrid = true;
6263
axis.gridwidth = lineWidth;
6364
else
6465
axis.showgrid = false;
6566
end
6667

67-
%-------------------------------------------------------------------------%
68+
%---------------------------------------------------------------------%
6869

6970
%-axis grid color-%
7071
try
7172
gridColor = 255*axisData.GridColor;
7273
gridAlpha = axisData.GridAlpha;
73-
axis.gridcolor = sprintf('rgba(%f,,%f,%f,%f)', gridColor, gridAlpha);
74+
axis.gridcolor = sprintf("rgba(%f,%f,%f,%f)", gridColor, gridAlpha);
7475
catch
7576
axis.gridcolor = axisColor;
7677
end
7778

78-
%-------------------------------------------------------------------------%
79+
%---------------------------------------------------------------------%
7980

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

83-
%=========================================================================%
84+
%=====================================================================%
8485
%
8586
% SET TICK LABELS
8687
%
87-
%=========================================================================%
88+
%=====================================================================%
8889

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

93-
%-------------------------------------------------------------------------%
94+
%---------------------------------------------------------------------%
9495

9596
%-there is not tick label case-%
9697
if isempty(tickValues)
97-
98-
axis.ticks = '';
98+
axis.ticks = "";
9999
axis.showticklabels = false;
100100
axis.autorange = true;
101-
101+
102102
switch axisData.Box
103-
case 'on'
103+
case "on"
104104
axis.mirror = true;
105-
case 'off'
105+
case "off"
106106
axis.mirror = false;
107107
end
108-
109-
%-------------------------------------------------------------------------%
110-
111-
%-there is tick labels case-%
112-
else
113-
108+
else %-there is tick labels case-%
114109
%-set tick values-%
115110
axis.showticklabels = true;
116-
axis.tickmode = 'array';
111+
axis.tickmode = "array";
117112

118113
if ~iscategorical(tickValues)
119114
axis.tickvals = tickValues;
120115
end
121116

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

125120
if isnumeric(axisLim)
126-
if strcmp(axis.type, 'linear')
121+
if any(~isfinite(axisLim))
122+
axis.range = shrinkInfLimits(axisData, axisLim, axisName);
123+
elseif strcmp(axis.type, "linear")
127124
axis.range = axisLim;
128-
elseif strcmp(axis.type, 'log')
125+
elseif strcmp(axis.type, "log")
129126
axis.range = log10(axisLim);
130127
end
131-
132128
elseif isduration(axisLim)
133129
[temp,type] = convertDuration(axisLim);
134130
if (~isduration(temp)) % duration class has specified .Format
135131
axis.range = temp;
136-
axis.type = 'duration';
132+
axis.type = "duration";
137133
axis.title = type;
138134
axis.tickvals = convertDuration(axis.tickvals);
139135
else
140-
nticks = eval(['length(axisData.' axisName 'Tick)-1;']);
136+
nticks = length(axisData.(axisName + "Tick"))-1;
141137
delta = 0.1;
142138
axis.range = [-delta nticks+delta];
143-
axis.type = 'duration - specified format';
139+
axis.type = "duration - specified format";
144140
end
145-
146141
elseif isdatetime(axisLim)
147142
axis.range = axisLim;
148-
axis.type = 'date';
149-
143+
axis.type = "date";
150144
elseif iscategorical(axisLim)
151145
axis.autorange = true;
152-
axis.type = 'category';
153-
146+
axis.type = "category";
154147
else
155148
axis.autorange = true;
156149
end
157150

158151
%-box setting-%
159152
switch axisData.Box
160-
case 'on'
161-
axis.mirror = 'ticks';
162-
case 'off'
153+
case "on"
154+
axis.mirror = "ticks";
155+
case "off"
163156
axis.mirror = false;
164157
end
165158

@@ -171,132 +164,77 @@
171164

172165
%---------------------------------------------------------------------%
173166

174-
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
175-
%
176-
% TODO: determine if following code piece is necessary. For this we need
177-
% to test fig2plotly with more examples
178-
%
179-
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
180-
181-
% %-LOG TYPE-%
182-
% if strcmp(axis.type,'log')
183-
184-
% axis.range = log10(axisLim);
185-
% axis.autotick = true;
186-
% axis.nticks = eval(['length(axisData.' axisName 'Tick) + 1;']);
187-
188-
% %---------------------------------------------------------------------%
189-
190-
% %-LINEAR TYPE-%
191-
% elseif strcmp(axis.type,'linear')
192-
193-
% %-----------------------------------------------------------------%
194-
195-
% % %-get tick label mode-%
196-
% % tickLabelMode = eval(['axisData.' axisName 'TickLabelMode;']);
197-
198-
% % %-----------------------------------------------------------------%
199-
200-
% % %-AUTO MODE-%
201-
% % if strcmp(tickLabelMode,'auto')
202-
203-
% %-------------------------------------------------------------%
204-
205-
% if isnumeric(axisLim)
206-
% %-axis range-%
207-
% axis.range = axisLim;
208-
% %-axis tickvals-%
209-
% axis.tickvals = tick;
210-
211-
% %-------------------------------------------------------------%
212-
213-
% elseif isduration(axisLim)
214-
% [temp,type] = convertDuration(axisLim);
215-
216-
% if (~isduration(temp))
217-
% axis.range = temp;
218-
% axis.type = 'duration';
219-
% axis.title = type;
220-
% else
221-
% nticks = eval(['length(axisData.' axisName 'Tick)-1;']);
222-
% delta = 0.1;
223-
% axis.range = [-delta nticks+delta];
224-
% axis.type = 'duration - specified format';
225-
% end
226-
227-
% %-------------------------------------------------------------%
228-
229-
% elseif isdatetime(axisLim)
230-
% axis.range = convertDate(axisLim);
231-
% axis.type = 'date';
232-
% else
233-
% % data is a category type other then duration and datetime
234-
% end
235-
236-
% %-------------------------------------------------------------%
237-
238-
% if ~isnumeric(axisLim)
239-
% %-axis autotick-%
240-
% axis.autotick = true;
241-
% %-axis numticks-%
242-
% axis.nticks = eval(['length(axisData.' axisName 'Tick)+1']);
243-
% end
244-
% end
245-
% end
246-
247-
%+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
248-
249-
%-------------------------------------------------------------------------%
250-
251167
%-axis direction-%
252-
axisDirection = eval(sprintf('axisData.%sDir', axisName));
168+
axisDirection = axisData.(axisName + "Dir");
253169

254-
if strcmp(axisDirection,'reverse')
170+
if strcmp(axisDirection, "reverse")
255171
axis.range = [axis.range(2) axis.range(1)];
256172
end
257173

258-
%=========================================================================%
174+
%=====================================================================%
259175
%
260176
% SET AXIS LABEL
261177
%
262-
%=========================================================================%
178+
%=====================================================================%
263179

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

268-
%-------------------------------------------------------------------------%
184+
%---------------------------------------------------------------------%
269185

270186
%-STANDARDIZE UNITS-%
271187
fontunits = label.FontUnits;
272-
set(label,'FontUnits','points');
188+
label.FontUnits = "points";
273189

274-
%-------------------------------------------------------------------------%
190+
%---------------------------------------------------------------------%
275191

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

281-
axis.titlefont.color = sprintf('rgb(%f,%f,%f)', 255*labelData.Color);
197+
axis.titlefont.color = sprintf("rgb(%f,%f,%f)", 255*labelData.Color);
282198
axis.titlefont.size = labelData.FontSize;
283199
axis.titlefont.family = matlab2plotlyfont(labelData.FontName);
284200

285-
%-------------------------------------------------------------------------%
201+
%---------------------------------------------------------------------%
286202

287203
%-REVERT UNITS-%
288-
set(label,'FontUnits',fontunits);
204+
label.FontUnits = fontunits;
289205

290-
%-------------------------------------------------------------------------%
206+
%---------------------------------------------------------------------%
291207

292208
%-set visibility conditions-%
293-
if strcmp(axisData.Visible,'on')
209+
if strcmp(axisData.Visible, "on")
294210
axis.showline = true;
295211
else
296212
axis.showticklabels = false;
297213
axis.showline = false;
298-
axis.ticks = '';
214+
axis.ticks = "";
299215
end
216+
end
300217

301-
%-------------------------------------------------------------------------%
218+
function lim = shrinkInfLimits(axis, lim, axisName)
219+
arguments
220+
axis
221+
lim
222+
axisName (1,1) string {mustBeMember(axisName,["Y" "X"])}
223+
end
224+
plots = axis.Children;
225+
plots = plots(~arrayfun( ...
226+
@(x) isa(x,"matlab.graphics.chart.decoration.ConstantLine"), ...
227+
plots));
228+
if ~isempty(plots)
229+
dataRange = [Inf -Inf];
230+
for i = 1:numel(plots)
231+
dataRange(1) = min(dataRange(1),min(plots(i).(axisName+"Data")));
232+
dataRange(2) = max(dataRange(2),max(plots(i).(axisName+"Data")));
233+
end
234+
dataRange = dataRange + [-1 1]*diff(dataRange)/8; % add some margin
235+
else
236+
dataRange = [0 1]; % matches default y-axis from `figure; xline(1)`
237+
end
238+
toShrink = ~isfinite(lim);
239+
lim(toShrink) = dataRange(toShrink);
302240
end

0 commit comments

Comments
 (0)