diff --git a/plotly/plotlyfig_aux/core/updateData.m b/plotly/plotlyfig_aux/core/updateData.m index e790c4cc..45c24b0a 100644 --- a/plotly/plotlyfig_aux/core/updateData.m +++ b/plotly/plotlyfig_aux/core/updateData.m @@ -34,7 +34,9 @@ elseif strcmpi(obj.PlotOptions.TreatAs, 'mesh') updateMesh(obj, dataIndex); elseif strcmpi(obj.PlotOptions.TreatAs, 'surfc') - updateSurfc(obj, dataIndex); + updateSurfc(obj, dataIndex); + elseif strcmpi(obj.PlotOptions.TreatAs, 'bubblecloud') + updateBubblecloud(obj,dataIndex); % this one will be revomed elseif strcmpi(obj.PlotOptions.TreatAs, 'streamtube') diff --git a/plotly/plotlyfig_aux/handlegraphics/updateBubblecloud.m b/plotly/plotlyfig_aux/handlegraphics/updateBubblecloud.m new file mode 100644 index 00000000..43646aa8 --- /dev/null +++ b/plotly/plotlyfig_aux/handlegraphics/updateBubblecloud.m @@ -0,0 +1,270 @@ +function updateBubblecloud(obj,~) + +%-AXIS INDEX-% +axIndex = obj.getAxisIndex(obj.State.Plot(1).AssociatedAxis); + +%-BubbleCloud (bc) DATA STRUCTURE- % +bcData = get(obj.State.Plot(1).Handle); + +%-CHECK FOR MULTIPLE AXES-% +[xsource, ysource] = findSourceAxis(obj,axIndex); + +% %-AXIS DATA-% +eval(['xaxis = obj.layout.xaxis' num2str(xsource) ';']); +eval(['yaxis = obj.layout.yaxis' num2str(ysource) ';']); + +obj.layout.xaxis1.showline = true; +obj.layout.xaxis1.zeroline = false; +obj.layout.xaxis1.autorange = false; +obj.layout.xaxis1.mirror = true; + +obj.layout.yaxis1.showline = true; +obj.layout.yaxis1.zeroline = false; +obj.layout.yaxis1.autorange = false; +obj.layout.yaxis1.mirror = true; + +%%%%%%%%%%%%%%% +%Useful for debugging!!! +% obj.layout.xaxis1.tickmode='auto'; +% obj.layout.xaxis1.nticks=11; +% obj.layout.xaxis1.showticklabels=0; +% obj.layout.yaxis1.tickmode='auto'; +% obj.layout.yaxis1.nticks=11; +% obj.layout.yaxis1.showticklabels=0; +%%%%%%%%%%%%%%% + +% obj.layout.title.text=''; +obj.layout.margin.t=80; +obj.layout.annotations{1}.text=''; + + +[sortedradii,RadiusIndex]=sort(sqrt(bcData.SizeData),'descend'); + +sortedradii=sortedradii/max(sortedradii); + +ar = obj.layout.width/obj.layout.height; + +xIN = xaxis.domain(2) - xaxis.domain(1); +yIN = yaxis.domain(2) - yaxis.domain(1); +axAR = ar*xIN/yIN; + +if isempty(bcData.GroupData) || all(bcData.GroupData==bcData.GroupData(1)) + XY = matlab.graphics.internal.layoutBubbleCloud(sortedradii,ar); + nGrps=1; + myIdx{1} = true(size(sortedradii)); +else + groups=bcData.GroupData(RadiusIndex); + undefined_ind=ismissing(groups); + grplist=unique(groups(~undefined_ind)); + groupradius=nan(numel(grplist),1); + for g=1:numel(grplist) + gp_ind=groups==grplist(g); + if any(gp_ind) + r=sortedradii(gp_ind); + xy=matlab.graphics.internal.layoutBubbleCloud(r,1); + groupradius(g)=max(sqrt(sum(xy.^2))+r); + XY(1:2,gp_ind)=xy; + end + end + + % Layout any nan/undefined as a separate group + if any(undefined_ind) + r=sortedradii(undefined_ind); + xy=matlab.graphics.internal.layoutBubbleCloud(r,1); + groupradius(end+1)=max(sqrt(sum(xy.^2))+r); + XY(1:2,undefined_ind)=xy; + end + + % Layout the circles that contain the groups + groupxyr=nan(3,numel(groupradius)); + groupxyr(3,:)=groupradius; + [gp_sortr,gp_sortind]=sort(groupradius,'descend'); + groupxyr(1:2,gp_sortind)=matlab.graphics.internal.layoutBubbleCloud(gp_sortr,ar); + + % Apply the group bubble position as an offset + for g=1:numel(grplist) + gp_ind=groups==grplist(g); + XY(1:2,gp_ind)=XY(1:2,gp_ind)+groupxyr(1:2,g); + end + + % Offset undefined group if it exists + if any(undefined_ind) + XY(1:2,undefined_ind)=XY(1:2,undefined_ind)+groupxyr(1:2,end); + end + + gps=unique(groups); + nGrps = numel(gps); + for i = 1:nGrps + gp_ind = groups == gps(i); + myIdx{i} = gp_ind; + end + +end + +xR = [min(XY(1,:)-sortedradii), max(XY(1,:)+sortedradii)]; +yR = [min(XY(2,:)-sortedradii), max(XY(2,:)+sortedradii)]; + +xR = xR + [-0.125, 0.125]*abs(diff(xR)); +yR = yR + [-0.125, 0.125]*abs(diff(yR)); + +dataAR = abs(diff(xR))/abs(diff(yR)); + +if dataAR > axAR + amounttopad = abs(diff(yR)) * dataAR/axAR - abs(diff(yR)); + yR = yR + [-amounttopad/2, amounttopad/2]; +else + amounttopad = abs(diff(xR)) * axAR/dataAR - abs(diff(xR)); + xR = xR + [-amounttopad/2, amounttopad/2]; +end + +radX = (2*sortedradii * (xIN*obj.layout.width) / abs(diff(xR))); + +obj.layout.xaxis1.range=xR; + +hei = obj.layout.height; +yCorr = -7.107E-13*hei^4 + 3.145E-09*hei^3 - 5.275E-06*hei^2 + 0.004197*hei - 1.602; + +% yCorr = -0.235; +if nGrps==1 + obj.layout.yaxis1.range = yR + [-yCorr, yCorr]; +else + obj.layout.yaxis1.range = yR + [0.16, -0.16]; +end +rads=radX; + +for bcIndex = 1:nGrps + %-------------------------------------------------------------------------% + + %-bc xaxis-% + obj.data{bcIndex}.xaxis = ['x' num2str(xsource)]; + + %-------------------------------------------------------------------------% + + %-bc yaxis-% + obj.data{bcIndex}.yaxis = ['y' num2str(ysource)]; + + %-------------------------------------------------------------------------% + + %-bc type-% + obj.data{bcIndex}.type = 'scatter'; + + %-------------------------------------------------------------------------% + + %-bc mode-% + obj.data{bcIndex}.mode = 'markers+text'; + + %-------------------------------------------------------------------------% + + %-bc visible-% + obj.data{bcIndex}.visible = strcmp(bcData.Visible,'on'); + + %-------------------------------------------------------------------------% + + labels = bcData.LabelData(RadiusIndex(myIdx{bcIndex})); + obj.data{bcIndex}.text = arrayfun(@(x) {char(x)}, labels); + obj.data{bcIndex}.textfont.family = matlab2plotlyfont(bcData.FontName); + obj.data{bcIndex}.textfont.color = sprintf('rgb(%i,%i,%i)',255*bcData.FontColor); + obj.data{bcIndex}.textfont.size = bcData.FontSize*1.5; + + %-------------------------------------------------------------------------% + + if isempty(bcData.SizeVariable) + bcData.SizeVariable='Size'; + end + if isempty(bcData.LabelVariable) + bcData.LabelVariable='Label'; + end + if isempty(bcData.GroupVariable) + bcData.GroupVariable='Group'; + end + + if nGrps>1 + obj.data{bcIndex}.hovertemplate = sprintf('%s: %%{hovertext}
%s: %%{text}',bcData.SizeVariable,bcData.LabelVariable); + j = find(myIdx{bcIndex}); + obj.data{bcIndex}.name = char(bcData.GroupData(RadiusIndex(j(1)))); + obj.data{bcIndex}.hovertext = arrayfun(@(x,y) {num2str(x)}, bcData.SizeData(RadiusIndex(myIdx{bcIndex})), 'UniformOutput',false); + else + obj.data{bcIndex}.hovertemplate = sprintf('%s: %%{hovertext}
%s: %%{text}',bcData.SizeVariable,bcData.LabelVariable); + obj.data{bcIndex}.hovertext = arrayfun(@(x) {num2str(x)}, bcData.SizeData(RadiusIndex(myIdx{bcIndex}))); + end + + %-------------------------------------------------------------------------% + + obj.data{bcIndex}.x = XY(1,myIdx{bcIndex}); + + %---------------------------------------------------------------------% + + obj.data{bcIndex}.y = XY(2,myIdx{bcIndex}); + + %---------------------------------------------------------------------% + + %-bc showlegend-% + try + leg = get(bcData.Annotation); + catch + leg=[]; + end + if ~isempty(leg) + legInfo = get(leg.LegendInformation); + + switch legInfo.IconDisplayStyle + case 'on' + showleg = true; + case 'off' + showleg = false; + end + end + + if isfield(bcData,'ZData') + if isempty(bcData.ZData) + obj.data{bcIndex}.showlegend = showleg; + end + end + + %---------------------------------------------------------------------% + + %-line color-% + if length(bcData) > 1 + obj.data{bcIndex}.marker.line.color{m} = childmarker.line.color{1}; + else + col=uint8(bcData.EdgeColor*255); + obj.data{bcIndex}.marker.line.color = sprintf('rgb(%i,%i,%i)',col); + end + + %---------------------------------------------------------------------% + + %-marker color-% + col=uint8(bcData.ColorOrder(bcIndex,:)*255); + obj.data{bcIndex}.marker.color = sprintf('rgb(%i,%i,%i)',col); + + %---------------------------------------------------------------------% + + %-sizeref-% + obj.data{bcIndex}.marker.sizeref = 1; + + %---------------------------------------------------------------------% + + %-sizemode-% + obj.data{bcIndex}.marker.sizemode = 'diameter'; + + %---------------------------------------------------------------------% + + %-symbol-% + obj.data{bcIndex}.marker.symbol = 'circle'; + + %---------------------------------------------------------------------% + + %-size-% + obj.data{bcIndex}.marker.size = rads(myIdx{bcIndex}); + + %---------------------------------------------------------------------% + + %-line width-% + obj.data{bcIndex}.marker.line.width = 1.5; + + %---------------------------------------------------------------------% + +end + +end + diff --git a/plotly/plotlyfig_aux/helpers/extractAxisData.m b/plotly/plotlyfig_aux/helpers/extractAxisData.m index a87d8b61..e7774c06 100644 --- a/plotly/plotlyfig_aux/helpers/extractAxisData.m +++ b/plotly/plotlyfig_aux/helpers/extractAxisData.m @@ -7,8 +7,15 @@ %-------------------------------------------------------------------------% %-axis-side-% -axis.side = eval(['axis_data.' axisName 'AxisLocation;']); - +try + axis.side = eval(['axis_data.' axisName 'AxisLocation;']); +catch + if axisName == 'X' + axis.side = 'bottom'; + elseif axisName == 'Y' + axis.side = 'left'; + end +end %-------------------------------------------------------------------------% %-axis zeroline-% @@ -36,16 +43,23 @@ %-------------------------------------------------------------------------% -ticklength = min(obj.PlotlyDefaults.MaxTickLength,... - max(axis_data.TickLength(1)*axis_data.Position(3)*obj.layout.width,... - axis_data.TickLength(1)*axis_data.Position(4)*obj.layout.height)); +try + ticklength = min(obj.PlotlyDefaults.MaxTickLength,... + max(axis_data.TickLength(1)*axis_data.Position(3)*obj.layout.width,... + axis_data.TickLength(1)*axis_data.Position(4)*obj.layout.height)); %-axis ticklen-% -axis.ticklen = ticklength; - + axis.ticklen = ticklength; +catch + axis.ticklen = 0; +end %-------------------------------------------------------------------------% -col = eval(['255*axis_data.' axisName 'Color;']); -axiscol = ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']; +try + col = eval(['255*axis_data.' axisName 'Color;']); +catch + col = [0,0,0]; +end +axiscol = sprintf('rgb(%i,%i,%i)',col); %-axis linecolor-% axis.linecolor = axiscol; @@ -57,29 +71,38 @@ axis.gridcolor = axiscol; %-------------------------------------------------------------------------% - -if strcmp(axis_data.XGrid, 'on') || strcmp(axis_data.XMinorGrid, 'on') - %-axis show grid-% - axis.showgrid = true; -else - axis.showgrid = false; +try + if strcmp(axis_data.XGrid, 'on') || strcmp(axis_data.XMinorGrid, 'on') + %-axis show grid-% + axis.showgrid = true; + else + axis.showgrid = false; + end +catch + axis.showgrid = false; end - %-------------------------------------------------------------------------% -grid = eval(['axis_data.' axisName 'Grid;']); -minorGrid = eval(['axis_data.' axisName 'MinorGrid;']); +try + grid = eval(['axis_data.' axisName 'Grid;']); + minorGrid = eval(['axis_data.' axisName 'MinorGrid;']); -if strcmp(grid, 'on') || strcmp(minorGrid, 'on') - %-axis show grid-% - axis.showgrid = true; -else + if strcmp(grid, 'on') || strcmp(minorGrid, 'on') + %-axis show grid-% + axis.showgrid = true; + else + axis.showgrid = false; + end +catch axis.showgrid = false; end %-------------------------------------------------------------------------% - -linewidth = max(1,axis_data.LineWidth*obj.PlotlyDefaults.AxisLineIncreaseFactor); +try + linewidth = max(1,axis_data.LineWidth*obj.PlotlyDefaults.AxisLineIncreaseFactor); +catch + linewidth = 0; +end %-axis line width-% axis.linewidth = linewidth; @@ -91,12 +114,21 @@ %-------------------------------------------------------------------------% %-axis type-% -axis.type = eval(['axis_data.' axisName 'Scale']); +try + axis.type = eval(['axis_data.' axisName 'Scale']); +catch + axis.type = 'linear'; +end %-------------------------------------------------------------------------% %-axis showtick labels / ticks-% -tick = eval(['axis_data.' axisName 'Tick']); +try + tick = eval(['axis_data.' axisName 'Tick']); +catch + tick=[]; +end + if isempty(tick) %-axis ticks-% @@ -107,13 +139,16 @@ axis.autorange = true; %---------------------------------------------------------------------% - - switch axis_data.Box - case 'on' - %-axis mirror-% - axis.mirror = true; - case 'off' - axis.mirror = false; + try + switch axis_data.Box + case 'on' + %-axis mirror-% + axis.mirror = true; + case 'off' + axis.mirror = false; + end + catch + axis.mirror = true; end %---------------------------------------------------------------------% @@ -295,50 +330,56 @@ end %-------------------------------------------------------------------------% - -Dir = eval(['axis_data.' axisName 'Dir;']); +try + Dir = eval(['axis_data.' axisName 'Dir;']); +catch + Dir = ''; +end if strcmp(Dir,'reverse') axis.range = [axis.range(2) axis.range(1)]; end %-------------------------------LABELS------------------------------------% +try + label = eval(['axis_data.' axisName 'Label;']); +catch + label=[]; +end +if ~isempty(label) + label_data = get(label); -label = eval(['axis_data.' axisName 'Label;']); - -label_data = get(label); - -%STANDARDIZE UNITS -fontunits = get(label,'FontUnits'); -set(label,'FontUnits','points'); + %STANDARDIZE UNITS + fontunits = get(label,'FontUnits'); + set(label,'FontUnits','points'); -%-------------------------------------------------------------------------% + %-------------------------------------------------------------------------% -%-title-% -if ~isempty(label_data.String) - axis.title = parseString(label_data.String,label_data.Interpreter); -end - -%-------------------------------------------------------------------------% + %-title-% + if ~isempty(label_data.String) + axis.title = parseString(label_data.String,label_data.Interpreter); + end -%-axis title font color-% -col = 255*label_data.Color; -axis.titlefont.color = ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']; + %-------------------------------------------------------------------------% -%-------------------------------------------------------------------------% + %-axis title font color-% + col = 255*label_data.Color; + axis.titlefont.color = ['rgb(' num2str(col(1)) ',' num2str(col(2)) ',' num2str(col(3)) ')']; -%-axis title font size-% -axis.titlefont.size = label_data.FontSize; + %-------------------------------------------------------------------------% -%-------------------------------------------------------------------------% + %-axis title font size-% + axis.titlefont.size = label_data.FontSize; -%-axis title font family-% -axis.titlefont.family = matlab2plotlyfont(label_data.FontName); + %-------------------------------------------------------------------------% -%-------------------------------------------------------------------------% + %-axis title font family-% + axis.titlefont.family = matlab2plotlyfont(label_data.FontName); -%REVERT UNITS -set(label,'FontUnits',fontunits); + %-------------------------------------------------------------------------% + %REVERT UNITS + set(label,'FontUnits',fontunits); +end %-------------------------------------------------------------------------% if strcmp(axis_data.Visible,'on') @@ -351,12 +392,6 @@ axis.showticklabels = false; %-axis ticks-% axis.ticks = ''; - %-axis showline-% - axis.showline = false; - %-axis showticklabels-% - axis.showticklabels = false; - %-axis ticks-% - axis.ticks = ''; end %-------------------------------------------------------------------------%