Search code examples
matlabplotmatlab-figuredendrogram

Coloring labels and lines in a dendrogram plot


I want to change the color of lines in the dendrogram corresponding to its label. However, I haven't seen anything like that before. So I want to at least change the color of the text labels.


Solution

  • It seems like there is no simple solution for that. The labels of the dendrogram are simply the y-axis tick labels and are all sharing the same color property. On the other hand, the lines are not constructed in sets, so all the lines connecting between to adjacent nodes are one object. The following example illustrates all that:

    color dend

    now the question is what is your specific purpose regarding the lines to color? mainly, what would you like to do with the vertical lines?


    Coloring the lables

    The idea in this woraround is to replace all the lables by text, so they could be colored saparetly:

    ax = gca; % get the axes handle
    lab = ax.YAxis.TickLabels; % get all the labels
    loc = ax.YAxis.TickValues; % get all labels location
    [ulab,~,lab_ind] = unique(lab); % find all unique labels
    clr = lines(numel(ulab)); % make a color map
    for k = 1:numel(ulab) % for every type of lable
        ind = strcmp(ulab{k},lab); % find all instances in lab
        x = repelem(ax.XAxis.Limits(1)-0.01,sum(ind)); % make an x position vector
         % place this lable at the same locations with a distinct color:
        text(x,loc(ind),lab(ind),'Color',clr(k,:));
    end
    ax.YAxis.TickLabels = []; % remove the original labels
    % replace the original labels with white space, to keep the axes position:
    ax.YAxis.TickLabels = repelem('  ',max(cellfun(@numel,lab)));
    

    color dend lables


    Coloring first level lines

    The idea here is similar - to place a line with the same color of the label above the current line. The nodes will be treated later.

    First, we have to collect all the coordinates data from the figure:

    ax = gca; % get the axes handle
    X = get(ax.Children,'XData'); % Get x values of all lines
    Y = get(ax.Children,'YData'); % Get y values of all lines
    

    this has to be done before adding the colored labels (if you choose to do that too), so you won't get an error.

    Then, we can loop through the lines and color them if they are placed at the y-axis ticks value (i.e. they have an integer y data). Recall (and look at the picture above for a reminder) that each line object is essentially 3 connected lines, so we want to look only at the first and last line:

    for k = 1:numel(Y)
        if Y{k}(1)==fix(Y{k}(1))
            line(ax,X{k}(1:2),Y{k}(1:2),'Color',clr(lab_ind(Y{k}(1)),:),...
                'LineWidth',2);
        end
        if Y{k}(3)==fix(Y{k}(3))
            line(ax,X{k}(3:4),Y{k}(3:4),'Color',clr(lab_ind(Y{k}(3)),:),...
                'LineWidth',2);
        end
    end
    

    clr and lab_ind are taken from the code above (for the labels), and I made the line a little thicker only for clarity.

    The result will be:

    color dend 2