Нанесите круги с альфа-значениями в MATLAB

#matlab

#matlab

Вопрос:

Я создаю точечную диаграмму некоторых данных, как и вы, и у меня есть несколько повторяющихся точек данных, которые я хотел бы отобразить в виде окружностей с некоторым альфа-значением, чтобы накопление дополнительных точек в одном и том же месте было очевидным.

Насколько я могу судить, вы не можете задать альфа-свойства маленьких окружностей, которые вы создаете с помощью plot(x, y, 'o') , поэтому я прибегнул к рисованию тысяч маленьких окружностей, используя patch() себя:

 x = repmat([1:10], [1 10]);
y = round(10*rand(100, 1))/10;
xlim([0 11])
ylim([0 1])
p = ag_plot_little_circles(x', y, 10, [1 0 .4], 0.2);

function p = ag_plot_little_circles(x, y, circle, col, alpha)
%AG_PLOT_LITTLE_CIRCLES Plot circular circles of relative size circle
% Returns handles to all patches plotted

    % aspect is width / height
    fPos = get(gcf, 'Position');
    % need width, height in data values
    xl = xlim();
    yl = ylim();
    w = circle*(xl(2)-xl(1))/fPos(3);
    h = circle*(yl(2)-yl(1))/fPos(4);

    theta = 0:pi/5:2*pi;
    mx = w*sin(theta);
    my = h*cos(theta);
    num = 0;
    for k = 1:max(size(x))
        for f = 1:size(y,2)
            num = num 1;
            p(num) = patch(x(k) mx, y(k,f) my, col, 'FaceColor', col, 'FaceAlpha', alpha, 'EdgeColor', 'none');
        end
    end
end
  

Как вы можете видеть, это не оптимально, поскольку мне нужно знать и устанавливать размер графика ( xlim и ylim ), прежде чем я начерчу его так, чтобы круги в конечном итоге были круглыми. Если я изменю форму графика, они в конечном итоге станут овалами. В итоге я также получаю миллионы объектов, что является проблемой при создании легенд.

Есть ли более простой способ?

Комментарии:

1. не могли бы вы добавить пример вызова вашей функции? Было бы проще не читать подробно, чтобы разобраться в синтаксисе…

2. С новой версией matlab это кажется возможным, но это все еще недокументировано. Смотрите здесь

Ответ №1:

Я не нашел способа установить линейный маркер с альфа-значением в MATLAB.

Если вы посмотрите на свойства линии ((средне) низкоуровневую функцию, стоящую за построением графика), вы увидите, что вы можете определять маркеры, и их единственными свойствами являются их цвет ( MarkerEdgeColor или MarkerFaceColor ), который не принимает никаких альфа-значений (нет MarkerFaceAlpha свойства).

Итак, как вы это делаете с помощью патчей, кажется правильным.

Единственное, что я могу предложить, чтобы избежать наличия миллиардов объектов, — это сгруппировать их в hggroup, что позволит им отображаться как единый объект в легенде.

Ответ №2:

Я попытался выполнить общую функцию, используя patch . Это медленно и немного глючит, но для простых случаев работает нормально. MATLAB все же нужна альфа в виде реальной строки.

x и y являются точками для построения, w шириной линии, col цветом и a альфа-значением.

Пример:

 x = linspace(-2,2,100);
plotWithAlpha(x,sin(4*x),0.04,'r',0.2)


function [] = plotWithAlpha(x,y,w,col,a)
%function [] = plotWithAlpha(x,y,w,col,a)
    if(size(x,1) ~= 1)
       x = x.';
    end

    if(size(x,1) ~= 1)
       y = y.';
    end

    sz = length(x);

    % Calculate derrivatives of the curve
    X = csaps(1:sz(1),x,1);
    Y = csaps(1:sz(1),y,1);

    mx = fnval(fnder(X,1),1:sz(1)).';
    my = fnval(fnder(Y,1),1:sz(1)).';

    T = [mx my]; %tangent

    % Normalize tangents
    T = bsxfun(@rdivide,T,sqrt(sum(T.^2,2)));

    N = zeros(size(T));

    N(:,2) = 1;
    N(:,1) = -T(:,2)./T(:,1);

    N = bsxfun(@rdivide,N,sqrt(sum(N.^2,2)));

    N = N.';

    hold on

    for i = 2:length(x)
        X = [x(i-1) w*N(1,i-1) x(i) w*N(1,i) x(i-1)-w*N(1,i-1) x(i)-w*N(1,i)];
        Y = [y(i-1) w*N(2,i-1) y(i) w*N(2,i) y(i-1)-w*N(2,i-1) y(i)-w*N(2,i)];

        % Order the points
        D = pdist([X' Y']);
        D = squareform(D); D(D==0) = Inf;

        inds = 1;
        D(:,1) = Inf;

        [val ind] = min(D(1,:));
        inds(2) = ind;
        D(:,ind) = Inf;

        [val ind] = min(D(ind,:));
        inds(3) = ind;
        D(:,ind) = Inf;

        inds(4) = setxor(inds,1:4);

        X = X(inds);
        Y = Y(inds);

        patch(X,Y,col,'edgeColor','none','FaceAlpha',a)
    end

    hold off
  

Ответ №3:

У меня та же проблема, и мой точечный график имеет 100 000 точек. Идея ответа № 2 великолепна, но для меня было непрактично открывать свой график в Illustrator, потому что у меня было слишком много точек. Итак, я адаптировал ответ № 2 к пакетному процессу:

распечатайте рисунок в PDF-файле в matlab:

 print -dpdf foo.pdf
  

преобразуйте PDF-файл в формат svg с помощью pdf2svg из пакета debian pdf2svg:

 pdf2svg foo.pdf foo.svg
  

сделайте все синие объекты прозрачными:

 sed '/rgb(0%,0%,100%)/s/fill-opacity:1/fill-opacity:.2' < foo.svg > foo2.svg
  

конвертируйте foo2.svg в pdf с помощью rsvg-конвертировать из пакета debian
librsvg2-bin:

 rsvg-convert -f pdf -o foo2.pdf foo2.svg
  

Ответ №4:

Найдена patchline функция на Matlab Exchange, которая может принимать любые patch аргументы, включая 'FaceAlpha' :

http://www.mathworks.com/matlabcentral/fileexchange/36953-patchline/content/patchline.m

Ответ №5:

Насколько я могу судить, в MATLAB нет способа напрямую установить альфа для маркеров. Методы исправления не работают должным образом, когда альфа установлена ниже 0,03 или когда имеется намного больше 10 000 маркеров.

Обходной путь для создания графики качества публикации при наличии плотного облака маркеров — придать маркерам уникальный цвет. Затем распечатайте рисунок в EPS. Затем откройте в Illustrator, выберите все объекты этого цвета и установите прозрачность и цвет объектов в Illustrator. Это не одноэтапное решение, на которое можно было бы надеяться, но оно дает гораздо, гораздо более привлекательные результаты, чем использование внутренних функций MATLAB, и выполняется быстро, при условии, что у вас есть Illustrator или эквивалентный пакет векторной графики.