Глава 4. Автоматизация спектроскопического эксперимента
Пункты меню «2. Ввод параметров измерения» и «3. Просмотр параметров измерения» достаточно просты для реализации и здесь не рассматриваются. Лишь упомянем, что все параметры, редактируемые пользователем, записываются в словарь params:
params = {'l_start': 400.0, 'l_stop': 700.0, 'l_step': 10.0, 't_meas': 1.0, 'datapath': './DATA/'}
Это позволяет очень легко организовать сохранение параметров при выходе из программы и их загрузку при старте, что экономит время при серийных измерениях с одинаковыми условиями эксперимента. Кроме того, добавление в словарь какого-нибудь нового параметра никак не скажется на файловых операциях:
В данном случае был использован стандартный модуль pickle, предназначенный для записи в файл сериализованных объектов. Заметим, что при этом создаётся бинарный файл, который невозможно просмотреть в текстовом редакторе.
Пункт меню «4. Старт измерения» предполагает проведение следующих операций:
а) выход на начальную длину волны l_start;
б) измерительный цикл с шагом l_step до конечной длины волны l_stop.
Поскольку измерения могут продолжаться достаточно длительное время, было бы удобным сразу отображать текущий результат в виде графика. Именно поэтому в строке 17 мы инициализируем графику в интерактивном режиме. Поскольку границы диапазона по длинам волн определены параметрами измерения, используем метод plt.xlim для установки масштаба по оси абсцисс. Осуществлять измерение и выводить точки на график будет функция meas_point, о которой скажем чуть позже. Строки 23-29 составляют основной измерительный цикл программы, после которого мы выключаем интерактивный режим графика (чтобы графическое окно не оказалось заблокированным). Экспериментальные данные записываются в список data неопределённой длины, который инициализируется в строке 15. Сразу же после измерения данные записываются во временный файл как сериализованный объект. Это избавляет экспериментатора от возможных случайных ошибок на финишной стадии эксперимента. Впоследствии полученные данные можно сохранить в обычный текстовый файл и снабдить необходимыми комментариями.
В программе предусмотрен аварийная остановка позиционирования монохроматора на любой стадии процесса измерения. После отсылки команды goto (строка 8) на уровень Arduino программа переходит к ожиданию выполнения действия (функция wait_mdr, строка 14). Однако это не простое ожидание:
Во время ожидания (бесконечный цикл while True) программа анализирует буфер клавиатуры, используя модуль msvcrt.
Обратите внимание, что модуль msvcrt корректно работает только в окне терминала Windows, для программ под Linux есть иные решения.
Метод kbhit проверяет наличие кода нажатой клавиши в буфере, не останавливая цикл. Таким образом, мы не мешаем программе отслеживать состояние последовательного порта. В случае, если мы нажали на клавиатуре клавишу X, символ «x» отправится в контроллер Arduino (строка 12). Программа контроллера, занимаясь вращением шагового двигателя, попутно анализирует последовательный порт. Если там появляется «x», происходит прерывание работы программы позиционирования и в порт возвращается «X.». Программа на Python принимает этот символ (строка 15) и останавливает измерительную процедуру.
Как было сказано выше, измерение, вывод точки на график и запись нового значения в массив данных осуществляются функцией meas_point. В качестве параметра ей передаётся текущее значение длины волны.
Эта функция не очень эстетична с точки зрения структурного подхода к программированию, поскольку здесь осуществляется взаимодействие с несколькими разнородными устройствами на чтение и запись, а также одновременное использование глобальных переменных и параметров функции. Однако, для проведения тестирования установки это оказалось удобно. В ходе измерительного цикла в первую очередь осуществляется запуск счётчика импульсов и остановка через промежуток времени, установленный параметром t_meas (строки 3-6). Полученное значение res выводится на консоль (в виде числа). В список данных добавляется новое значение с помощью метода append (строка 9).
И, наконец, в строках 10-12 данные выводятся на график. Следует отметить, что, в отличие от примеров главы 2, использовать метод plt.scat-ter оказалось не очень удобно – в нашем эксперименте точек обычно не бывает более 500, и очень часто их менее 100. При этом маркеры, не связанные линией, не дают экспериментатору хорошего восприятия данных. Однако построить в интерактивном режиме график с маркерами точек и линиями, соединяющими точки, тоже очень просто. Достаточно использовать стандартный метод plt.plot с необходимыми значениями параметров. Требуется лишь задавать в качестве одномерных массивов PX и PY весь набор экспериментальных значений, полученных на данном шаге. Поскольку список заполняется построчно, а требуются столбцы абсцисс и ординат, хорошим решением является использование функции zip, которая из исходного списка, состоящего из вложенных списков, вновь формирует списки, состоящие из последовательности элементов с одинаковыми индексами. Символ * при аргументе убирает внешний список, позволяя распаковать исходный набор данных в две переменных. Использование метода plt.pause является обязательным для корректного отображения графика, однако следует помнить, что время паузы «мёртвое», никаких действий программа при этом не совершает, и этот промежуток времени желательно сделать как можно более коротким.
Если вы заметили неточность, ошибку или хотите поделиться своими мыслями по поводу статьи - мы рады обратной связи. Давайте вместе сделаем ресурс лучше!