Продолжить с остальной частью мультиплота, несмотря на ошибку «все точки Y значение неопределено» в одном подзаговоре - PullRequest
0 голосов
/ 07 января 2019

В мультиплоте, когда я получаю сообщение об ошибке all points Y value undefined для одного под-сюжета , как я могу заставить gnuplot продолжить и вывести хотя бы оставшиеся под-сюжеты?

Справочная информация:

Давайте предположим следующий пример широтно-временных данных от некоторого GPS-трекера. На самом деле мои данные содержат более 100 тыс. Субсекундных выборок, охватывающих несколько дней.

$DATA << EOD
# Zero values are invalid (no GPS fix) and shall be ignored.
#
# Segment 1) Trip 1 around longitude 50.0:
00:01   49.99990
00:02   49.99994
00:03   50.00006
00:04   50.00008
00:05   0
00:06   0
00:07   0
00:08   50.00004
00:09   50.00002
#
# Segment 2) no data recorded at all
# ...
#
# Segment 3) Trip 2 around longitude -164.0:
00:21   -163.99992
00:22   -163.99998
00:23   -164.00006
00:24   -164.00004
00:25   0
00:26   0
00:27   0
00:28   -164.00002
00:29   -164.00002
#
# Segment 3) only invalid data recorded
00:31   0
00:32   0
00:33   0
00:34   0
00:35   0
00:36   0
00:37   0
00:38   0
00:39   0
#
# Segment 4) Trip 3 around longitude 120.0:
00:41   120.00000
00:42   120.00002
00:43   119.99998
00:44   119.99996
00:45   119.99994
00:46   119.99998
00:47   120.00002
00:48   120.00006
00:49   120.00002
EOD

Я хочу отобразить эти данные в мультиплоте вместе с другими данными о времени из другого источника, с другими временами выборки, но с использованием того же диапазона X. Для демонстрации давайте просто используем:

# data for second sub-plot
y(x) = sin(x)

Я могу построить полный диапазон времени (от 00:00 до 00:50) с помощью следующего кода gnuplot:

# General settings
timeformat = "%H:%M"
set xdata time
set timefmt timeformat
set xtics timedate
set xtics format timeformat
set xtics 10*60
set mxtics 10
set ytics format "%.5f"

# Function to skip zero / invalid longitude values:
strip_zero(Y) = ( Y == 0 ? NaN : Y )

# Plot full X range:
set multiplot layout 2, 1
set xrange [0 : 50*60]
set yrange [-180<*:*<180]
plot $DATA using 1: (strip_zero($2)) with lines notitle, \
     $DATA using 1: (strip_zero($2)) with points notitle
set yrange [*:*]
plot y(x) with lines
unset multiplot

Результат: мультиплот с полным диапазоном X

Очевидно, что разрешение вокруг кластеров в 50, -160 и 120 довольно плохое. Поэтому я хочу разбить диапазон X на несколько 10-минутных зум-фрагментов . Используя автоматическое масштабирование, ось Y будет увеличена, чтобы получить лучшее разрешение. Я ожидаю получить 5 графиков, покрывающих (примерно) области, отмеченные как 1 - 5 на диаграмме выше.

Я использую цикл do for для генерации увеличенных диаграмм:

# Plot 10-minute slices:
do for [x_min = 0 : 40 : 10] {
    set multiplot layout 2, 1
    set xrange [x_min * 60 : (x_min + 10) * 60]
    set yrange [-180<*:*<180]
    plot $DATA using 1: (strip_zero($2)) with lines notitle, \
         $DATA using 1: (strip_zero($2)) with point notitle
    set yrange [*:*]
    plot y(x) with lines
    unset multiplot
}

Сегмент 1 все еще может быть получен как ожидалось: мультиплот увеличен до первых 10 минут

Но при нажатии на сегмент 2 (диапазон X от 00:10 до 00:20) и позже на сегмент 4 (от 00:30 до 00:40) я получаю ошибку all points Y value undefined и gnuplot завершает работу. Обратите внимание, что в сегменте 2 происходит сбой, поскольку в наборе данных вообще нет точек, но в сегменте 4 происходит сбой, поскольку существующие точки преобразуются в NaN с помощью strip_zero().

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

Мне все равно что выводит gnuplot вместо провального подзаговора (ничего, пустое пространство диаграммы, пустая сетка, соединительная линия между точками за пределами заданного X-диапазона, ... ).

  • Перемещение цикла for из gnuplot в какой-либо сценарий оболочки может работать только для одного (под) графика, но не решает проблему пропуска дальнейших вспомогательных участков в мультиплоте.
  • Изменение порядка вспомогательных сюжетов (так, чтобы непроблематичные вспомогательные сюжеты строились до выхода из gnuplot) не является вариантом, поскольку все данные вспомогательного сюжета в основном подвержены той же проблеме.

Я бы предпочел решения, которые не требуют внешней предварительной обработки с использованием сценариев оболочки и т. Д., Чтобы обеспечить максимальную переносимость.

Gnuplot 5.2, уровень исправлений 5 под родной Windows 10 или cygwin.

1 Ответ

0 голосов
/ 07 января 2019

Чтобы пропустить график в среде с множеством графиков, как правило, можно сделать с помощью set multiplot next, однако, пропуская график без данных, я не знаю, есть ли «простой» способ добиться этого. Итак, взгляните на обходной путь ниже. Это неоптимизированный код, но протестированный в gnuplot 5.2.5. Основная идея состоит в том, чтобы поместить данные в фиктивную таблицу и проверить, находится ли время в пределах диапазона сегмента, а также содержит ли некоторые данные, отличные от 0. Вероятно, предстоит еще много работы, чтобы граф выглядел красиво. Просто посмотрите на это как на возможную отправную точку.

### skipping plot having no data
reset session

$DATA << EOD
# Zero values are invalid (no GPS fix) and shall be ignored.
#
# Segment 1) Trip 1 around longitude 50.0:
00:01   49.99990
00:02   49.99994
00:03   50.00006
00:04   50.00008
00:05   0
00:06   0
00:07   0
00:08   50.00004
00:09   50.00002
#
# Segment 2) no data recorded at all
# ...
#
# Segment 3) Trip 2 around longitude -164.0:
00:21   -163.99992
00:22   -163.99998
00:23   -164.00006
00:24   -164.00004
00:25   0
00:26   0
00:27   0
00:28   -164.00002
00:29   -164.00002
#
# Segment 3) only invalid data recorded
00:31   0
00:32   0
00:33   0
00:34   0
00:35   0
00:36   0
00:37   0
00:38   0
00:39   0
#
# Segment 4) Trip 3 around longitude 120.0:
00:41   120.00000
00:42   120.00002
00:43   119.99998
00:44   119.99996
00:45   119.99994
00:46   119.99998
00:47   120.00002
00:48   120.00006
00:49   120.00002
EOD

# data for second sub-plot
y(x) = sin(x)

# General settings
timeformat = "%H:%M"
set xdata time
set timefmt timeformat
set xtics timedate
set xtics format timeformat
set xtics 10*60
set mxtics 10
set ytics format "%.5f"

# Function to skip zero / invalid longitude values:
strip_zero(Y) = ( Y == 0 ? NaN : Y )


# Plot 10-minute slices:
set multiplot layout 2,5 columnsfirst
set margins 8,1,2,1

x_start = 0
x_end = 40
x_step = 10
do for [i = x_start*60:x_end*60:x_step*60] {
    set xrange [i : i + x_step*60]
    ContainsData = 0
    set table $Dummy
        plot $DATA using 1:\
        ((timecolumn(1)>=i) && (timecolumn(1)<=(i + x_step*60)) && ($2!=0) ?\
        ContainsData=1 : 0) with table
    unset table

    if (ContainsData == 0) { set multiplot next }
    else {
        plot [i : i + x_step*60] $DATA using 1:(strip_zero($2)) with lp pt 7 lc rgb "red" notitle
    }
    plot y(x) with lines notitle
}
unset multiplot
### end of code

Что приводит к:

enter image description here

...