Search code examples
matlabalignmentcustomizationmatlab-figureheatmap

Fixing a clustergram column label misalignment


In the code below I try to highlight a specific column by red. However, the resulting label color bar is not aligned with the labels, as shown in the image. How can I correct this?

datdat = randn(5,10);
regregnames = {'A', 'B', 'C', 'D', 'E'};
colors = cell(1,size(datdat,2));
for i=1:size(datdat,2)
    colors{i} = [1,1,1];
end
colors{3} = [1,0,0];
s.Labels = arrayfun(@num2str, 1:size(datdat,2), 'UniformOutput', false);
s.Colors = colors;
clscls = clustergram(datdat, 'RowLabels', regregnames, 'ColumnLabels', s.Labels, 'ColumnLabelsColor', s, 'LabelsWithMarkers', true);

Image with misalignment


Solution

  • This is definitely a bug in MATLAB. How do I know? By inspecting the clustergram.plot function.

    If we set a breakpoint on line 142, positionAxes(obj, imAxes), and run your code until that point, we get the following figure:

    Intermediate plot with correct positioning of the bottom bar

    where the alignment is correct, but the dendrogram is not visible. Then, the code proceeds to reposition the axes (mainly making them smaller), while unfortunately neglecting the bottom part with the red label.

    To understand how to fix this, we should go a bit back, into HeatMap.plot > initHMAxes where this bottom bar is created and find where its handle is stored. Then, all we need to do is adjust the position of this element in accordance with the rest of the clustergram (HeatMap).

    I'll leave digging through the handles/appdata "as an exercise to the reader", but long story short, just add this to the end of your code:

    hAx = struct(clscls).HMAxesHandle;
    data = getappdata(hAx, 'HeatMapAxesData');
    data.XMarkerAxes.Position = data.XMarkerAxes.Position.*[0 1 0 1] + hAx.Position.*[1 0 1 0];
    

    The result:

    The desired result


    BTW, on R2017b I'm getting the following warning:

    Warning: COLUMNLABELSCOLOR is not supported and will be removed in a future release.
    Use LabelsWithMarkers for similar functionality.
    

    So technically this is not a bug, but rather an unsupported feature.