Как вручную выполнить итерацию значений x и y графика и применить индексы x, y к функции тепловой карты? - PullRequest
0 голосов
/ 29 апреля 2019

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

Однако, поскольку в файле данных содержится так много снимков одного и того же соединения, обычный график приведет к тому, что тысячи точек данных будут наложены друг на друга, что приведет к нечитаемому изображению, поэтому я планирую использовать STATS, чтобы уменьшить информация на соединение 3 изображения с информацией мин, макс, среднее.

Я не знаю, как правильно использовать функцию plot для достижения этой цели, и документация для gnuplot предполагает только предварительно обработанные чистые (без избыточности матрицы) файлы данных, что мне не подходит.

Мне уже удалось создать массив средних данных для каждой подключенной пары (i, j) и сохранить данные в формате avg [1 + i + j * max], и он, похоже, выполняет то, что я намереваюсь сделать ,

Теперь то, что осталось бы сделать, - это нечто, похожее на

plot i:j:avg[1+i+j*max] with image

Мой текущий код (как показано ниже) использует файл данных для выбора значений x, y, а затем применяет avg [...] в отношении x, y в качестве значения z. Это приводит к тому, что многие многоярусные рисунки одного и того же значения могут быть идентифицированы по некоторым данным более толстыми, чем другие, и, вероятно, являются основной причиной того, почему мои изображения не получатся красивыми. Поэтому я пытаюсь просто повторить один раз (x, y) от 0 до n каждый и нарисовать значение z один раз для (x, y) -пары.

Я не уверен, как вручную указать команде plot, что она должна повторять x и y от 0 до n, а затем использовать avg [...] в качестве значения z для рисования изображения

текущий снятый gnuplot

# Color runs from white to green
set palette rgbformula -7,2,-7
set cblabel "Score"
unset cbtics
stats 'NxN_10GB.dat' using (column(10)) nooutput
set cbrange [STATS_min:STATS_max]

set output 'heatmap.png'
set title 'heatmap'
set xlabel 'en_id'
set ylabel 'pn_id'
set xrange [-1:10]
set yrange [-1:10]
set xtics 1
set ytics 1

stats 'NxN_10GB.dat' using (column(1)) nooutput
max_en = STATS_max
num_en = max_en + 1
stats 'NxN_10GB.dat' using (column(2)) nooutput
max_pn = STATS_max
num_pn = max_pn + 1
print sprintf("num_en = %d", num_en)
print sprintf("num_pn = %d", num_pn)


array Avg[num_en * num_pn]
ind(a,b) = 1+a+b*num_pn
getavg(a,b) = Avg[ind(a,b)]
do for [i=0:max_en] {
    do for [j=0:max_pn] {
    index = ind(i,j)
    stats 'NxN_10GB.dat' using ($1 == i && $2 == j && $3 == 10 ? column(10) : 1/0) nooutput
    print sprintf("index = %d",index)
    Avg[index] = STATS_mean
    print sprintf("Avg[%2d,%2d] = %f",i,j,Avg[index])
    }
}

plot 'NxN_10GB.dat' using 1:2:(Avg[1+$1+$2*num_pn]) with image , \
     'NxN_10GB.dat' using 1:2:(sprintf("%g",Avg[1+$1+$2*num_pn])) with labels

это урезанные данные, примерно 360 снимков / пара соединений ($ 1, $ 2). Меня сейчас интересуют только столбцы 1,2 и 10

en_id pn_id #en #pn time(sec) completions msg_size byte total_data(Gb) datarate(Gb/s)
0 0 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 1 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 2 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 3 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 4 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 5 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 6 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 7 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 8 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
0 9 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 0 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 1 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 2 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 3 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 4 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 5 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 6 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 7 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 8 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
1 9 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
2 0 10 10 10.0002 531 5048576 2680793856 21.4464 2.14459
2 1 10 10 10.0002 531 5048576 2680793856 21.4464 2.14459
2 2 10 10 10.0002 531 5048576 2680793856 21.4464 2.14459
3 3 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
3 4 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863
3 5 10 10 10.0002 532 5048576 2685842432 21.4867 2.14863

Таким образом, стандартная тепловая карта должна закрасить квадрат по индексу i, j с помощью color_code (значение (i, j)).

Все измеренные данные очень и очень близко друг к другу (что на самом деле хорошо), поэтому не удивительно, что мы видим довольно скучное однородное изображение:

set cbrange [0:STATS_max]

Однако, если я манипулирую цветовым диапазоном, чтобы он был очень близок к средним результатам, чтобы получить больше контраста, я начинаю видеть ужасные эффекты: set cbrange [STATS_min:STATS_max]

У меня есть 3 теории на то, что может вызвать это:

  1. в настоящее время мы рисуем каждую запись о соединении (но с тем же значением). Поэтому сложение такого количества точек может привести к странному поведению (мы можем увидеть это с более толстыми значениями, у которых было больше точек данных)

  2. квадраты по некоторым причинам перекрываются

  3. cbrange слишком мал, чтобы правильно вычислить нужный цвет (но я сомневаюсь в этом)

Относительно 1. это то, что я хотел бы подтвердить этим вопросом.

редактирование:

на догадках я создал несколько поддельных данных, чтобы уменьшить среднее значение datarate на одном из узлов. но результат так же далек от ожидаемого. Я сейчас совершенно сбит с толку :( enter image description here

как мы видим (1,1) значение avg упало до ~ 0.5 и должно просто появиться в более светло-зеленом цвете - но что это?!

edit2:

Я подготовил несколько образцов данных, чтобы проверить, все еще ли я в здравом уме. 1 точка данных для каждой (x, y) -пары дает именно тот результат, который я ищу: enter image description here

поэтому решение моей проблемы определенно возвращается к исходному вопросу.

Ответы [ 2 ]

1 голос
/ 30 апреля 2019

Вы можете использовать специальное имя файла ++, чтобы создать список (x, y) точек, которые затем можно использовать для индексации массива. См. help ++, чтобы узнать, как установить интервал между этими точками, используя set urange, set samples и т. Д. Помните, что эти координаты являются числами с плавающей запятой, поэтому вы должны округлить их до ближайшего целого числа, если хотите использовать их в качестве индексов массива.

Что-то вроде этого может работать для вас:

reset

set palette rgbformula -7,2,-7
1set cblabel "Score"
unset cbtics
stats 'NxN_10GB.dat' using (column(10)) nooutput
set cbrange [STATS_min:STATS_max]

#set output 'heatmap.png'
set title 'heatmap'
set xlabel 'en_id'
set ylabel 'pn_id'
set xtics 1
set ytics 1

stats 'NxN_10GB.dat' using (column(1)) nooutput
max_en = STATS_max
num_en = max_en + 1
stats 'NxN_10GB.dat' using (column(2)) nooutput
max_pn = STATS_max
num_pn = max_pn + 1
print sprintf("num_en = %d", num_en)
print sprintf("num_pn = %d", num_pn)

array Avg[num_en * num_pn]
ind(a,b) = 1+a+b*num_pn
getavg(a,b) = Avg[ind(a,b)]
do for [i=0:max_en] {
    do for [j=0:max_pn] {
    index = ind(i,j)
    stats 'NxN_10GB.dat' using ($1 == i && $2 == j && $3 == 10 ? column(10) : 1/0) nooutput
    print sprintf("index = %d",index)
    Avg[index] = STATS_mean
    print sprintf("Avg[%2d,%2d] = %f",i,j,Avg[index])
    }
}

set urange [0:num_en-1]
set vrange[0:num_pn-1]
set samples num_en
set isosamples num_pn
plot "++" using 1:2:(Avg[1+int($1+0.5)+int($2+0.5)*num_pn]) w image, \
     "++" using 1:2:(sprintf("%g",Avg[1+int($1+0.5)+int($2+0.5)*num_pn])) with labels
0 голосов
/ 30 апреля 2019

Мой способ реализовать (то, что я предполагаю) то, что вы хотите, будет следующим:

Вместо выполнения stats NxN раз с отфильтрованными данными, передайте ваши данные только один раз и сделайте статистикусамостоятельно, извлекая значения для минимума, максимума, суммы и числа и помещая их в массивы.Этот подход также допустим, если нет данных для одного из ваших подключений (см. Белый квадрат на графике ниже).

Построение в виде тепловой карты - один из способов.Вы также можете создать график типа «тепловая карта», используя with boxxyerror.Еще одно предложение для построения ваших данных - это построить график with yerrorbars и показать отклонение от среднего.При этом может быть также проще визуализировать минимальное и максимальное значения на одном графике.

Код:

### statistics: minimum, maximum, average
reset session
set size square
set key left

FILE = "NxN_10GB.dat"  # skip random generation section and replace $Data with FILE

# generate some random data
M = 10
N = 10
set print $Data
do for [i=1:500] {
    print sprintf("%d %d 0 0 0 0 0 0 0 %g",int(rand(0)*N),int(rand(0)*M),rand(0)/100.+2.14)
}
set print

# get the size of the array
stats $Data u 1:2 nooutput
M = int(STATS_max_y+1)
N = int(STATS_max_x+1)
ConnectionsCount = M*N

# initialize arrays
array Min[ConnectionsCount]   
array Max[ConnectionsCount]   
array Sum[ConnectionsCount]
array Count[ConnectionsCount]
do for [i=1:ConnectionsCount] {
    Min[i] = NaN; Max[i] = NaN; Sum[i] = 0; Count[i] = 0
}

IndexNo(m,n) = m*N + n +1
set table $Dummy
    plot $Data u \
        (a=Min[IndexNo($1,$2)], Min[IndexNo($1,$2)] = ($10>=a && (a==a)) ? a : $10, \
         b=Max[IndexNo($1,$2)], Max[IndexNo($1,$2)] = ($10<=b && (b==b)) ? b : $10, \
         Sum[IndexNo($1,$2)] = Sum[IndexNo($1,$2)] + $10, \
         Count[IndexNo($1,$2)] = Count[IndexNo($1,$2)]+1 ) with table
unset table

set xrange[-0.5:N-0.5]
set xtics out
set yrange[-0.5:M-0.5]
set ytics out

SumTotal = sum[i=1:ConnectionsCount] (Sum[i])
CountTotal = sum[i=1:ConnectionsCount] (Count[i])
AverageTotal = SumTotal/CountTotal
print AverageTotal

set samples ConnectionsCount  # number of samples for '+'
set multiplot layout 2,1
    plot '+' u (int($0)%N):(int($0/N)):(0.5):(0.5):(Sum[$0+1]/Count[$0+1]) w boxxyerror lc palette fs solid 1.0 not

    set title sprintf("Deviation of average from total average %g",AverageTotal)    
    set size nosquare
    set xlabel "Number of connection"
    set xrange[0:ConnectionsCount+1]
    set yrange[*:*]
    plot '+' u ($0+1):(Sum[$0+1]/Count[$0+1]-AverageTotal):(Min[$0+1]-AverageTotal):(Max[$0+1]-AverageTotal) \
        with yerr pt 7 lc rgb "red" notitle
unset multiplot
### end of code

Результат:

enter image description here

...