123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- function hBeanAx = beanPlot(groupData, groupLabels, colors, offsetScale, hAx, varargin)
- if ~exist('hAx', 'var')
- hBeanFig = createFullScreenFig;
- hBeanFig.Position(4) = hBeanFig.Position(3) / 2;
- hAx = gca;
- end
- switch nargin
- case 6
- support = varargin{1};
- plotOrientation = 'horizontal'; % Can change to plotHorizontalBool.
- halveBean = false;
- useAlpha = true;
- bwOption = true;
- case 7
- support = varargin{1};
- plotOrientation = varargin{2};
- halveBean = false;
- useAlpha = true;
- bwOption = true;
- case 8
- support = varargin{1};
- plotOrientation = varargin{2};
- halveBean = varargin{3};
- useAlpha = true;
- bwOption = true;
- case 9
- support = varargin{1};
- plotOrientation = varargin{2};
- halveBean = varargin{3};
- useAlpha = varargin{4};
- bwOption = true;
- case 10
- support = varargin{1};
- plotOrientation = varargin{2};
- halveBean = varargin{3};
- useAlpha = varargin{4};
- bwOption = varargin{5};
- otherwise
- support = 'unbounded';
- plotOrientation = 'horizontal'; % Can change to plotHorizontalBool.
- halveBean = false;
- useAlpha = true;
- bwOption = true;
- end
- hold(hAx, 'on');
- nGroups = numel(groupLabels);
- zeroLineX = [0 0];
- if nGroups == 1
- zeroLineColor = [1 1 1] * 0.5;
- zeroLineY = offsetScale * [1 1.5];
- else
- zeroLineColor = mean(rgb2gray(colors));
- zeroLineY = offsetScale * [1 / 2 (nGroups + 1 / 2)];
- end
- % Flip variables for vertical plotting orientation.
- if strcmp(plotOrientation, 'vertical')
- [zeroLineX, zeroLineY] = deal(zeroLineY, zeroLineX);
- end
- hZeroLine = plot(zeroLineX, zeroLineY, 'LineStyle', '--', 'Color', zeroLineColor);
- bandWidth = nan(1, nGroups);
- for iGroup = 1: nGroups
- data = groupData{iGroup};
- if numel(data) > 1 && range(data) ~=0
- if ~strcmp(support, 'unbounded')
- [bw, f, xi, cdf] = kde(data, 2^10, support(1), support(2));
- else
- [bw, f, xi, cdf] = kde(data, 2^10);
- end
- bandWidth(iGroup) = bw;
- end
- end
- bwMean = nanmedian(bandWidth);
- % 1/2 for the half bean and 2 / 15 for two times the data ticks length.
- if halveBean
- halfOffsetFactor = (1 / 2 + 2 / 15);
- else
- halfOffsetFactor = 1 + 3 / 15;
- end
- for iGroup = 1: nGroups
- % Define data and plot format.
- data = groupData{iGroup};
- iColor = colors(iGroup, :);
- offset = iGroup * offsetScale * halfOffsetFactor;
- % 1-D strip plot of individual data points.
- dataPointAlpha = 0.1;
- if nGroups == 1
- dataPointColor = [1 1 1] * 0.5;
- else
- dataPointColor = mean(rgb2gray(colors));
- end
- if useAlpha
- dataPointColor = [dataPointColor dataPointAlpha];
- end
- for iDataPoint = 1: numel(data)
- dataPointX = data(iDataPoint) * [1 1];
- if halveBean
- dataPointY = offset + offsetScale / 15 * [-1 0];
- else
- dataPointY = offset + offsetScale / 20 * [-1 1];
- end
- % Flip variables for vertical plotting orientation.
- if strcmp(plotOrientation, 'vertical')
- [dataPointX, dataPointY] = deal(dataPointY, dataPointX);
- end
- plot(dataPointX, dataPointY, 'Color', dataPointColor, 'LineWidth', 0.5);
- end
- % Get kernel density estimate.
- if bwOption
- bw = bwMean; % Dirty way fo homogeneizing the bandwidth.
- if numel(data) <=10
- bw = numel(data) / 10 * bw;
- end
- else
- bw = bandWidth(iGroup);
- end
- % end
- if numel(data) > 1 && range(data) ~=0
- % if ~strcmp(support, 'unbounded')
- % [bandwidth, f, xi, cdf] = kde(data, 2^10, support(1), support(2));
- [f, xi] = ksdensity(data, 'Support', support, 'BoundaryCorrection', 'reflection', 'BandWidth', bw);
- % else
- % [bandWidth, f, xi, cdf] = kde(data, 2^10);
- % end
- f = f(:)';
- xi = xi(:)';
- else
- f = 1;
- xi = data(1);
- end
- % [f, xi] = ksdensity(data, 'Support', support, 'BoundaryCorrection', 'reflection', 'BandWidth', bw);
- % Normalize the area for plots with different value ranges.
- maxF = max(f);
- f = f / maxF * offsetScale / 2;
- % Half bean.
- if halveBean
- areaXCoords = [xi fliplr(xi)]; % This is the variable value.
- areaYCoords = [f zeros(size(f))] + offset; % This is the variable frequency.
- else
- % Concatenate to make the bean area.
- areaXCoords = [xi xi(end: -1: 1)]; % This is the variable value.
- areaYCoords = [-f f(end: -1: 1)] + offset; % This is the variable frequency.
- end
- % Flip variables for vertical plotting orientation.
- if strcmp(plotOrientation, 'vertical')
- [areaXCoords, areaYCoords] = deal(areaYCoords, areaXCoords);
- end
- fill(areaXCoords, areaYCoords, iColor, ...
- 'FaceAlpha', 0.7, 'EdgeColor', 'none')
- % Now plot quantiles
- % quantileValue = 0.25;
- lineFormatCell = {'Color', iColor, 'LineWidth', 1};
- % plotQuantileBean(data, quantileValue, offsetX, lineFormatCell)
- % quantileValue = 0.5;
- % lineFormatCell{end} = 2;
- % plotQuantileBean(data, quantileValue, offsetX, lineFormatCell)
- % quantileValue = 0.75;
- % lineFormatCell{end} = 1;
- % plotQuantileBean(data, quantileValue, offsetX, lineFormatCell)
- lineFormatCell{end} = 2;
- plotBeanMean(data, offsetScale, offset, lineFormatCell, plotOrientation, halveBean)
- end
- hBeanAx = gca;
- prettifyAxes(hBeanAx)
- hBeanAx.XMinorTick = 'off';
- hBeanAx.YMinorTick = 'off';
- % Flip variables for vertical plotting orientation.
- if strcmp(plotOrientation, 'vertical')
- hBeanAx.XTick = offsetScale * (1: nGroups) * halfOffsetFactor;
- hBeanAx.XTickLabel = groupLabels;
- hBeanAx.XTickLabelRotation = 0;
- % if nGroups > 1
- % hBeanAx.PlotBoxAspectRatio = [2 1 1];
- % end
- if halveBean
- hBeanAx.XLim = offsetScale * [(halfOffsetFactor - 1 / 15) ;
- ( 1 / 2 + nGroups * halfOffsetFactor + 1 / 15)];
- else
- hBeanAx.XLim = offsetScale * [(- 1 / 2 + halfOffsetFactor - 2 / 15) ...
- (+ 1 / 2 + halfOffsetFactor * nGroups + 2 / 15)];
- end
- else
- hBeanAx.YTick = offsetScale * (1: nGroups) * halfOffsetFactor;
- hBeanAx.YTickLabel = groupLabels;
- hBeanAx.YTickLabelRotation = 0;
- % if nGroups > 1
- % hBeanAx.PlotBoxAspectRatio = [1 1 1];
- % end
- % Add option for half bean
- if halveBean
- hBeanAx.YLim = offsetScale * [(halfOffsetFactor - 1.2 / 15) ;
- ( 1 / 2 + nGroups * halfOffsetFactor + 1 / 15)];
- else
- hBeanAx.YLim = offsetScale * [(- 1 / 2 + halfOffsetFactor - 2 / 15) ...
- (+ 1 / 2 + halfOffsetFactor * nGroups + 2 / 15)];
- end
- if nGroups == 1; axis tight; end
- end
- % Flip variables for vertical plotting orientation.
- if strcmp(plotOrientation, 'vertical')
- hZeroLine.XData = get(gca, 'XLim');
- else
- hZeroLine.YData = get(gca, 'YLim');
- end
- end
- function plotQuantileBean(data, quantileValue, offset, lineFormatCell)
- [f, xi] = ksdensity(data);
- quantileYCoords = quantile(data, quantileValue) * [1 1];
- [~, quantileInd] = min(abs(quantileYCoords(1) - xi));
- quantileXCoords = [-1 1] * f(quantileInd);
- hold on
- plot(quantileXCoords + offset, quantileYCoords, lineFormatCell{:})
- end
- function plotBeanMean(data, offsetScale, offset, lineFormatCell, plotOrientation, halveBean)
- [f, xi] = ksdensity(data);
- meanXCoords = nanmean(data) * [1 1];
- if halveBean
- meanYCoords = [0 1] * offsetScale / 2 + offset;
- else
- meanYCoords = [-1 1] * offsetScale / 2 + offset;
- end
- [~, meanInd] = min(abs(meanYCoords(1) - xi));
- if strcmp(plotOrientation, 'vertical')
- [meanXCoords, meanYCoords] = deal(meanYCoords, meanXCoords);
- end
- hold on
- plot(meanXCoords, meanYCoords, lineFormatCell{:})
- end
|