Как стать автором
Обновить

Студенты, лабы и gnuplot: обработка данных

Время на прочтение8 мин
Количество просмотров9.5K

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


Установка gnuplot

Gnuplot – высокоуровневый язык команд и сценариев, предназначенный для построения графиков математических функций и работы с данными, активно развивающийся с 1986 года. Исходный код gnuplot защищён авторским правом, но распространяется как свободное программное обеспечение и способен работать на  Linux, OS/2, MS Windows, OSX, VMS и многих других платформах. Для установки gnuplot на компьютер с MS Windows наиболее удачным решением будет обратиться к официальному сайту gnuplot.info,  перейти по ссылке «Download» и загрузить актуальную версию с ресурса sourceforge.net. Размер скачиваемого файла  – около 30 Мб, после установки пакет занимает примерно 100 Мб дискового пространства. 

Установщик задаст несколько простых вопросов о конфигурации (на английском языке), одно из окошек будет называться «Select Additional Tasks», в нем я рекомендую выбрать тип терминала wxt, а также поставить галочку в последнем пункте «Add application directory to your PATH environment variable». После установки в меню запуска программ появятся два новых пункта, кажется они называются «gnuplot» и «gnuplot console version». Если выбрать второй вариант, появится черное окно с командной строкой, как показано на рисунке:

Если ввести командуpwd, вы увидите директорию, в которой запускается gnuplot. Команда
plot sin(x)откроет графический терминал wxt и нарисует в нем график функции \sin(x).

Если запускать просто gnuplot (не консоль), окно для ввода команд будет белое с черным текстом, при этом в нем будет отображаться верхнее меню с многочисленными командами. В gnuplot есть команда help для быстрого получения справки по любой из команд. Для облегчения работы с gnuplot пользователям MS Windows настоятельно рекомендую обзавестись нормальным текстовым редактором (я не очень в курсе текущей ситуации с Notepad).

Эксперимент

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

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

Теоретическая зависимость измеряемого напряжения U от угла поворота поляризатора \thetaописывается законом Малюса:

U(\theta) = U_0\cos^2(\theta-\theta_0),

где U_0 – максимальное значение напряжения, \theta_0– угол между плоскостью поляризации света и оптической осью поляризатора.

Моделирование 

Применим gnuplot для моделирования возможных результатов эксперимента, в котором измеряется зависимость U от угла поворота \theta. Стоит отметить, что в реальных экспериментах моделирование изучаемого явления широко используется для создания и тестирования средств анализа результатов измерений. Отличие наблюдаемых величин от модельных данных заставляет исследователей проверять и совершенствовать модель, добавляя в нее уже известные науке эффекты. Ситуация, в которой результаты эксперимента невозможно описать известными явлениями, называется открытием. Итак, создадим текстовый файл model.gpl со сценарием из gnuplot-команд и комментариев к ним: 

reset # сбрасываем все ранее определенные переменные среды gnuplot
set angles degrees    # используем градусы как единицу измерения углов
set xrange [0:350]    # диапазон изменения угла поворота поляризатора
set samples 36        # число точек для вычисления значений функции
set format x "%5.1f"  # формат вывода значения угла  
set format y "%5.3f"  # формат вывода величины напряжения
# Применим преобразование Бокса-Мюллера для моделирования 'ошибки' 
# измерения угла, которая описывается нормальным распределением 
# с нулевым средним и дисперсией D. Воспользуемся имеющимся в
# gnuplot генератором псевдо-случайных чисел, функцией rand(x):
err(D) = D * cos(360*rand(0))*sqrt(-2*log(rand(0))) 
# Создадим функцию для описания закона Малюса:
U(x) = Uo * cos(x + err(D) - To)**2 + B 
Uo = 0.65  # параметр Uo
To = 71.   # параметр θo
B  = 0.02  # напряжение на фотодетекторе при выключенном источнике света 
D  = 1.0   # ошибка считывания значения угла со шкалы на оправе
set table "exp.dat" # имя текстового файла для вывода результатов 
plot U(x)           # записываем результаты в файл
unset table         # закрываем файл

В окне gnuplot набираем командуload 'model.gpl'.Подразумевается, что созданный нами файл находится в рабочей директории, в противном случае директорию можно сменить, введя команду cd 'your_path'. После выполнения скрипта мы получим текстовый файл cрезультатами моделированияexp.dat, который выглядит примерно так:

# Curve 0 of 1, 36 points
# Curve title: "U(x)"
# x y type
  0.0 0.089  i
 10.0 0.176  i
 20.0 0.283  i
 30.0 0.395  i
 40.0 0.505  i
 50.0 0.595  i
 60.0 0.643  i
 ...

Анализ данных

Начнем обработку данных с построения графика данных моделирования (или измерений). Также используем метод наименьших квадратов для сравнения полученных результатов с теорией. Редуцированное значение взвешенного параметра хи-квадрат определяется так:

\chi_{\nu}^2 = \frac{\chi^2}{\nu} = \frac{1}{\nu}\sum_i \frac{(Y_i - f(X_i))^2}{\sigma_i^2}.
  • \nu называется числом степеней свободы алгоритма поиска минимального значения \chi^2и определяется как число измерений (точек на графике) минус количество свободных параметров функции f(x),

  • X_i– точки на оси x, в которых проведены измерения,

  • Y_i – результат измерения в точке X_i,

  • f(X_i)– значение теоретической функции в точке X_i,

  • \sigma_i – среднеквадратическое отклонение измеренного значения величины Y_iот ее среднего значения \langle Y_i \rangle.

В gnuplot отношение \chi^2/\nuиз последней формулы обозначается как WSSR / NDF, что является аббревиатурой от фраз «Weighted Sum of Squared Residuals» и «Number of Degrees of Freedom».

Рассматриваемый здесь пример лабораторной работы является частным случаем обширного класса задач, в которых есть набор данных измерений/моделирования и теоретическая функция, которая «должна» описывать изучаемое явление. Для проверки соответствия между теорией и экспериментом мы будем варьировать свободные параметры функции так, чтобы минимизировать величину \chi^2. Для этого в gnuplot есть команда fit, изпользующая алгоритм Левенберга — Марквардта. На русский язык фраза «fit function to data» переводится как «подогнать функцию к данным».

Создадим текстовый файлlook.gpl со сценарием для gnuplot.

reset
set angles degrees
f(x) = Uo * cos(x-To)**2 + B            # определение теоретической функции
Uo  = 0.6                               # параметр Uo
To = 10                                 # параметр To
B  = 0.05                               # параметр B
set fit nolog         # отмена опции записи логов процесса подгонки в файл
# Запускаем алгоритм поиска минимума хи-квадрат, используя 1 колонку файла
# "exp.dat" в качестве X[i], а вторую - в качестве Y[i]. При поиске минимума
# алгоритм варьирует значения свободных параметров Uo, B, To
fit f(x) "exp.dat" using 1:2  via Uo, To, B
# Среднее квадратичное отклонение эксперимента и теории в милливольтах
L = sprintf("Закон Малюса: {/Symbol s} = %.2f [мВ]", 1000*FIT_STDFIT) 
# Найденное значение угла поворота оси и оценка его точности
T = sprintf("Поворот оси поляроида {/Symbol q_0} = %.2f° ± %.2f°", To, To_err)
set title T # Название для получившегося графика
set grid    # Указание рисовать сетку на графике
set key box width -14 # прямоугольник для отображения подписей к графикам
set xlabel 'угол поворота поляризатора {/Symbol q} [ ° ]'
set ylabel 'напряжение на фотоприёмнике U [ В ]'
set yrange [0:0.8] # диапазон графика по вертикальной оси
set terminal png size 800, 600 # выбираем тип терминала - png файл
set out 'look.png' # имя файла для записи графика
# Рисуем функцию и точки из файла:
plot f(x) with line title L ls 3 lw 2, \
"exp.dat" u 1:2 title 'эксперимент' with points ls 7 ps 1.5 
set out # закрываем файл

Символ «\» используется в сценариях для переноса длинных строк и должень быть последним символом в своей строке. В окне gnuplot вводим команду load 'look.gpl', в результате выполнения которой у нас появится файл look.png с построенными графиками данных и теоретической функции:

Итак, мы видим, что «на глазок» данные хорошо совпадают с теорией. Нам даже удалось правильно «измерить» угол \theta_0с точностью 0.2 градуса. Однако, мы имеем среднеквадратическое отклонение теории от моделирования \sigma \simeq 9милливольт. Что бы это могло означать? Много это или мало?

Если посмотреть на использование команды fit (строка №11 в файле look.gpl), можно заметить, что мы не передаём процедуре подгонки никаких данных об ошибках измерений, т. е. алгоритм ничего «не знает» о величинах\sigma_i из последней формулы. Что же он (алгоритм) делает в таком случае? А вот что: все \sigma_i считаются равными безразмерной единице и мы получаем невзвешенное значение редуцированного параметра хи-квадрат, квадратный корень из которого является размерной величиной, описывающей среднеквадратическое отклонение функции от экспериментальных точек – те самые 8.88 милливольт, приведённые в заголовке графика.

Если в процессе измерений текущее наблюдаемое значение напряжения в каждой точке ведет себя достаточно стабильно, можно предположить, что отличие теории и эксперимента может быть связано с неточностью отсчета угла по шкале оправы с вращающимся поляризатором. Чтобы преобразовать ошибки отсчета угла в эквивалентные ошибки измерения напряжения, продифференцируем функцию U(\theta)и назовем получившуюся функцию V(\theta):

V(\theta) \equiv \frac{\partial U(\theta)}{\partial \theta} = U_0 \sin(2(\theta_0-\theta)) .

В нашем моделировании (см. файлmodel.gplв начале этого текста) мы «учли» погрешность измерения угла, добавив его к закону Малюса как случайную величину с нормальным распределением и среднеквадратическим разбросом в 1 градус. Чтобы учесть погрешности измерений, создадим усовершенствованный скрипт для обработки данных. Заодно, нарисуем графики в полярных координатах (удобных для визуализации поляризационных явлений), а также сохраним картинку в формате pdf.

reset
set angles degrees
f(x) = Uo * cos(x-To)**2 + B      # определение теоретической функции
v(x) = Uo * sin(2*(To-x))*pi/180  # производная f(x)
Uo  = 0.6                         # параметр Uo
To = 10                           # параметр To
B  = 0.05                         # параметр B
dT = 1.0                          # ошибка измерения угла
set fit nolog
#  Запускаем алгоритм поиска минимума (не-взвешенный хи-квадрат)
fit f(x) "exp.dat" using 1:2             via Uo, To, B
#  Запускаем алгоритм поиска минимума (взвешенный хи-квадрат)
fit f(x) "exp.dat" using 1:2:(dT*v($1)) via Uo, To, B
L = sprintf("Теория: {/Symbol c^2}/NDF = %.1f/%2d\n \
Вероятность: %.2f \%", FIT_WSSR, FIT_NDF, 100*FIT_P) 
T = sprintf("Поворот оси поляроида {/Symbol q_0} = %.2f° ± %.2f°", To, To_err)
set title T # Название для получившегося графика
set key box left opaque  width -12 spacing 2
unset border # не рисовать рамку
unset xtics  # не показывать ось x
unset ytics  # не показывать ось y
set polar    # рисуем графики в полярных координатах
set grid polar linetype 2 lc rgb 'black' lw 0.25 dashtype 2
set rtics 0.1 format '%.1f'
unset raxis
Umax = 0.76  # максимальное значение напряжения
set rrange [0:Umax]
set rlabel 'U_{ФД} [В]'
set trange[0:360]
set for [i=0:330:30] label at first Umax*cos(i), \
first Umax*sin(i) center sprintf('%d°', i)
set terminal pdf background rgb '0xFFFFF0' size 5, 5 # тип терминала - pdf файл
set out 'closelook.pdf' # имя файла для записи графика
plot f(t) with line title L ls 3 lw 2, \
"exp.dat" u 1:2:(dT*v($1)) title 'эксперимент' with err ls 7 ps 0.5 
set out # закрываем файл

Следующее изображение - скриншот получившегося файла closelook.pdf.

В результате применения алгоритма подгонки мы получили редуцированное значение взвешенного параметра хи-квадрат \chi^2/\text{NDF}=33.9/33. Используя распределение хи-квадрат с соответствующим числом степеней свободы gnuplot находит значение вероятности (p-value) получения наблюдаемого результата в предположении, что исходная теоретическая гипотеза верна. В нашем случае эта вероятность довольно высока - 42%.

Заключение

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

Разумеется, существуют и иные средства, позволяющие решать обсуждавшиеся здесь задачи. Например, можно обратиться к статье «Студенты, лабы и python: обработка данных».

Теги:
Хабы:
+27
Комментарии10

Публикации

Истории

Ближайшие события

Weekend Offer в AliExpress
Дата20 – 21 апреля
Время10:00 – 20:00
Место
Онлайн
Конференция «Я.Железо»
Дата18 мая
Время14:00 – 23:59
Место
МоскваОнлайн