ThesisPDF Available

Abstract

In the course of the dissertation master's work, the driver for the Encephalan electroencephalograph was developed, the driver was integrated into the OpenViBE software package. Thus, an intelligent information system for developing, researching and using computer brain interfaces was obtained. The approbation of the obtained system was carried out using the developed metric for assessing the interrelationships of brain regions. The analysis of the obtained data. Data analysis showed the possibility of using the metric to assess a person’s cognitive potential.
Министерство образования и науки Российской Федерации
Федеральное государственное автономное образовательное учреждение
высшего образования
«Уральский федеральный университет имени первого Президента России
Б.Н.Ельцина»
Институт радиоэлектроники и информационных технологий-РТФ
Департамент радиоэлектроники и связи
ДОПУСТИТЬ К ЗАЩИТЕ |ПЕРЕД ГЭК
Руководитель ОП
________ Кубланов В. С.
(подпись) (Ф.И.О.)
«______» _______________2019 г.
МАГИСТЕРСКАЯ ДИССЕРТАЦИЯ
ИНТЕЛЛЕКТУАЛЬНАЯ ИНФОРМАЦИОННАЯ СИСТЕМА ДЛЯ
ИССЛЕДОВАНИЯ ИНТЕРФЕЙСА МОЗГ-КОМПЬЮТЕР НА БАЗЕ
OpenViBE
Научный руководитель:
канд. техн. наук, доцент Сысков А.М. ________
Нормоконтролер:
Кубланов Е. В.
(подпись)
________
Студент группы РИМ-271207
Минин А. В.
(подпись)
________
(подпись)
Екатеринбург, 2019
РЕФЕРАТ
Пояснительная записка 78 страниц содержит 27 рисунков, 27
источников, 2 таблицы, 5 приложений, 4 формулы, состоит из 5 глав.
ЭЛЕКТРОЭНЦЕФАЛОГРФАИЯ, ИНТЕРФЕЙС МОЗГ-КОМПЬЮТЕР,
КОГНИТИВНЫЙ ПОТЕНЦИАЛ ЧЕЛОВЕКА.
Цель работы разработать драйвер для интеграции проприетарного
программного обеспечения энцефалографа с системой OpenViBE, построить
интегральную метрику для оценки степени связности областей головного
мозга, провести исследование данной метрики.
В процессе работы проведен аналитический обзор темы, разработан
драйвер для электроэнцефалографа «Энцефалан» в комплексе OpenViBE.
Разработанный драйвер интегрирован в комплекс OpenViBE. Построена
интегральная метрика оценки степени связности областей мозга и проведены
исследования когнитивного потенциала с использованием данной метрики.
Результаты показали, что с помощью разработанной метрики можно
установить увеличение степени вовлеченности областей мозга в
деятельность, а значит разработанную метрику можно использовать для
оценки когнитивного потенциала человека.
Дальнейшее развитие темы может быть направлено на апробацию
эффективности метрики на большем количестве испытуемых.
Изм
..
Лист № докум. Подпис
ь
Дата
Лист
2
090402 000000 804 ПЗ
Выполнил Минин А.В.
Провер. Сысков А.М.
Н. Контр. Кубланов
Е.В.
Утверд. Кубланов В.С.
Интеллектуальная
информационная система для
исследования интерфейса
мозг-компьютер на базе
OpenViBE
Лит. Листов
78
ФГАО ВО УРФУ ИРИТ-
РТФ РИМ-271207
ОГЛАВЛЕНИЕ
РЕФЕРАТ..................................................................................................................2
СПИСОК СОКРАЩЕНИЙ.....................................................................................5
СПИСОК ОБОЗНАЧЕНИЙ....................................................................................6
ВВЕДЕНИЕ..............................................................................................................7
1 АНАЛИТИЧЕСКИЙ ОБЗОР.............................................................................10
1.1 Общая структура интерфейсов мозг-компьютер..........................................10
1.2 Программные комплексы для исследования и разработки интерфейсов
мозг-компьютер.....................................................................................................14
1.3 Электроэнцефалограф-регистратор «Энцефалан-ЭЭГР-19/26»
модификация «Мини»...........................................................................................17
2 РАЗРАБОТКА ДРАЙВЕРА ДЛЯ ЭНЦЕФАЛОГРАФА «ЭНЦЕФАЛАН»......24
2.1 Описание протоколов обмена данными........................................................24
2.2 Драйвер в инфраструктуре комплекса OpenViBE........................................26
2.3 Интеграция драйвера с OpenViBE.................................................................28
2.4 Интерфейс разработанного драйвера............................................................31
3 ИНТЕЛЛЕКТУАЛЬНАЯ СИСТЕМА ДЛЯ ИССЛЕДОВАНИЯ
ИНТЕРФЕЙСА МОЗГ-КОМПЬЮТЕР................................................................34
4 ИССЛЕДОВАНИЯ КОГНИТИВНОГО ПОТЕНЦИАЛА...............................37
4.1 Интегральная метрика оценки взаимосвязи областей мозга.......................37
4.2 Сбор данных и программа эксперимента......................................................39
4.3 Анализ данных.................................................................................................39
5 ЗАЩИТА ОБЪЕКТОВ ИНТЕЛЛЕКТУАЛЬНОЙ СОБСТВЕННОСТИ........48
ОБСУЖДЕНИЕ РЕЗУЛЬТАТОВ..........................................................................51
ЗАКЛЮЧЕНИЕ......................................................................................................53
3
СПИСОК ЛИТЕРАТУРЫ......................................................................................54
ПРИЛОЖЕНИЕ А.................................................................................................57
ПРИЛОЖЕНИЕ Б..................................................................................................58
ПРИЛОЖЕНИЕ В..................................................................................................61
ПРИЛОЖЕНИЕ Г..................................................................................................70
ПРИЛОЖЕНИЕ Д..................................................................................................72
4
СПИСОК СОКРАЩЕНИЙ
ЭЭГ – электроэнцефалография
BCI – brain computer interface
IDE – интегрированная среда разработки
CSV – comma-separated values
GDF – general data format
EDF – European data format
БД – база данных
ПО – программное обеспечение
ПМО – программно-методическое обеспечение
SDK – software development kit
API – application programming interface
5
СПИСОК ОБОЗНАЧЕНИЙ
Cw – взвешенный коэффициент кластеризации
6
ВВЕДЕНИЕ
Системы интерфейс-мозг компьютер находят свое применение во
многих областях включая медицину, робототехнику, мультимедиа и другие.
При этом наиболее часто используемым сигналом, характеризующим
деятельность головного мозга, является электроэнцефалографический сигнал
[1].
Разработка интерфейсов мозг-компьютер включает в себя несколько
стадий. Эти стадии по своему содержанию во много схожи для различных
реализаций интерфейсов мозг-компьютер: исследовательская стадия;
испытания; продуктовый режим эксплуатации.
На исследовательской стадии решаются следующие типовые задачи
обработки сигналов ЭЭГ: получение сигнала, фильтрация, удаление
артефактов, извлечение признаков, классификация, формирование
управляющих сигналов.
Ввиду типизации набора этапов и задач в настоящее время существуют
различные программные комплексы для исследования и проектирования
интерфейсов мозг-компьютер. Наибольший интерес с точки зрения научных
исследований представляют системы с открытым исходным кодом. На
сегодняшний день наиболее известные проекты с открытым исходным кодом
– американская BCI2000 и французская OpenViBE.
Несмотря на все плюсы использования открытого программного
обеспечения для проектирования интерфейсов мозг-компьютер, существует
ряд типовых проблем, с которыми сталкиваются исследователи. Одна из
таких проблем необходимость интеграции с проприетарным программным
обеспечением производителя энцефалографа для получения сигнала в
режиме реального времени. Особенно остро эта проблема стоит при
использовании энцефалографов российского производства.
В настоящем исследовании используется энцефалограф-регистратор
«Энцефалан-ЭЭГР-19/26» модификация «Мини». Данный энцефалограф
7
является универсальным инструментом для большинства задач, связанных с
контролем и диагностикой состояния головного мозга, при различных
нейрофизиологических исследованиях и в смежных областях медицины [23].
Проприетарное программное обеспечение энцефалографа имеет расширение
для интеграции с внешними системами при передаче сигналов ЭЭГ в режиме
реального времени. Однако, например, проект OpenViBE не поддерживает
интеграцию с проприетарным программным обеспечением энцефалана.
Исследовательская стадия проектирования интерфейса мозг-компьютер
базируется на какой-либо гипотезе о свойствах сигналов ЭЭГ для различных
функциональных состояний человека, которые определяются областью и
задачами применения интерфейса мозг-компьютер.
В настоящей работе рассмотрена область определения когнитивного
потенциала человека с применением методов анализа ЭЭГ, при этом
необходимо решить задачу оценки связанности электрической активности
различных областей головного мозга. Данная задача решается с
использованием методов когерентного анализа, результатом, как правило,
является карта связей областей головного мозга.
Получаемые карты удобно использовать при анализе изменений
функционального состояния человека уже после проведения эксперимента.
Для оценки изменения функционального состояния в режиме реального
времени и взаимодействия с пользователем интерфейса мозг-компьютер
использование такой карты является проблемным.
В работе рассматривается построение интегральной меры, которая
строится на базе графа связей областей головного мозга. Данная мера может
быть использована для отображения динамики изменения функционального
состояния человека в виде графиков и определения нахождения
функционального состояния человека в определенных целевых пределах при
оценке изменений когнитивного потенциала человека.
Таким образом, цель настоящей работы: осуществить вклад в проект
OpenViBE для интеграции проприетарного программного обеспечения
8
энцефалографа с системой, построить интегральную метрику для оценки
степени связности областей головного мозга, провести исследование данной
метрики.
Задачи:
Провести обзор систем для разработки и исследования интерфейсов
мозг-компьютер.
Разработать драйвер для энцефалографа «Энцефалан» для
интеграции с OpenViBE.
Разработать интегральную метрику оценки взаимосвязи областей
мозга.
Провести апробацию полученной системы при исследованиях
когнитивного потенциала с использованием интегральной метрики
оценки взаимосвязи областей мозга.
9
1 АНАЛИТИЧЕСКИЙ ОБЗОР
В большинстве случаев для интерфейсов мозг-компьютер в качестве
входного сигнала используется сигнал ЭЭГ [1]. С помощью
электроэнцефалографии регистрируют электрофизиологическую активность
головного мозга. Наиболее распространенным является неинвазивный метод,
то есть электроды регистрируют разность потенциалов на поверхности кожи
головы. Флуктуации напряжения являются результатом ионных токов в
нейронах головного мозга.
1.1 Общая структура интерфейсов мозг-компьютер
Наиболее общая и полная структура систем, которые реализуют
интерфейсы мозг-компьютер, представлена последовательным рядом блоков
обработки сигналов (рисунок 1.1).
Рисунок 1.1 – общая схема реализации интерфейсов мозг-компьютер [2]
В соответствии с приведенной схемой вся система состоит из пяти
основных блоков:
получение не обработанных данных ЭЭГ;
предварительная обработка полученных данных: фильтрация,
удаление не желательных артефактов;
извлечение из сигнала значимых данных и уменьшение
размерности;
классификация полученных данных;
10
формирование управляющих сигналов.
Наиболее распространенным решением задачи сбора данных является
использование устройств, позволяющих неинвазивно регистрировать
изменение потенциалов с поверхности кожи головы, то есть использование
различных электроэнцефалографов, от профессиональных систем
медицинского назначения [3], до относительно дешевых и легко доступных
[4][5]. Однако для ряда исследований решением задач сбора данных не
занимаются в принципе, а берут необходимые сигналы из общедоступных баз
медицинских сигналов для дальнейшей обработки [6].
Фильтрацию сигналов, как показано в [2] можно проводить с помощью
простых аналоговых или цифровых фильтров нижних и верхних частот. В
случае, когда интересующая информация для конкретной задачи находится на
частотах ниже определенной, все шумы с более высокими частотами могут
быть удалены с использованием фильтра нижних частот. Конкретные полосы
частот также могут быть выбраны с использованием полосовых фильтров.
Шумы от электрической сети с фиксированной частотой 50 Гц или 60 Гц
зачастую удаляются режекторным фильтром.
Так же для удаления нежелательных артефактов используют ряд
методов, которые позволяют улучшить качество сигнала. Выбор подходящего
метода улучшения зависит от нескольких факторов, таких как технология
записи, количество электродов и нейромеханизм формирования сигнала.
Описание методов улучшения и частота их использования (рисунок 1.2) в
исследованиях приводится в работе [2]:
пространственные фильтры (common average referencing (CAR) и
surface laplacian (SL));
метод главных компонент – principal component analysis (PCA);
независимый компонентный анализ – independent component
analysis (ICA);
общие пространственные шаблоны сommon spatial patterns
(CSP);
11
общая пространственная декомпозиция – сommon spatial subspace
decomposition (CSSD);
нормализация частоты – frequency normalization (Freq-Norm).
Рисунок 1.2 – частота применения методов улучшения сигнала [2]
В системах, реализующих интерфейс мозг-компьютер, часто остро
стоит проблема большой размерности данных, поскольку выбор признаков из
многих каналов и частотных диапазонов зачастую велик. При разработке
системы необходимо выбрать лишь небольшое количество характерных
признаков, данные признаки должны быть наиболее значимые из массива
данных, особенно при малой обучающей выборке. Наиболее
распространённые методы извлечения признаков и уменьшения размерности:
Анализ основных компонент или principal component analysis
(PCA). Основная цель использования PCA - выбрать
минимальное количество основных компонентов m-мерного
пространства признаков, таким образом, чтобы субъекты
максимально разделялись в признаковом пространстве компонент.
Так можно значительно уменьшить размерность с минимальными
потерями данных.
Так же встречаются такие методы уменьшения размерности как
генетический алгоритм (genetic algorithm (GA)) и квантование
векторов при обучении (learning vector quantization (LVQ)).
Классификации данных и сравнению различных методов
классификации посвящено много исследований [7][8]. Наиболее часто
12
применяемые классификаторы, которые описываются в приведенных
работах:
метод опорных векторов (support vector machine (SVM));
линейный дискриминантный анализ (linear discriminant analysis
(LDA));
разновидности искусственных нейронных сетей (artificial neural
network (ANN));
дерево принятия решений (decision tree (DT));
разновидности Байесовского классификатора (Bayesian Classifier
(BC)).
Формирование сигналов является крайне специфической задачей в
каждом исследовании. На специфику формирования сигнала влияет внешнее
устройство и интерфейсы взаимодействия. Так же не маловажную роль могут
сыграть системы помощи в управлении [9], то есть внешние устройства
оснащены дополнительными датчиками, позволяющими получать
дополнительную информацию об окружающих устройство объектах, что
позволяет формировать управляющие сигналы не только на основе сигналов
от системы мозг-компьютер, но и других вспомогательных систем. В таких
случаях система интерфейса мозг-компьютер является системой
целеполагания, а не прямого управления внешним устройством.
Системы BCI (brain computer interface) можно разделить на семь
основных категорий, в зависимости от нейромеханизмов формирования
сигнала, которые используются для генерации управляющих сигналов [2]:
сенсомоторная активность;
медленные корковые потенциалы – частоты 1-2 Гц;
связанные с событиями мозговые потенциалы (ERP P300);
визуальные вызванные потенциалы VEP и SSVEP;
ответ на умственные задачи предполагается, что различные
умственные задачи приводят к различным специфическим для
конкретной задачи распределению частотных характеристик ЭЭГ
над скальпом;
13
активность нервных клеток активность нейронов в моторной
коре увеличивается при движении в предпочтительном
направлении для нейронов. Когда движение отличается от
предпочтительного направления нейронов, активность снижается;
множественные нейромеханизмы (комбинация нескольких
категорий, представленных выше).
Наиболее распространенные методы формирования сигналов основаны
на сенсомоторной активности и вызванных потенциалах P300.
1.2 Программные комплексы для исследования и разработки интерфейсов
мозг-компьютер
Существует ряд программных комплексов, которые позволяют
реализовывать интерфейсы мозг-компьютер в различных парадигмах.
Подобные комплексы должны решать ряд описанных выше задач, то есть
сбор, обработку данных и формирование управляющих сигналов или
обратной связи.
Два наиболее известных программных комплекса это система BCI2000
[24] и OpenVibe [25]. Оба программных комплекса являются универсальными
программными системами для исследования, проектирования, тестирования
и использования интерфейсов мозг-компьютер в реальном времени,
позиционируются как кроссплатформенные системы, имеют открытый
исходный код и бесплатны для некоммерческих исследований. Как в том, так
и в другом решении используются только собственные программные
компоненты, то есть оба комплекса не зависимы от стороннего программного
обеспечения, однако существует возможность выполнять сценарии,
реализованные в стороннем программном обеспечении, BCI2000 способен
выполнять сценарии Matlab в режиме реального времени, а OpenVibe
поддерживает взаимодействие со сценариями реализованными в Matlab или
на Python, а также взаимодействовать (принимать и отправлять) со стимулами
с помощью инструмента Lua Stimulator (скрипты реализованные на языке
Lua). Проекты реализованы на языке C++ и для сборки и компиляции
14
используют доступные бесплатно компиляторы, OpenVibe так же имеет
удобные инструменты для сборки проекта под окружение IDE VisualStudio.
Комплекс BCI2000 увидел свет в 2001 году, первая версия OpenVibe
вышла в 2007 году, оба проекта существуют достаточно долгое время, однако
OpenVibe имеет намного более подробную документацию для пользователей
системы по проектированию интерфейсов «мозг-компьютер» [20], а также
более полную документацию для разработчиков [21], что является большим
плюсом для реализации дополнительного функционала системы. Еще одним
большим плюсом OpenVibe является наличие графического дизайнера
сценариев обработки данных, в котором каждый элемент системы,
выполняющий одну из функций: сбор, фильтрация, обработка,
классификация или визуализация сигналов мозга, представлен
прямоугольником в цепочке обработки (рисунок 1.3).
В качестве входных и выходных данных обе системы могут
использовать как потоки данных, передаваемых в реальном времени между
устройствами, так и записанные данные, в распространенных форматах CSV
(Comma-Separated Values), GDF (General Data Format), EDF (European Data
Format) и другие. Список поддерживаемых ЭЭГ усилителей достаточно
большой в обоих комплексах.
Проект OpenVibe остается активно развивающимся и поддерживаемым
в настоящее время, в то время как последние изменения в проекте BCI2000
были внесены в 2013 году.
15
Рисунок 1.3 – графический интерфейс дизайнера OpenVibe
Программный комплекс OpenVibe имеет ряд преимуществ перед
комплексом BCI2000:
более подробные руководство пользователя и документация для
разработчиков;
быстрая сборка проекта под более современные средства
разработки (VisualStudio 2013);
наличие графического пользовательского интерфейса для
создания сценариев обработки сигнала;
OpenVibe является развивающимся проектом и поэтому можно
получить поддержку со стороны сообщества, развивающего
проект.
16
1.3 Электроэнцефалограф-регистратор «Энцефалан-ЭЭГР-19/26»
модификация «Мини»
Электроэнцефалограф-регистратор «Энцефалан-ЭЭГР-19/26»,
модификация «Мини» производится научно-производственной-
конструкторской фирмой «Медиком МТД» г. Таганрог [19].
Данный 8-канальный электроэнцефалограф способен работать в
телеметрическом или автономном (Холтер-ЭЭГ) режиме, позволяет
проводить кратковременные и длительные ЭЭГ-исследования для
большинства задач, связанных с контролем и диагностикой состояния
головного мозга, при различных нейрофизиологических исследованиях и в
смежных областях медицины.
Основные функциональные возможности:
модификации электроэнцефалографа: 8 электроэнцефалографических
отведений; дополнительно до 4 полиграфических каналов (ЭКГ, КГР,
ЭМГ, ЭОГ, ФПГ, температура);
непрерывный контроль и регистрация подэлектродных сопротивлений
и потенциалов;
озможность обмена информацией с внешними системами в режиме
реального времени.
На рисунке 1.4 приведена структурная схема диагностического
комплекса «Энцефалан-ЭЭГР-19/26» «мини». В данной комплектации
диагностический комплекс состоит из интерфейсного блока ИБ-4, который
связан с персональным компьютером оператора (ПК) и автономным блоком
пациента АБП-10. Интерфейсный блок ИБ-4 осуществляет взаимодействие
АБП-10 и ПК через интерфейсы USB и Bluetooth.
17
Рисунок 1.4 - структурная схема диагностического комплекса Энцефалан
АБП-10 работает в телеметрическом режиме, и позволяет осуществлять
непрерывную передачу данных, регистрируемых с помощью электродной
системы ЭС-ЭЭГ-8-3, технические характеристики блока АБП-10 приведены
в Приложении А. К блоку ИБ-4 через интерфейс Bluetooth. Блок ИБ-4 связан
с компьютером по USB. Блок ПОЛИ-4 является опциональным в системе и
позволяет регистрировать один или несколько дополнительных сигналов:
ЭКГ, ФПГ, КГР. Основные блоки электроэнцефалографа представлены на
рисунке 1.5.
Рисунок 1.5 – блоки диагностического комплекса: ИБ-4, АБП-10 и ПОЛИ-4
В диагностическом комплексе «Энцефалан-ЭЭГР-19/26» «мини»
регистрация ЭЭГ осуществляется с помощью системы ЭС-ЭЭГ8-3 (рисунок
1.6). Данная электродная система обеспечивает регистрацию 8 отведений
ЭЭГ. Электродная система имеет 8 скальповых, 2 референтных и 1
нейтральный ЭЭГ-электрод.
18
Рисунок 1.6 – электродная система ЭС-ЭЭГ-8-3
Электроды системы фиксируются в люверсах эластичных шлемов.
Проводники электродов собраны в общий кабель и имеют групповой разъём
для соединения с блоком АБП-10. При подключении электродной системы к
блоку АБП-10 остаётся доступен 1 полиграфический канал блока для
датчиков с разъемом микро-8.
Регистрация ЭЭГ может осуществляться как в телеметрическом, так и в
автономном режиме (запись на встроенную карту памяти блока пациента -
ЭЭГ-холтер). В обоих случаях запись передается на компьютер с
установленным программным обеспечением. Ниже приведены основные
функциональные возможности программного обеспечения [22]:
Общие настройки:
Графический пользовательский интерфейс (Ribbon), аналогичный
пользовательскому интерфейсу MS Office (рисунок 1.7).
Справочник конфигураций съёма сигнала и монтажных схем, а также
редактор монтажных схем и настройка референтов. В качестве
референта может быть выбрано любое отведение ЭЭГ, возможна
установка. Вид используемой монтажной схемы графически
представляется на инструментальной панели (рисунок 1.8).
Использование БД «Картотека» для хранения учётных данных врачей,
пациентов и проведённых исследований. БД позволяет
структурировано хранить базу исследований, осуществлять в этой базе
поиск исследований по любым признакам, выполнять экспорт и импорт
19
исследований для переноса их между рабочими станциями. Возможна
работа «Картотеки» в сети на выделенном сервере.
Рисунок 1.7 – графический пользовательский интерфейс ПО «Энцефалан»
Рисунок 1.8 – выбор схемы отведений в ПО «Энцефалан»
Регистрация ЭЭГ:
20
ПО обеспечивает контроль подэлектродных импедансов и
межэлектродных потенциалов как во время установки электродов, так и
в процессе реального съёма и при обработке записанных данных
(рисунок 1.9).
Ручное и автоматическое управление сценарием записи. Возможность
создания новых сценариев, содержащих различные виды стимуляции,
аппаратные и не аппаратные пробы.
Установка типовых и настраиваемых пользователем маркеров в
процессе съема от внешнего генератора сигнала.
Рисунок 1.9 – контроль подэлектродных импедансов
Количественный анализ:
Количественный анализ: подавление артефактов от ЭМГ, ЭКГ, ЭОГ.
Измерение размаха амплитуд на выделенном фрагменте ЭЭГ.
Временная развёртка амплитудных карт, позволяющая выявить
истинную латерализацию патологической активности ЭЭГ.
21
Картирование: трехмерное топическое отображение спектральных
характеристик ЭЭГ позволяет увидеть фокус патологической
активности в процессе записи ЭЭГ.
Спектральный анализ топического вида позволяет уточнить
локализацию очага патологической активности и получить его
количественные характеристики.
Кросскорреляционный анализ ЭЭГ позволяет количественно оценить
степень сходства процессов во времени в различных областях мозга
относительно выделенной зоны.
Когерентный анализ позволяет оценить степень сходства процессов по
частоте во всех зонах мозга относительно выделенной зоны.
Псевдотрёхмерное представление динамики спектров.
Автоматический поиск эпилептиформной активности и
нестационарных ЭЭГ фрагментов.
Автоматической формирование отчётов, в том числе только по
фрагментам без артефактов, с учётом заданных пользователем
параметров.
Подробно рассмотрев функциональные возможности ПМО
«Энцефалан» можно выделить ряд достоинств:
Большое количество методов выявления различных патологий;
Использование проверенных методов обработки данных;
Формирование отчетов по обработанным данным.
Однако на ряду с плюсами ПМО «Энцефалан» существует и ряд
ограничений в исследовательских задачах:
Отсутствует возможность обрабатывать сигналы в режиме реального
времени;
Нет возможности гибкой настройки методов обработки сигналов и
построения собственных цепочек обработки;
Нет возможности передавать результаты обработки данных для
дальнейшей работы с ними.
22
Таким образом можно сделать заключение, что программное
обеспечение «Энцефалан» нацелено на практическое применение в
клинических целях, но имеет ограничения для использования в ряде
исследовательских задачах. Однако ПО «Энцефалан» имеет возможность
передачи необработанных данных ЭЭГ для дальнейшей обработки. По
причине ограничения применения программного обеспечения в
исследовательских целях и благодаря возможности получения
необработанных данных ЭЭГ необходимо реализовать функционал
обработки в стороннем программном обеспечении. Исходя из проведенного
обзора решений систем для обработки сигналов ЭЭГ было решено
реализовать драйвер для передачи данных программному комплексу
OpenViBE.
23
2 РАЗРАБОТКА ДРАЙВЕРА ДЛЯ ЭНЦЕФАЛОГРАФА «ЭНЦЕФАЛАН»
Программно-методическое обеспечение «Энцефалан» предоставляет
возможность получать необработанные сигналы ЭЭГ в режиме реального
времени. Сырые данные предоставляются по сетевому протоколу TCP/IP. Для
разработки драйвера компанией «Медиком МТД» был предоставлен пример
реализации обмена данными с ПМО «Энцефалан» и SDK, используя который
был реализован драйвер в среде OpenViBE.
Для того чтобы установить соединение и иметь возможность получить
данные, необходимо соответствующим образом настроить ПМО
«Энцефалан» (зайти во вкладку «Обработки», запустить «Доступ к данным»
и настроить IP адрес и Port, введя их в соответствующие поля, более
подробно на рисунке 2.1).
Рисунок 2.1 – порядок настройки ПМО «Энцефалан» для получения доступа
к данным
Настройки IP адреса и порта в дальнейшем будут использованы при
подключении к ПМО «Энцефалан», единовременное число подключений не
более одного, при подключении нового клиента связь с предыдущим будет
разорвана.
2.1 Описание протоколов обмена данными
ПМО «Энцефалан» способно передавать внешней системе
физиологические сигналы, регистрируемые в рамках основного
24
программного обеспечения. Данные могут передаваться с разной частотой
дискретизации (для модификации «Мини» 250 Гц).
Для обмена данными необходимо установить сокетное соединение с
ПМО «Энцефалан» и отправить запрос на получение информации. После
отправки запроса сервер выдает информацию о пациенте, исследовании и
режиме источника данных «Энцефалан», а затем, в случае если установлен
режим съема в реальном времени или воспроизведение, ПМО «Энцефалан»
начинает передавать пакеты с данными сигналов.
Вид пакета:
Первые 4 байта — размер данных, которые необходимо считать;
Последующие 4 байта соответствующий идентификатор равный
0х0001 для получения только ЭЭГ данных, 0х000С для получения
данных по всем доступным каналам.
Алгоритм принятия и распаковки данных:
1. Считывается пакет данных размером 4 байта, в которых хранится
размер посылаемых данных (посылки).
2. Считывается заранее определенное количество байт посылки.
3. Обрабатываются первых 4 байта, в которых хранится идентификатор
посылки (пакета).
4. В зависимости от полученного идентификатора происходит
соответствующая обработка посылки.
Используемые типы данных:
DWORD — 4б целое беззнаковое
Int — 4б целое знаковое
Short — 2б целое знаковое
Char — 1б символ
Double — 8б число с плавающей точкой.
String представляем как <int количество символов> <char[] символы
строки без завершающего 0>.
25
Полное описание пакетов приведено в Приложении Б.
2.2 Драйвер в инфраструктуре комплекса OpenViBE
Драйвер в OpenViBE – это отдельный объект, который взаимодействует
с периферийным устройством сбора данных и форматирует полученные
показатели и информацию так, как это понимает сервер сбора данных. Как
только сервер сбора данных получает информацию, он может отправлять их
одному или нескольким подключенным клиентам.
Тип соединения между оборудованием и драйвером не имеет большого
значения для сервера сбора данных. Некоторые производители оборудования
предоставляют API, чтобы драйвер имел прямой доступ к периферийному
устройству через физическое соединение (например, USB, последовательный
порт и т.д.). Некоторые из них предоставляют собственный сервер сбора
данных, который позволяет подключаться через TCP/IP для потоковой
передачи измерений в режиме реального времени. Что бы ни предоставлял
ваш производитель оборудования, драйвер OpenViBE отвечает за сбор
необходимой информации и данных с устройства и форматирует их в
соответствии с форматом OpenViBE.
Существуют два основных подхода к реализации нового драйвера.
Один из них – взять существующий драйвер (например, Generic Oscillator или
какой-либо драйвер для реального устройства) и изменить его код в
соответствии с вашими целями. Альтернатива – начать с «пустого» драйвера.
Для этого существует инструмент разработчика под названием Skeleton-
generator, который генерирует пустые файлы шаблонов, которые можно
заполнить в соответствии со своими потребностями.
Новый драйвер сначала должен объявить свое имя на сервере сбора
данных. Это будет использоваться в графическом интерфейсе сервера сбора
данных для простой идентификации оборудования, с которым работает
пользователь, поэтому необходимо дать точное имя драйверу, используя,
26
например, имя производителя оборудования и название модели
оборудования.
Драйвер по существу имеет дело с двумя видами данных: заголовок и
буфер.
Заголовок – это часть данных, которая не изменяется со временем. Он
содержит несколько идентификаторов о проводимом эксперименте,
информацию о получаемых каналах и так далее.
Буфер – это часть данных, которая меняется со временем. Он содержит
отсчеты для каждого канала в данный период времени и зависит от
количества отсчетов на отправляемый пакет. Это значение передается
драйверу на этапе инициализации.
Три наиболее важных этапа функционирования драйвера:
конфигурация;
инициализация/деинициализация;
получение данных.
Этап конфигурации может использоваться драйвером для запроса
информации заголовка от пользователя, т.е. информации которая не будет
доступна с аппаратного обеспечения. В зависимости от аппаратного
обеспечения вся информация для заголовка может быть найдена в потоковых
данных, что приводит к не конфигурируемому драйверу (если это возможно,
это может быть проще для пользователя сервера сбора данных). Например,
драйвер с физическим подключением может не указывать возраст или пол
субъекта. Такой драйвер будет нуждаться в фазе конфигурации, если такая
информация должна быть предоставлена устройством.
На этапе инициализации драйвер запрашивает состояние готовности у
оборудования. После инициализации драйвера (это означает, что
возвращается OpenViBEAcquisitionServer::Idriver::initialize), драйвер должен
иметь полный заголовок, готовый для отправки на сервер сбора данных. Цикл
драйвера OpenViBEAcquisitionServer::Idriver::loop регулярно вызывается,
27
чтобы драйвер мог поддерживать соединение с устройством в реальном
времени, отбрасывая при необходимости некоторые данные.
Этап сбора данных происходит, после вызова
OpenViBEAcquisitionServer::Idriver::start. На этом этапе драйвер регулярно
запрашивается для предоставления новых данных в функции
OpenViBEAcquisitionServer::Idriver::loop. Вся описанная выше схема
функционирования драйвера схематично изображена на рисунке 2.2.
Рисунок 2.2 – схематическое представление автомата для драйвера [17]
Реализация драйвера заключается в создании двух объектов:
OpenViBEAcquisitionServer::Idriver
OpenViBEAcquisitionServer::CСonfiguration
Листинг реализации этих объектов для энцефалографа «Энцефалан»
приведен в Приложении В.
28
2.3 Интеграция драйвера с OpenViBE
Для возможности интеграции драйвера с комплексом OpenViBE до
этапа реализации потребовалось ознакомиться правилами оформления кода в
проекте. В официальной документации приведены правила оформления кода
для версии 2.1.0 [25], текущая версия продукта 2.2.0, основные положения
правил оформления представлены в Приложении Г.
После реализации драйвера были изучены правовые вопросы,
касающиеся лицензии под которой выпущен проект OpenViBE и правил
вклада в проект.
Весь исходный код OpenViBE выпущен для общественности под
лицензией AGPL-3. Однако разные правила регулируют включение кода в
разные репозитории проекта (проект состоит из четырех репозиториев). Эти
правила необходимы для обеспечения соответствия ядра OpenViBE стандарту
«Программное обеспечение для медицинских устройств IEC 62304: 2006».
OpenViBE является бесплатным, а исходный код находится в свободном
доступе. Тем не менее, существуют требования в отношении кода и патчей
для программного обеспечения. Во всех случаях должны соблюдаться
соглашения кода OpenViBE [26]. Кроме того, для различных репозиториев
кода различаются правила вклада:
meta: вклад требует передачи авторских прав INRIA (фр. Institut
national de recherche en informatique et en automatique,
государственный институт исследований в информатике и
автоматике).
sdk и designer: вклад требует передачи авторских прав в INRIA и
строгий процесс обеспечения качества.
extras: вклад требует передачи авторских прав в INRIA.
Исключением является папка репозитория extras/contrib/, в которую
можно свободно вносить вклады, без передачи авторских прав.
Для репозитория extras, вклады могут быть свободно отправлены в
папку contrib/ дистрибутива OpenViBE. Авторы сохраняют за собой право на
29
свою работу. Вклад должен иметь совместимую лицензию AGPL3 [2].
Драйверы для электроэнцефалографов могут быть приняты в этой категории.
Для кода, предназначенного для любой другой папки в extras, участник
должен передать права на произведение INRIA.
Для кода, касающегося репозиториев sdk и designer, должен
соблюдаться строгий процесс обеспечения качества. Например, модификация
ядра относятся к этому классу.
Во всех случаях вкладчик будет считаться моральным автором
представленной работы и будет отмечен в ней в примечаниях к выпуску, веб-
документации и в других местах, которые могут применяться (например, в
исходном коде для добавленных модулей).
Практическое значение между вкладом с сохранением авторских прав и
с передачей авторских прав заключается в том, что, если предоставлена
передача авторских прав, то INRIA может получить двойную лицензию на
вклад, который будет включен в сторонние дочерние продукты OpenViBE с
закрытым исходным кодом. На данный момент к ним относятся решения для
лечения NeuroRT Studio и ADHD от Mensia Technologies. Материалы в
contrib/ не имеют двойной лицензии и, следовательно, не могут
использоваться в производных продуктах с закрытым исходным кодом.
Следовательно, участники, такие как производители оборудования, могут
рассмотреть возможность передачи авторских прав на драйверы, чтобы
получить максимальный охват пользователей для своего устройства.
Интеграция вкладов осуществляется на разных уровнях.
Во-первых, старшие разработчики основной команды имеют полный
доступ к хранилищу. Они могут изменить любой файл.
Далее, младшие разработчики основной команды имеют доступ к
работе над своими ветками в хранилище. Интеграция в основную
ветку решается со старшими разработчиками.
Наконец, участники сообщества обычно имеют доступ только для
чтения к хранилищу. Участники могут выпускать исправления и
разрабатывать пользовательские функции локально и отправлять их
30
по электронной почте основной команде в качестве кандидатов для
включения.
После рассмотрения правил вклада в проект было решено, что вклад
драйвера будет производится в директорию extras/contrib, то есть директорию
проекта, при вкладе в которую мы не передаем права на владение драйвером.
Для вклада разработанного драйвера, в соответствии с правилами,
исходный код драйвера был передан разработчикам проекта OpenViBE, после
чего с их стороны была произведена проверка кода на соответствие правилам
оформления, проверка возможности компиляции под операционные системы
windows и linux, и получена обратная связь с рекомендациями по
нормализации кода. После внесения правок в соответствии с рекомендациями
драйвер был принят в проект OpenViBE, без передачи права владения кодом
INRIA.
Драйвер будет доступен в приложении OpenViBE после релиза версии
2.3.0. Релиз данной версии запланирован на лето 2019.
2.4 Интерфейс разработанного драйвера
Драйвер является частью сервера сбора данных в программном
комплексе OpenViBE и доступен для выбора в графическом интерфейсе
наряду с драйверами для других электроэнцефалографов (рисунок 2.3).
Рисунок 2.3 – интерфейс сервера сбора данных OpenViBE
31
Разработанный драйвер является конфигурируемым, то есть при
нажатии на кнопку «Driver Properties» открывается окно настроек драйвера
(рисунок 2.4).
Рисунок 10.4 – окно настроек драйвера
В настройках драйвера можно установить идентификатор, возраст и
пол испытуемого, а также необходимо задать число каналов в сигнале,
частоту дискретизации текущей реализации доступно значение только 250
Гц, что соответствует частоте сигнала в модификации «Мини») и адрес
сервера «Энцефалан» (IP и Port).
Дополнительно для каналов можно установить символьные
обозначения. Для этого необходимо нажать кнопку «Change channel names» и
в открывшемся окне (рисунок 2.5) установить советующим номерам каналов
символьные обозначения.
32
Рисунок 2.5 – установка символьных обозначений для каналов в сигнале
33
3 ИНТЕЛЛЕКТУАЛЬНАЯ СИСТЕМА ДЛЯ ИССЛЕДОВАНИЯ
ИНТЕРФЕЙСА МОЗГ-КОМПЬЮТЕР
В результате разработки драйвера появилась возможность использовать
потенциал системы OpenViBE совместно с электроэнцефалографом
«Энцефалан». Ниже представлены основные характеристики и возможности
полученной системы.
OpenViBE это программная платформа, предназначенная для
проектирования, тестирования и использования интерфейсов мозг-
компьютер. OpenViBE позволяет строить системы обработки сигналов
электроэнцефалограммы в реальном времени. ПО OpenViBE можно
использовать для сбора, фильтрации, обработки, классификации и
визуализации сигналов мозга в режиме реального времени.
Основными областями применения OpenViBE являются медицинские
(помощь людям с ограниченными возможностями, биологическая обратная
связь в реальном времени, нейробиоуправление, диагностика в реальном
времени), мультимедиа (виртуальная реальность, видеоигры), робототехника
и другие области применения, связанные с интерфейсами мозг-компьютер.
Платформа OpenViBE обладает множеством уникальных функций,
которые помогают создавать приложения BCI.
Платформа OpenViBE поставляется с универсальным сервером сбора
данных. Он способен получать данные со множества совместимых устройств
и отправлять их любому количеству клиентов OpenViBE в сети. Число
поддерживаемых устройств более 30, в том числе в ближайшем времени
список пополнится электроэнцефалографом «Энцефалан». Сервер сбора
данных позволяет переключать устройства для сбора ЭЭГ без необходимости
вносить какие-либо изменения в цепочку обработки.
Комплекс OpenViBE является мультиплатформенной системой с
открытым исходным кодом, выпущенное под лицензией GNU Affero General
Public License v3.0 (AGPL-3). Это означает, что исходный код приложения
34
можно модифицировать и распространять. OpenViBE написан с учетом
совместимости с несколькими платформами. В настоящее время он может
быть построен на Windows и Linux. Кроме того, для Windows существует
установочный пакет, который позволяет использовать OpenViBE без сборки и
компиляции.
Простой в использовании графический интерфейс, с помощью которого
можно легко и быстро построить цепочку обработки данных. Для проведения
исследования с OpenViBE нет нужды знать язык программирования, все
делается мышью и простыми жестами перетаскивания. Каждая часть цепочки
обработки сигналов представлена прямоугольником. Чтобы связать выход
одного блока с входом другого, прямоугольники просто связываются вместе.
Таким образом строятся сценарии обработки данных, которые могут быть
сопровождены комментариями с поддержкой расширенного текста.
В OpenViBE широкий выбор методов обработки сигналов, поскольку
система поставляется со многими алгоритмами обработки, которые можно
использовать для фильтрации и извлечения признаков из сигнала.
OpenViBE содержит различные методы классификации:
Линейный Дискриминантный Анализ (LDA);
Метод опорных векторов (SVM);
Искусственные нейронные сети (многослойный персептрон (MLP)).
Для преобразования признаков в команды можно использовать
несколько методов машинного обучения, включенных в OpenViBE.
OpenViBE включает в себя инструмент для анализа в автономном
режиме, называемый OpenViBE Tracker. С помощью Tracker можно загружать
несколько файлов одновременно и свободно просматривать их содержимое
(рисунок 3.1).
35
Рисунок 3.1 – графический интерфейса OpenViBE Tracker
Загруженные данные могут быть перенаправлены в обычные плагины
OpenViBE локи, сценарии) для обработки, либо каждый набор данных
независимо, либо сгруппированы в один длинный набор данных. OpenViBE
Tracker может использовать несколько процессорных ядер для параллельной
обработки сигналов.
В OpenViBE включены плагины для реализации собственных блоков
обработки сигналов на языках Python, MatLab, LUA.
Документация OpenViBE описывает, как работать с различными
приложениями и компонентами системы. Учебники и примеры являются
хорошей отправной точкой. Кроме того, раздел с часто задаваемыми
вопросами (FAQ) по OpenViBE отвечает на многие распространенные
вопросы.
36
4 ИССЛЕДОВАНИЯ КОГНИТИВНОГО ПОТЕНЦИАЛА
При органических повреждениях коры головного мозга основным
патологическим процессом является гибель нервных клеток
(нейродегенерация). Клиническим эквивалентом нейродегенерации является
когнитивный дефицит [10]. Эта проблема проявляет себя так же при
старении, когда истощаются ресурсы организма.
При выполнении когнитивных нагрузок в здоровом мозге наблюдается
высокая степень интегративности структур мозга, в то время как для
поврежденного мозга степень вовлеченности структур может быть
значительно снижена, другими словами, органическое повреждение центров
коры препятствует их интеграции [11]. Для оценки интегративной
деятельности мозга необходимо решать задачу выявления взаимосвязи между
различными областями головного мозга. В настоящей работе для
определения степени связи между каналами в сигнале ЭЭГ использовался
метод когерентного анализа.
4.1 Интегральная метрика оценки взаимосвязи областей мозга
Функция когерентности является аналогом коэффициента корреляции в
частотной области и отражает степень линейной взаимосвязи гармонических
компонент рассматриваемых процессов. Чем ближе функция когерентности к
единице на данной частоте, тем больше совпадение гармонических
составляющих на этой частоте.
Функция когерентности (xy) определяется путем нормировки взаимной
спектральной плотности (1).
γ2
xy
(
f
)
=
|
Sxy (f)
|
2
Sxx (f)∙Syy (f)
(1)
где Sxy взаимная спектральная плотность или кросс-спектр, Sxx и Syy – авто-
спектры.
37
После применения когерентного анализа для N-канальной записи
получаем матрицу связей (2). Значения функции когерентности на главной
диагонали равны единицы (xx = 1)
γ=
1γ1N(f)
⋮ ⋱ ⋮
γN1(f)1
(2)
Полученная матрицу N×N была преобразована в неориентированный
взвешенный граф, как в работе [12], с применением порога Т. Вершины
представляют электроды ЭЭГ, в то время как наличие ребер между
вершинами зависит от силы связи между соответствующими каналами. Если
значение функции когерентности превышает порог T, то между вершинами
устанавливается ребро, и весу ребра присваивается значение функции
когерентности, в противном случае ребро между вершинами отсутствует.
Ребра графа имеют вес поскольку взвешенные графы представляют собой
более точные модели реальных сетей и используют больше информации по
сравнению с двоичными графами [13].
Для полученного графа рассчитывается среднее значение
коэффициента кластеризации вершины ni. Веса между вершинами ni и nj
являются симметричными ijji). Взвешенный коэффициент кластеризации
(Cw) определяется в соответствии с [14]:
Ci
W=
j≠ i
k ≠i
k ≠ j
(ω' ij ω ' ik ω ' jk)1/3
ki(ki1),
(3)
где ki обозначает степень ni, то есть число ребер, связанных с ni;
ω’ijij/max(ωij) - нормализованный вес. Средний коэффициент кластеризации
всего графа может быть определен как (4):
CW=1
N
i=1
N
Ci
W,
(4)
где N – количество вершин графа.
38
4.2 Сбор данных и программа эксперимента
Экспериментальные данные были получены для 7 испытуемых. Для
записи сигнала использовался электроэнцефалограф «Энцефалан-ЭЭГР-
19/26» модификация «Мини». Полученные данные были сохранены в
формате GDF с помощью OpenViBE.
Во время исследования испытуемые выполняли тесты, моделирующие
различные функциональные состояния при которых предполагается
наблюдать увеличение степени связи областей мозга [15].
Тест 1 взаимная координация: участника просят поочередно сжимать
кулаки, при этом руки подняты до уровня головы.
Тест 2 динамическая практика: участника просят повторить
последовательность быстрых движений «кулак» - «ребро» - «ладонь».
Тест 3 словесный подсчет: испытуемому предлагается производить
вычитание от 100 по 7, произнося в слух только результат вычитания.
В таблице 1 приведена циклограмма исследования. Перед началом
выполнения тестов необходимо выполнить запись фонового сигнала. Между
тестами небольшие паузы для отдыха испытуемого.
Таблица 4.1
Циклограмма исследования
Стадия Длительность, мин. Начало Конец
1 Фон 2 0:00 2:00
2 Тест 1 1,5 2:00 3:30
3 Фон 0,5 3:30 4:00
4 Тест 2 1,5 4:00 5:30
5 Фон 0,5 5:30 6:00
6 Тест 3 1,5 6:00 7:30
7 Фон 1,5 7:30 9:00
4.3 Анализ данных
Для анализа данных в графическом дизайнере OpenViBE была
составлена цепочка обработки данных (рисунок 4.1).
39
Рисунок 4.1 – цепочка обработки данных в OpenViBE
Цепочка обработки данных состоит из шести блоков:
1. GDF file reader – блок, реализующий чтение сигнала из GDF файла;
2. Temporal Filter – временной фильтр для выделения полосы частот
14-30 Гц;
3. Time based epoching – выделение эпох из сигнала (15 секунд с шагом
в 5 секунд);
4. Connectivity Measure (Coherence) блок, реализующий метод
когерентного анализа (на выходе спектр когерентности);
5. Spectrum Average получение среднего значения спектра
когерентности по всем частотам, найденным во входном сигнале;
6. Connectivity Analysis блок в котором реализован расчет метрики,
блок реализован исключительно для проведения исследования и
производит запись результатов в файл CSV (Приложение Д).
40
Для расчета метрики необходимо установить пороговое значение T.
Для установки порогового значения был произведен анализ данных для всех
значений параметра T [0, 1] с шагом 0,02. В результате получилась
зависимость Cw от T (рисунок 4.2).
0 0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9 1
0.00000
0.10000
0.20000
0.30000
0.40000
0.50000
0.60000
0.70000
0.80000
0.90000
фон тест 1 тест 2 тест 3
T
Cw
Рисунок 4.2 – зависимость Cw от T для всех функциональных состояний
На графике можно видеть резкое уменьшение значения Cw при
достижении определённого порогового значения. Наибольшую разницу
значения Cw между функциональными состояниями можно наблюдать при
значении параметра T, при котором скорость изменения Cw максимальна.
Поэтому в качестве порогового было выбрано значение, соответствующее
максимальной скорости изменения Cw для фонового сигнала. Для всех
испытуемых значение порога T лежит в пределах 0.56-0.6. Для дальнейшего
анализа данных использовалось пороговое значение T = 0.58 для всех
испытуемых.
Для всех испытуемых получены графики распределения Cw во времени
с шагом 5 секунд, графики приведены на рисунках 4.3-4.9.
41
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Время (t)
Cw
Рисунок 4.3 – изменение Cw во времени для первого испытуемого
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
1
Время (t)
Cw
Рисунок 4.4 – изменение Cw во времени для второго испытуемого
42
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
0.9
Время (t)
Cw
Рисунок 4.5 – изменение Cw во времени для третьего испытуемого
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Время (t)
Cw
Рисунок 4.6 – изменение Cw во времени для четвертого испытуемого
43
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Время (t)
Cw
Рисунок 4.7 – изменение Cw во времени для пятого испытуемого
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Время (t)
Cw
Рисунок 4.8 – изменение Cw во времени для шестого испытуемого
44
15
35
55
75
95
115
135
155
175
195
215
235
255
275
295
315
335
355
375
395
415
435
455
475
495
515
535
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Время (t)
Cw
Рисунок 4.9 – изменение Cw во времени для седьмого испытуемого
Из приведенных графиков можно видеть увеличение значения Cw во
время выполнения тестов и снижение для фонового сигнала.
Для всех испытуемых по каждому функциональному состоянию было
получено среднее значение Cw. Полученные средние значения,
соответствующие выполнению тестов, сравнивались со значением для
фоновой записи, данное сравнение показано на рисунках 4.10-4.12.
45
1 2 3 4 5 6 7
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
0.8
Фон Тест 1
Испытуемый
Cw
Рисунок 4.10 – сравнение Cw для теста 1 и фоновой записи для всех
испытуемых
1 2 3 4 5 6 7
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
Фон Тест 2
Испытуемый
Cw
Рисунок 4.11 – сравнение Cw для теста 2 и фоновой записи для всех
испытуемых
46
1 2 3 4 5 6 7
0
0.1
0.2
0.3
0.4
0.5
0.6
0.7
Фон Тест 3
Испытуемый
Cw
Рисунок 4.12 – сравнение Cw во время теста 3 и фоновой записи для всех
испытуемых
Из полученных графиков видно, что значения Cw во время выполнения
тестов превышают значения для фонового сигнала. Для проверки
статистической значимости различия средних значений Cw был применен
непараметрический критерий U-Манна-Уитни, который применяется для
выборок с малым количеством испытуемых [16]. Для выборок по 7
измерений Uкрит. = 11 для уровня значимости p=0.05. U значения для тестов
в сравнении с фоном составили следующие значения: для первого теста U1 =
9, для второго U2 = 0 и для третьего U3 = 21. В случае, U > Uкрит.
принимается гипотеза о незначительности различий между выборками. В
случае, U ≤ Uкрит. между выборками существует статистически значимое
различие. Таким образом для первого и второго тестов удалось показать
статистически значимое отличие Cw от фонового значения. Для третьего
теста различия с фоновым значением Cw статистически не значимы.
47
5 ЗАЩИТА ОБЪЕКТОВ ИНТЕЛЛЕКТУАЛЬНОЙ СОБСТВЕННОСТИ
Одним из результатов работы стала разработка драйвера для
электроэнцефалографа «Энцефалан» в комплексе OpenViBE. Разработанный
драйвер предназначен для получения необработанных данных в режиме
реального времени программным комплексом OpenViBE из программного
обеспечения «Энцефалан». Драйвер обеспечивает выполнение следующих
функций: инициализация сокетного подключения к программному
обеспечению «Энцефалан»; обмен пакетами данных в режиме реального
времени; чтение пакетов данных, полученных от программного обеспечения
«Энцефалан»; упаковка и передача пакетов данных программному комплексу
OpenViBE.
Данная разработка является уникальной. Для подтверждения
уникальности был произведен патентный поиск по базам данных
«Федерального института промышленной собственности» [27]. Патентный
поиск проводился на предмет разработок, связанных с
электроэнцефалографом «Энцефалан» и с программным обеспечением
OpenViBE, результаты патентного поиска приведены в таблице 5.1.
Таблица 5.1
Результаты патентного поиска
Название программы Номер
регистрации
Дата
регистрации
Программа для выявления в реальном
времени паттернов на ЭЭГ в процессе
решения когнитивных задач
2018662580 11.10.2018
Программа для ЭВМ для поиска и
выделения проэпилептических событий на
сигналах ЭЭГ на базе вейвлет-анализа и
эмпирических мод
2017619170 16.08.2017
Программа для ЭВМ на базе вейвлетного
анализа предоставляющая возможность
оценки основных характерных ритмов
активности головного мозга (альфа-, бета-,
2017613679 24.03.2017
48
гамма-ритмы)
Программа визуального отображения
связей между сигналами ЭЭГ 2017619061 15.08.2017
Программа для ЭВМ по удалению
мышечных артефактов на сигнале ЭЭГ на
базе преобразования Гильберта-Хуанга
(Huang EMG Artifact Filtration)
2017613643 23.03.2017
Программа для ЭВМ классификации
паттернов движений человека по
экспериментальным данным ЭЭГ на основе
непрерывного вейвлетного преобразования
2017613164 13.03.2017
Программа для ЭВМ по предварительной
обработке многоканальных записей
электроэнцефалографии человека
(PREProcessing EEG)
2016660511 16.09.2016
Программа для ЭВМ многоканального
выделения устойчивых паттернов по
сигналам ЭЭГ на базе адаптивного
вейвлетного преобразования
2017613305 15.03.2017
Программа для ЭВМ по построению
вейвлетных усреднённых характеристик
для оценки когнитивной функции человека
(COGNITIVE WVlt EEG)
2016660399 15.09.2016
Программа для ЭВМ обеспечения сложного
дизайна нейрофизиологического
эксперимента в области исследования
двигательной активности различных типов
при синхронной
электроэнцефалографической регистрации
у человека
2018612999 01.03.2018
Chemical Differentiation 2016661340 06.10.2016
В результате патентного поиска удалось найти 12 регистраций,
связанных с обработкой данных электроэнцефалограммы и синхронизацией с
программным обеспечением «Энцефалан». Разработок для программного
комплекса OpenViBE найти не удалось. Таким образом можно сделать вывод,
что нет зарегистрированных разработок по интеграции
49
электроэнцефалографа «Энцефалан» с программным обеспечением
OpenViBE.
Для разработанного программного обеспечения была заполнена анкета
для заявки на регистрацию программного обеспечения. В качестве заявителя
выступает ФГАОУ ВО «УрФУ имени первого Президента России Б.Н.
Ельцина». Наименование продукта: Драйвер для программного комплекса
OpenViBE для получения данных из программного обеспечения
«Энцефалан».
50
ОБСУЖДЕНИЕ РЕЗУЛЬТАТОВ
Для создания системы для разработки, исследования и использования
интерфейсов мозг-компьютер был произведен сравнительный анализ двух
крупных международных проектов по исследованию систем мозг-компьютер:
BCI2000 и OpenViBE. Оба проекта представляют из себя программные
комплексы с открытым исходным кодом и поддержкой многих парадигм
реализации интерфейсов мозг-компьютер. Благодаря более подробной
документации, наличию графического редактора сценариев обработки
данных и сообществу, которое развивает проект в настоящее время, в
качестве основы для реализации интеллектуальной системы для
исследования интерфейса мозг-компьютер был выбран программный
комплекс OpenViBE.
Для электроэнцефалографа-регистратора «Энцефалан» был реализован
драйвер, позволяющий получать сырые данные ЭЭГ. Разработанный драйвер
был интегрирован в программный комплекс OpenViBE. Драйвер будет
доступен для всех исследователей, использующих электроэнцефалограф
«Энцефалан», в проекте OpenViBE версии 2.3.0, релиз этой версии
запланирован на лето 2019. Благодаря реализованному драйверу удалось
получить программный комплекс с открытым исходным кодом, который
развивается крупным сообществом и который можно модернизировать в
соответствии с потребностями исследователей.
Была произведена апробация интеллектуальной информационной
системы при проведении исследования по определению когнитивного
потенциала человека. Для проведения данного исследования была
предложена интегральная метрика оценки взаимосвязи областей мозга на
базе анализа графа. Данная метрика основана на коэффициенте
кластеризации графа и принимает значения от 0 до 1.
С помощью предложенной метрики удалось пронаблюдать увеличение
степени вовлеченности структур мозга в деятельность при когнитивной
51
нагрузке. При анализе данных был определен оптимальный порог для
определения наличия связи по коэффициенту когерентности, который
составил 0.58. Исходя из полученного порогового значения сформирован
граф связей для каждого функционального состояния и рассчитано значение
предложенной метрики. Полученные результаты для всех функциональных
состояний сравнивались с фоновым значением, при этом для проверки
статистической значимости различия средних двух выборок был применен
однофакторный дисперсионный анализ.
Для всех функциональных состояний значение метрики увеличилось в
разной степени: для первого («сжимание-разжимание кулаков») и второго
теста («кулак-ребро-ладонь») удалось показать статистически значимое
различие средних значений по сравнению с фоновым, они составили
соответственно 0,14 и 0,18, для третьего теста («устный обратный счет») не
удалось установить статистически значимого увеличения среднего значения
метрики, которое составило 0,05.
Наличие статистически значимых различий говорит о возможности
определения изменения функционального состояния человека с
использованием предложенной метрики. Так как метрика оценивает наличие
и величину связей между различными областями головного мозга, то она
может применяться для различных методик восстановления когнитивного
потенциала.
Наличие вклада в проект OpenViBE позволяет сделать доступными
результаты работы для отечественных и зарубежных исследователей
интерфейсов мозг-компьютер.
52
ЗАКЛЮЧЕНИЕ
В ходе выполнения диссертационной магистерской работы был
разработан драйвер для электроэнцефалографа «Энцефалан», разработанный
драйвер интегрирован в программный комплекс OpenViBE. Таким образом
получена интеллектуальная информационная система для разработки,
исследования и использования интерфейсов мозг компьютер.
Проведена апробация полученной системы с применением
разработанной метрики оценки взаимосвязей областей мозга. Произведен
анализ полученных данных. Анализ данных показал возможность
применения метрики для оценки когнитивного потенциала человека.
В итоге можно сделать вывод, что цель магистерской диссертации
достигнута и выполнены все задачи, поставленные для достижения цели.
53
СПИСОК ЛИТЕРАТУРЫ
1. Wang F. [и др.]. EEG-based mental fatigue assessment during driving by using
sample entropy and rhythm energy 2015. 1906–1911 с.
2. Tarik Al-ani and Dalila Trad. Signal Processing and Classification Approaches
for Brain-Computer Interface // Intelligent and Biosensors 2010, Vernon S.
Somerset (Ed).
3. Rajesh Singla. Comparison of SVM and ANN for classification of eye events in
EEG / Rajesh Singla, Brijil Chambayil, Arun Khosla, Jayashree Santosh // J.
Biomedical Science and Engineering. 2011. 4. 62-69. DOI:
10.4236/jbise.2011.41008.
4. Jesus Minguillon. Trends in EEG-BCI for Daily-Life: Requirements for Artifact
Removal / Jesus Minguillon, M. Angel Lopez-Gordo, Francisco Pelayo //
Biomedical Signal Processing and Control. January 2017. DOI:
10.1016/j.bspc.2016.09.005.
5. B. Sumak. Design and Development of Contactless Interaction with Computers
Based on the Emotiv EPOC+ Device // MIPRO 2017, May 22-26, Opatija,
Croatia, 2017.
6. Asif Ishfaque. Evaluation of ANN, LDA and Decision Trees for EEG Based
Brain Computer Interface // International Conference on Emerging
Technologies (ICET 2013). 2013. DOI: 10.1109/ICET.2013.6743513.
7. L. Gao. EEG classification for motor imagery and resting state in BCI
applications using multi-class Adaboost extreme learning machine / L. Gao, W.
Cheng, J. Zhang, J. Wang // Review of Scientific Instruments. 2016. vol. 87, no.
8. DOI: 10.1063/1.4959983.
8. Alexander Frolov. Comparison of four classification methods for brain-
computer interface / Alexander Frolov, Dusan Husek, Pavel Bobrov // Neural
Network World. 2011. 21(2). 101-115. DOI: 10.14311/NNW.2011.21.007.
9. Jiayu Zhuang. Motion Control of a Four-Wheel-Independent-Drive Electric
Vehicle by Motor Imagery EEG Based BCI System // Proceedings of the 36th
Chinese Control Conference 2017, July 26-28. Dalian, China, 2017.
10.Retyunskiy, K. J., Kublanov, V. S., Petrenko, T. S., Petrenko, A. A., Dolganov,
A. Y. The functional brain asymmetry as a method for evaluation of the
cognitive potential for patients with organic brain damage // Cognitive
Sciences, Genomics and Bioinformatics (CSGB). Novosibirsk, 2016. pp.1-4.
54
11.Inge Leunissen. Subcortical volume analysis in traumatic brain injury: the
importance of the frontostriato-thalamic circuit in task switching / Inge
Leunissen, J.P. Coxon, K.Caeyenberghs, K. Michiels, S. Sunaert, S.P.
Swinnen // Cortex. 2014. vol.51. pp.67–81.
12.Junjie Wu. Graph theoretical analysis of EEG functional connectivity during
music perception / Junjie Wu, Junsong Zhang, Chu Liu, Dongwei Liu, Xiaojun
Ding, Changle Zhou // Brain research. 2012.
13.Stam, C.J. Graph theoretical analysis of complex networks in the brain / Stam,
C.J., Reijneveld, J.C. // Nonlinear Biomed. 2007. Phy. 1, 3.
14.Onnela, J.-P. 2005. Intensity and coherence of motifs in weighted complex
networks. / Onnela, J.-P., Saramaki, J., Kertesz, J., Kaski, K. // Physical Review
E. vol. 71. 2005.
15.M.I. Posner. Cognitive neuroscience: Origins and promise / M.I. Posner, G.J.
Digirolamo // Psychological Bulletin. vol. 126 (6). 2000. pp.873–889.
16.Glantz S.A. Primer of biostatistics / S.A. Glantz, 5th ed., New York: McGraw-
Hill: Medical Pub. Div., 2002.
17.BCI2000 // Schalk Lab [Электронный ресурс]. URL:
http://www.schalklab.org/research/bci2000 (дата обращения: 15.05.2019).
18.Software for Brain Computer Interfaces and Real Time Neurosciences //
OpenViBE [Электронный ресурс]. URL: http://openvibe.inria.fr/ (дата
обращения: 15.05.2019).
19.Медицинское оборудование для функциональной диагностики,
нейрофизиологии, реабилитации и научных исследований // Медиком
МТД [Электронный ресурс]. URL: http://medicom-
mtd.com/htm/Products/products_main.html (дата обращения: 15.05.2019).
20.Documentation: Box Descriptions // OpenViBE [Электронный ресурс]. URL:
http://openvibe.inria.fr/documentation/2.2.0/Doc_BoxAlgorithms.html (дата
обращения: 15.05.2019).
21.Documentation // OpenViBE [Электронный ресурс]. URL:
http://openvibe.inria.fr/documentation-index/ (дата обращения: 15.05.2019).
22.Электроэнцефалографические исследования «Энцефалан-ЭЭГ» //
Медиком МТД [Электронный ресурс]. URL: http://medicom-
mtd.com/htm/Study/EEG/study_eeg_temp.html (дата обращения: 15.05.2019).
23.Электроэнцефалограф-регистратор «Энцефалан-ЭЭГР-19/26».
Модификация «Мини» // Медиком МТД [Электронный ресурс]. URL:
55
http://medicom-mtd.com/htm/Products/eegr-mini.html (дата обращения:
15.05.2019).
24.Tutorial 1: Creating a new driver for the acquisition server // OpenViBE
[Электронный ресурс]. URL: http://openvibe.inria.fr/tutorial-creating-a-new-
driver-for-the-acquisition-server/ (дата обращения: 15.05.2019).
25.Coding Rules // OpenViBE [Электронный ресурс]. URL:
http://openvibe.inria.fr/coding-rules/ (дата обращения: 15.05.2019)
26.Contribution Rules and Coding Standards // OpenViBE [Электронный
ресурс]. URL: http://openvibe.inria.fr/contribution-rules/ (дата обращения:
15.05.2019).
27.Федеральное государственное бюджетное учреждение Федеральный
институт промышленной собственности // ФИПС [Электронный ресурс].
URL: http://www1.fips.ru/ (дата обращения: 13.03.2019)
28.
56
ПРИЛОЖЕНИЕ А
Технические характеристики блока АБП-10
Разрядность АЦП: 24 бит;
Частота съема данных: 250 Гц;
Диапазон регистрации напряжения: от 0,005 до 8 мВ;
Напряжение шума: 0.23 мкВ;
Коэффициент подавления режекторного фильтра: не менее 60 дБ;
Входное сопротивление: не менее 200 Мом;
Фильтрация сигнала: настраиваемые ФНЧ и ФВЧ;
Масса: 200г (без аккумуляторов);
Габаритные размеры: 123x78x28 мм.
57
ПРИЛОЖЕНИЕ Б
Описание пакетов данных для обмена с ПО «Энцефалан»
Таблица Б.1
Описание пакетов для обмена с ПО «Энцефалан»
Идентификат
ор пакета
(DWORD)
Данные пакета Описание
0x0001 - Входящее: запрос на общую
информацию об исследовании.
Без данного запроса процесс
передачи данных не начинается!
0x0002 < string Имя пациента >,
<int кол-во каналов>,[<
string имена каналов>],
< string имя схемы
реконструкции>, <double
вес бита>, <double
частота дискретизации>
Исходящее: Ответ на общую
информацию об исследовании
0x0003 <int идентификатор
кнопки> < состояние
кнопки>
Исходящее: Нажата кнопка на
GUI
0x0004 <int идентификатор
кнопки> < состояние
кнопки>
Входящее: Установить состояние
кнопки в GUI
0x0005 <int идентификатор
кнопки> <string
подпись>
Входящее: Установить подпись
для GUI элемента
0x0006 <int> 1 начинаем
передачу (пользователь
перешел в режим съема
Исходящее: Начало/завершение
передачи данных
58
данных)
0 завершаем передачу
(пользователь перешел в
режим обработки)
0x0007 <int> - номер ФП от 0 Входящее: Смена текущей ФП
0x0008 <int номер среза>< int
количество каналов>
<[Short данные
сигналов]>
Исходящее: Срез данных
0x0009 <int номер среза>,
<string название ФП>
Исходящее: Данные о маркере
Функциональной пробы.
0x000A <int номер среза>,
<string имя файла
картинки>
Исходящее: Данные о маркере
АВС
0x000E Входящий запрос. Говорит о том
что нам нужны будут
килогерцовые данные.
0x002E <ID>
<Имя пациента>
<Возраст>
<Пол>
<Количество каналов>
[
<Имя канала >
<Вес бита>
<Частота>
<Метрика>
<Нижний фильтр>
<Верхний фильтр>
ровень фильтра>
<Состояние режектора>
Ответ на запрос килогерцовых
данных.
59
<Чувствительность>
]
<Идентификатор
исследования>
<Схема реконструкции>
0x00E8 <ID>
<Количество
килогерцовых каналов>
<Общий размер данных>
<Данные>
Пришел пакет с данными
60
ПРИЛОЖЕНИЕ В
Листинг реализации драйвера
ovasCConfigurationEncephalan.h
///--------------------------------------------------------------------------
-----------------------
///
/// \file ovasCConfigurationEncephalan.h
/// \brief The CConfigurationEncephalan handles the configuration dialog
specific to the Encephalan device.
/// \author Alexey Minin (UrFU)
/// \version 1.0.
/// \date 02/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU
Affero General Public License v3.0</a>.
///
///--------------------------------------------------------------------------
-----------------------
#pragma once
#include "../ovasCConfigurationBuilder.h"
#include "ovasIDriver.h"
namespace OpenViBEAcquisitionServer
{
/// <summary> The CConfigurationEncephalan handles the configuration
dialog specific to the Encephalan device. </summary>
/// <seealso cref="CDriverEncephalan" />
class CConfigurationEncephalan : public CConfigurationBuilder
{
public:
CConfigurationEncephalan(IDriverContext& driverContext, const
char* gtkFileName, uint32_t& connectionPort, char* connectionIp);
bool preConfigure() override;
bool postConfigure() override;
char* getConnectionIp() const { return m_connectionIp; }
protected:
IDriverContext& m_driverContext;
uint32_t& m_connectionPort;
char* m_connectionIp;
};
};
ovasCConfigurationEncephalan.cpp
#include "ovasCConfigurationEncephalan.h"
#include <gtk/gtk.h>
using namespace OpenViBE;
using namespace Kernel;
using namespace OpenViBEAcquisitionServer;
using namespace std;
61
//---------------------------------------------------------------------------
------------------------
CConfigurationEncephalan::CConfigurationEncephalan(IDriverContext&
driverContext, const char* gtkFileName, uint32_t& connectionPort, char*
connectionIp)
: CConfigurationBuilder(gtkFileName), m_driverContext(driverContext),
m_connectionPort(connectionPort), m_connectionIp(connectionIp) { }
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CConfigurationEncephalan::preConfigure()
{
if (!CConfigurationBuilder::preConfigure()) { return false; }
GtkSpinButton* l_pConnectionPort =
GTK_SPIN_BUTTON(gtk_builder_get_object(m_pBuilderConfigureInterface,
"spinbutton_port"));
gtk_spin_button_set_value(l_pConnectionPort, m_connectionPort);
GtkEntry* l_pConnectionIp =
GTK_ENTRY(gtk_builder_get_object(m_pBuilderConfigureInterface, "entry_ip"));
gtk_entry_set_text(l_pConnectionIp, m_connectionIp);
return true;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CConfigurationEncephalan::postConfigure()
{
if (m_bApplyConfiguration)
{
GtkSpinButton* l_pConnectionPort =
GTK_SPIN_BUTTON(gtk_builder_get_object(m_pBuilderConfigureInterface,
"spinbutton_port"));
m_connectionPort =
uint32_t(::gtk_spin_button_get_value_as_int(l_pConnectionPort));
GtkEntry* l_pConnectionIp =
GTK_ENTRY(gtk_builder_get_object(m_pBuilderConfigureInterface, "entry_ip"));
m_connectionIp =
const_cast<char*>(gtk_entry_get_text(l_pConnectionIp));
}
return CConfigurationBuilder::postConfigure();
}
//---------------------------------------------------------------------------
------------------------
ovasCDriverEncephalan.h
///--------------------------------------------------------------------------
-----------------------
///
/// \file ovasCDriverEncephalan.h
/// \brief The CDriverEncephalan allows the acquisition server to acquire
data from a Encephalan device.
/// \author Alexey Minin (UrFU)
62
/// \version 1.0.
/// \date 02/01/2019.
/// \copyright <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU
Affero General Public License v3.0</a>.
///
///--------------------------------------------------------------------------
-----------------------
#pragma once
#if defined TARGET_OS_Windows
#include "ovasIDriver.h"
#include "../ovasCHeader.h"
#include <openvibe/ov_all.h>
#include "../ovasCSettingsHelper.h"
#include "../ovasCSettingsHelperOperators.h"
#include "winsock.h"
namespace OpenViBEAcquisitionServer
{
/// <summary> The CDriverEncephalan allows the acquisition server to
acquire data from a Encephalan device. </summary>
/// <seealso cref="CConfigurationEncephalan" />
class CDriverEncephalan : public IDriver
{
public:
explicit CDriverEncephalan(IDriverContext& driverContext);
~CDriverEncephalan() override = default;
const char* getName() override { return "Encephalan"; }
bool initialize(uint32_t sampleCountPerBlock, IDriverCallback&
callback) override;
bool uninitialize() override;
bool start() override;
bool stop() override;
bool loop() override;
bool isConfigurable() override { return true; }// change
to false if your device is not configurable
bool configure() override;
const IHeader* getHeader() override { return &m_header; }
bool isFlagSet(const EDriverFlag flag) const override { return
flag == DriverFlag_IsUnstable; }
protected:
bool connectEncephalan();
bool sendRequestForData() const;
bool sendData(BYTE* data, int dataSize) const;
bool receiveData();
void readData(BYTE* data, int dataSize);
static void getData(BYTE* & data, int& dataSize, void*
pTargetData, int targetDataSize);
void receiveEEGData(BYTE* curData, int curDataSize);
SettingsHelper m_settings;
IDriverCallback* m_callback = nullptr;
CHeader m_header;
63
uint32_t m_sampleCountPerBlock = 0;
float* m_sample = nullptr;
char* m_connectionIp = nullptr;
uint32_t m_connectionPort = 120;
uint32_t m_currentPoint = 0;
SOCKET m_client = 0;
};
}
;
#endif // TARGET_OS_Windows
ovasCDriverEncephalan.cpp
#if defined TARGET_OS_Windows
#include "ovasCDriverEncephalan.h"
#include "ovasCConfigurationEncephalan.h"
using namespace OpenViBEAcquisitionServer;
using namespace OpenViBE;
using namespace Kernel;
using namespace std;
//---------------------------------------------------------------------------
------------------------
CDriverEncephalan::CDriverEncephalan(IDriverContext& driverContext)
: IDriver(driverContext),
m_settings("AcquisitionServer_Driver_Encephalan",
m_rDriverContext.getConfigurationManager())
{
m_connectionIp = static_cast<char*>("127.0.0.1");
m_header.setSamplingFrequency(250);
m_header.setChannelCount(8);
m_settings.add("Header", &m_header);
m_settings.load();
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::initialize(const uint32_t sampleCountPerBlock,
IDriverCallback& callback)
{
if (m_rDriverContext.isConnected()) { return false; }
if (!m_header.isChannelCountSet() || !
m_header.isSamplingFrequencySet()) { return false; }
m_sample = new float[m_header.getChannelCount() *
sampleCountPerBlock];
if (!m_sample)
{
delete[] m_sample;
m_sample = nullptr;
return false;
}
// Saves parameters
m_callback = &callback;
64
m_sampleCountPerBlock = sampleCountPerBlock;
return connectEncephalan();
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::start()
{
if (!m_rDriverContext.isConnected() || m_rDriverContext.isStarted()) {
return false; }
// request hardware to start
return sendRequestForData();
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::loop()
{
if (!m_rDriverContext.isConnected()) { return false; }
if (!m_rDriverContext.isStarted()) { return true; }
m_currentPoint = 0;
ZeroMemory(m_sample,
sizeof(float32)*m_sampleCountPerBlock*m_header.getChannelCount());
while (m_currentPoint < m_sampleCountPerBlock) { receiveData(); }
m_callback->setSamples(m_sample);
return true;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::stop()
{
return m_rDriverContext.isConnected() && m_rDriverContext.isStarted();
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::uninitialize()
{
if (!m_rDriverContext.isConnected() || m_rDriverContext.isStarted()) {
return false; }
delete[] m_sample;
m_sample = nullptr;
m_callback = nullptr;
closesocket(m_client);
WSACleanup();
return true;
}
65
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::connectEncephalan()
{
WSADATA wsaData;
const int wsaret = WSAStartup(0x101, &wsaData);
if (wsaret != 0)
{
m_rDriverContext.getLogManager() << LogLevel_Error << "Error
WSAStartup (initialization windows socket api): " << WSAGetLastError() <<
"\n";
return false;
}
m_client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (m_client == INVALID_SOCKET)
{
m_rDriverContext.getLogManager() << LogLevel_Error << "Error
socket (creation a socket): " << WSAGetLastError() << "\n";
WSACleanup();
return false;
}
sockaddr_in sockaddrIn;
sockaddrIn.sin_family = AF_INET;
sockaddrIn.sin_addr.s_addr = inet_addr(m_connectionIp);
sockaddrIn.sin_port = htons(u_short(m_connectionPort));
const int connectError = connect(m_client,
reinterpret_cast<sockaddr*>(&sockaddrIn), sizeof(sockaddrIn));
if (connectError != 0)
{
m_rDriverContext.getLogManager() << LogLevel_Error << "Error
connect (connection to a specified socket): " << WSAGetLastError() << "\n";
return false;
}
return true;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::sendRequestForData() const
{
BYTE* sendDataBuffer = new BYTE;
unsigned long ID = 0x0001; //EEG_ONLY_MODE
//unsigned long ID = 0x000C; //ALL_CHANNELS_MODE
//unsigned long ID = 0x000E; //HD_CHANNELS_MODE
CopyMemory(sendDataBuffer, &ID, sizeof(ID));
if (!sendData(sendDataBuffer, sizeof(ID)))
{
m_rDriverContext.getLogManager() << LogLevel_Error << "Error
sendRequestForData: " << WSAGetLastError() << "\n";
return false;
}
m_rDriverContext.getLogManager() << LogLevel_Info <<
"sendRequestForData\n";
return true;
66
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::sendData(BYTE* data, int dataSize) const
{
if (m_client == INVALID_SOCKET) { return false; }
const long fullLen = dataSize + sizeof(int);
char* outData = new char[fullLen];
CopyMemory(&outData[0], &dataSize, sizeof(int));
CopyMemory(&outData[sizeof(int)], &data[0], dataSize);
if (send(m_client, outData, fullLen, 0) != fullLen)
{
delete[] outData;
return false;
}
delete[]outData;
return true;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::receiveData()
{
int inpSize = 0;
char* inpData = new char[sizeof(inpSize) * sizeof(BYTE)];
const int nReadSize = recv(m_client, inpData, sizeof(inpSize), 0);
if (nReadSize <= 0) { return false; }
CopyMemory(&inpSize, &inpData[0], sizeof(inpSize));
delete[]inpData;
if ((inpSize > 0) && (inpSize < 1024 * 512))
{
//unsigned long ID = 0;
inpData = new char[inpSize * sizeof(BYTE)];
if (recv(m_client, inpData, inpSize, 0) == inpSize)
{
readData(reinterpret_cast<BYTE*>(inpData), inpSize);
}
delete[]inpData;
inpData = nullptr;
}
else { return false; }
return true;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
void CDriverEncephalan::readData(BYTE* data, const int dataSize)
{
BYTE* pCurData = data;
int curDataSize = dataSize;
67
unsigned long ID = 0;
getData(pCurData, curDataSize, &ID, sizeof(ID));
switch (ID)
{
case 0x0002:// Information on research
m_rDriverContext.getLogManager() << LogLevel_Info <<
"Recieved information on research\n";
break;
case 0x00E2:// This prompted all the data including the
kilohertz
m_rDriverContext.getLogManager() << LogLevel_Info <<
"Recieved all the data including the kilohertz\n";
break;
case 0x0003:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"0x0003 data package\n";
break;
case 0x0006:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"0x0006 data package\n";
break;
case 0x0008:// We came signal data
receiveEEGData(pCurData, curDataSize);
break;
case 0x00E8:// Packet came with HD data
m_rDriverContext.getLogManager() << LogLevel_Info <<
"Packet came with HD data\n";
break;
case 0x0009:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"0x0009 data package\n";
break;
case 0x000A:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"0x000A data package\n";
break;
case 0x0101:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"0x0101 data package\n";
break;
default:
m_rDriverContext.getLogManager() << LogLevel_Info <<
"Undefined data package\n";
}
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
// Parsing package with EEG data
void CDriverEncephalan::receiveEEGData(BYTE* curData, int curDataSize)
{
int sliceNum = 0;
int pointsNumber = 0;
getData(curData, curDataSize, &sliceNum, sizeof(sliceNum));
getData(curData, curDataSize, &pointsNumber, sizeof(pointsNumber));
short* pShortData = new short[pointsNumber];
ZeroMemory(pShortData, sizeof(short)*pointsNumber);
getData(curData, curDataSize, pShortData, pointsNumber *
sizeof(short));
68
for (uint32_t iPos = 0; iPos < m_header.getChannelCount(); ++iPos)
{
float val = float(pShortData[iPos]);
CopyMemory(m_sample + (m_currentPoint + iPos *
m_sampleCountPerBlock), &val, sizeof(float));
}
m_currentPoint++;
delete[] pShortData;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
void CDriverEncephalan::getData(BYTE* & data, int& dataSize, void*
pTargetData, int targetDataSize)
{
if (dataSize < targetDataSize) { return; }
CopyMemory(pTargetData, data, targetDataSize);
data += targetDataSize;
dataSize -= targetDataSize;
}
//---------------------------------------------------------------------------
------------------------
//---------------------------------------------------------------------------
------------------------
bool CDriverEncephalan::configure()
{
// Change this line if you need to specify some references to your
driver attribute that need configuration, e.g. the connection ID.
CConfigurationEncephalan configuration(m_rDriverContext,
Directories::getDataDir() + "/applications/acquisition-server/interface-
Encephalan.ui", m_connectionPort, m_connectionIp);
if (!configuration.configure(m_header)) { return false; }
m_connectionIp = configuration.getConnectionIp();
m_settings.save();
return true;
}
//---------------------------------------------------------------------------
------------------------
#endif // TARGET_OS_Windows
69
ПРИЛОЖЕНИЕ Г
Основные положения правил оформления кода в OpenViBE
Правила именования:
Для именования любых объектов (файла, класса, переменной и т.д.)
в системе должен использоваться американский английский.
Имя должно содержать достаточно информации, чтобы понять
назначение именованного объекта.
Новые вклады должны следовать лицензии AGPL3.
Остальная информация таблица Г.1.
Таблица Г.1
Правила именования в проекте OpenViBE
Сущность Префикс Шаблон
именования
Класс С CMyClass
Структура S SMyStruct
Шаблон класса T TMyTemplateClass
Интерфейс (абстрактный класс) I IMyInterface
Перечисление (Enum) Е EMyEnum
Функция / метод Без префикса myFunction
Закрытая переменная класса /
структуры m_ m_MyVariable
Публичная переменная класса /
структуры Без префикса myClassVariable
Локальная переменная Без префикса myLocalVariable
Параметр функции / метода Без префикса myParameter
Файловая система:
Объявление класса / функции должно находиться в заголовочном
файле (.h)
70
Определение класса / функции должно находиться в файле
реализации (.cpp)
Частные заголовочные файлы (используемые в шаблонах) должны
иметь расширение .hpp
Все файлы должны быть закодированы в UTF-8
Класс и структура. Структуру необходимо использовать для пассивного
носителя данных (класс данных). Помимо конструкторов и деструкторов,
структура не должна иметь методов, которые изменяют состояние объекта.
Все члены структуры должны быть публичными. Элементы класса должны
быть private (не public и не protected).
Функции. При объявлении функции необходимо соблюдать следующий
порядок аргументов: выходные параметры, обновляемые параметры .е.
которые являются входными и выходными), входные параметры.
void doFoo(char* output, const char* input0, int input1, int input2);
Избегать использования числовых значений в коде; вместо этого
использовать символические значения (не использовать 3.14159265359 в коде,
а использовать M_PI). Если для числа не существует символического
обозначения – определить его.
71
ПРИЛОЖЕНИЕ Д
Листинг блока расчета метрики на базе графа
ovpCBoxAlgorithmCoherenceAnalysis.h
#ifndef __OpenViBEPlugins_BoxAlgorithm_CoherenceAnalysis_H__
#define __OpenViBEPlugins_BoxAlgorithm_CoherenceAnalysis_H__
//You may have to change this path to match your folder organisation
#include "../ovp_defines.h"
#include <openvibe/ov_all.h>
#include <toolkit/ovtk_all.h>
#include <fstream>
// The unique identifiers for the box and its descriptor.
// Identifier are randomly chosen by the skeleton-generator.
#define OVP_ClassId_BoxAlgorithm_CoherenceAnalysis (0x58b145c6, 0xd4b88bbb)
#define OVP_ClassId_BoxAlgorithm_CoherenceAnalysisDesc (0x1322fb72,
0xa5ec8c9a)
#define OV_AttributeId_Box_FlagIsUnstable OpenViBE::CIdentifier(0x666FFFFF,
0x666FFFFF)
namespace OpenViBEPlugins
{
namespace SignalProcessing
{
/**
* \class CBoxAlgorithmCoherenceAnalysis
* \author Alexey Minin (UrFU)
* \date Sun Feb 10 17:55:05 2019
* \brief The class CBoxAlgorithmCoherenceAnalysis describes
the box Coherence analysis.
*
*/
class CBoxAlgorithmCoherenceAnalysis : virtual public
OpenViBEToolkit::TBoxAlgorithm < OpenViBE::Plugins::IBoxAlgorithm >
{
public:
virtual void release(void) { delete this; }
virtual bool initialize(void);
virtual bool uninitialize(void);
//Here is the different process callbacks possible
// - On clock ticks :
//virtual bool processClock(OpenViBE::CMessageClock&
rMessageClock);
// - On new input received (the most common behaviour
for signal processing) :
virtual bool processInput(uint32_t ui32InputIndex);
// If you want to use processClock, you must provide
the clock frequency.
//virtual uint64_t getClockFrequency(void);
virtual bool process(void);
72
// As we do with any class in openvibe, we use the
macro below
// to associate this box to an unique identifier.
// The inheritance information is also made available,
// as we provide the superclass
OpenViBEToolkit::TBoxAlgorithm < OpenViBE::Plugins::IBoxAlgorithm >
_IsDerivedFromClass_Final_(OpenViBEToolkit::TBoxAlgorithm <
OpenViBE::Plugins::IBoxAlgorithm >,
OVP_ClassId_BoxAlgorithm_CoherenceAnalysis);
protected:
OpenViBE::Kernel::IAlgorithmProxy* m_pMatrixDecoder;
// Input decoder
OpenViBEToolkit::TStreamedMatrixDecoder <
CBoxAlgorithmCoherenceAnalysis > m_oInputConnectivityMatrixDecoder;
// Output encoder
OpenViBEToolkit::TStreamedMatrixEncoder <
CBoxAlgorithmCoherenceAnalysis> m_oOutputConnectivityValueEncoder;
// Input matrix
OpenViBE::Kernel::TParameterHandler<OpenViBE::IMatrix*>
ip_pMatrix;
// Output matrix
OpenViBE::Kernel::TParameterHandler<OpenViBE::IMatrix*>
op_pMatrix;
// Количество узлов графа (каналов ЭЭ")
uint32_t m_nodeCount = 0;
// Количество связей м/д каналами (размер буфера)
uint32_t m_connectionCount;
uint32_t checkElementCount(uint32_t ui32ElementCount);
uint32_t getConnectivityIndex(uint32_t i, uint32_t j);
uint32_t getKi(uint32_t i, OpenViBE::float64*
connectionMatrix);
OpenViBE::float64 getCwi(uint32_t i, uint32_t j,
uint32_t k, OpenViBE::float64* connectionMatrix);
std::ofstream csv;
};
/**
* \class CBoxAlgorithmCoherenceAnalysisDesc
* \author Alexey Minin (UrFU)
* \date Sun Feb 10 17:55:05 2019
* \brief Descriptor of the box Coherence analysis.
*
*/
class CBoxAlgorithmCoherenceAnalysisDesc : virtual public
OpenViBE::Plugins::IBoxAlgorithmDesc
{
public:
virtual void release(void) { }
virtual OpenViBE::CString getName(void) const
{ return OpenViBE::CString("Connectivity Analysis"); }
virtual OpenViBE::CString getAuthorName(void) const
{ return OpenViBE::CString("Alexey Minin"); }
virtual OpenViBE::CString getAuthorCompanyName(void)
const { return OpenViBE::CString("UrFU"); }
virtual OpenViBE::CString getShortDescription(void)
const { return OpenViBE::CString("Graph theoretical analysis of EEG
functional connectivity"); }
73
virtual OpenViBE::CString getDetailedDescription(void)
const { return OpenViBE::CString("Graph theoretical analysis of EEG
functional connectivity"); }
virtual OpenViBE::CString getCategory(void) const
{ return OpenViBE::CString("Signal processing/Connectivity"); }
virtual OpenViBE::CString getVersion(void) const
{ return OpenViBE::CString("0.1.1"); }
virtual OpenViBE::CString getStockItemName(void) const
{ return OpenViBE::CString("gtk-file"); }
virtual OpenViBE::CIdentifier getCreatedClass(void)
const { return OVP_ClassId_BoxAlgorithm_CoherenceAnalysis; }
virtual OpenViBE::Plugins::IPluginObject* create(void)
{ return new
OpenViBEPlugins::SignalProcessing::CBoxAlgorithmCoherenceAnalysis; }
virtual bool getBoxPrototype(
OpenViBE::Kernel::IBoxProto&
rBoxAlgorithmPrototype) const
{
rBoxAlgorithmPrototype.addInput("Connectivity
matrix", OV_TypeId_StreamedMatrix);
rBoxAlgorithmPrototype.addOutput("Connectivity
value",OV_TypeId_StreamedMatrix);
rBoxAlgorithmPrototype.addFlag(OV_AttributeId_Box_FlagIsUnstable);
return true;
}
_IsDerivedFromClass_Final_(OpenViBE::Plugins::IBoxAlgorithmDesc,
OVP_ClassId_BoxAlgorithm_CoherenceAnalysisDesc);
};
};
};
#endif // __OpenViBEPlugins_BoxAlgorithm_CoherenceAnalysis_H__
ovpCBoxAlgorithmCoherenceAnalysis.cpp
#include "ovpCBoxAlgorithmCoherenceAnalysis.h"
#include <cmath>
using namespace OpenViBE;
using namespace OpenViBE::Kernel;
using namespace OpenViBE::Plugins;
using namespace OpenViBEPlugins;
using namespace OpenViBEPlugins::SignalProcessing;
bool CBoxAlgorithmCoherenceAnalysis::initialize(void)
{
m_oInputConnectivityMatrixDecoder.initialize(*this, 0);
m_oOutputConnectivityValueEncoder.initialize(*this, 0);
ip_pMatrix = m_oInputConnectivityMatrixDecoder.getOutputMatrix();
op_pMatrix = m_oOutputConnectivityValueEncoder.getInputMatrix();
op_pMatrix->setDimensionCount(2);
op_pMatrix->setDimensionSize(0, 1);
74
op_pMatrix->setDimensionSize(1, 1);
csv.open("example.csv");
return true;
}
/
*****************************************************************************
**/
bool CBoxAlgorithmCoherenceAnalysis::uninitialize(void)
{
m_oInputConnectivityMatrixDecoder.uninitialize();
m_oOutputConnectivityValueEncoder.uninitialize();
csv.close();
return true;
}
/
*****************************************************************************
**/
bool CBoxAlgorithmCoherenceAnalysis::processInput(uint32 ui32InputIndex)
{
// some pre-processing code if needed...
// ready to process !
getBoxAlgorithmContext()->markAlgorithmAsReadyToProcess();
return true;
}
/
*****************************************************************************
**/
bool CBoxAlgorithmCoherenceAnalysis::process(void)
{
// the static box context describes the box inputs, outputs, settings
structures
const IBox& l_rStaticBoxContext = this->getStaticBoxContext();
// the dynamic box context describes the current state of the box
inputs and outputs (i.e. the chunks)
IBoxIO& l_rDynamicBoxContext = this->getDynamicBoxContext();
//iterate over all chunk on input 0
for (uint32_t i = 0; i<l_rDynamicBoxContext.getInputChunkCount(0); i+
+)
{
// decode the chunk i
m_oInputConnectivityMatrixDecoder.decode(i);
// the decoder may have decoded 3 different parts : the
header, a buffer or the end of stream.
if (m_oInputConnectivityMatrixDecoder.isHeaderReceived())
{
// Header received. This happens only once when
pressing "play". For example with a StreamedMatrix input, you now know the
dimension count, sizes, and labels of the matrix
// ... maybe do some process ...
uint32_t dimensionCount = ip_pMatrix-
>getDimensionCount();
uint32_t dimensionSize;
75
m_connectionCount = 1;
for (uint32_t d = 0; d < dimensionCount; d++) {
dimensionSize = ip_pMatrix-
>getDimensionSize(d);
m_connectionCount *= dimensionSize;
}
m_nodeCount = checkElementCount(m_connectionCount);
if (m_nodeCount < 3) {
this->getLogManager() << LogLevel_Warning <<
"Incorrect amount of connectivity measure values\n";
}
l_rDynamicBoxContext.markOutputAsReadyToSend(0,
l_rDynamicBoxContext.getInputChunkStartTime(0, i),
l_rDynamicBoxContext.getInputChunkEndTime(0, i));
}
if (m_oInputConnectivityMatrixDecoder.isBufferReceived())
{
// Если размер буфера соответсвует матрице больше чем
2х2
if (m_nodeCount > 2) {
// -начения связей
float64* l_pConnectivityMatrixBuffer =
ip_pMatrix->getBuffer();
float64* connectivityMatrix = new float64[100];
// Поиск максимума
float64 maxConnectivityValue = 0;
for (uint32_t j = 0; j < m_connectionCount; j+
+) {
if (l_pConnectivityMatrixBuffer[j] >
maxConnectivityValue) {
maxConnectivityValue =
l_pConnectivityMatrixBuffer[j];
}
}
// Установление наличия связей по пороговому
значению T и взвешивание w' = w / max
float64 T = 0.4;
while (T <= 0.8) {
for (uint32_t j = 0; j <
m_connectionCount; j++) {
if
(l_pConnectivityMatrixBuffer[j] > T) {
connectivityMatrix[j] =
l_pConnectivityMatrixBuffer[j] / maxConnectivityValue;
}
else {
connectivityMatrix[j] =
0;
}
}
// Расчет коэффициентов кластеризации
для каждого узла и интегрального для всего графа
float64 cw = 0;
for (uint32_t j = 0; j < m_nodeCount;
j++) {
uint32_t ki = getKi(j,
connectivityMatrix);
if (ki > 1) {
float64 cwi = 0;
for (uint32_t k = 0; k <
m_nodeCount; k++) {
if (j != k) {
76
for
(uint32_t m = 0; m < m_nodeCount; m++) {
if (m != j && m != k) {
cwi += getCwi(j, k, m, connectivityMatrix);
}
}
}
}
cwi = cwi / (ki * (ki -
1));
cw += cwi;
}
}
cw = cw / m_nodeCount;
csv << cw << ";";
T = T + 0.02;
}
csv << "\n";
}
}
}
return true;
}
uint32_t CBoxAlgorithmCoherenceAnalysis::checkElementCount(uint32_t
ui32ElementCount)
{
uint32 i = 1;
uint32 elementCount = ui32ElementCount;
while (elementCount > 0) {
elementCount -= i;
i++;
}
if (elementCount == 0) {
return i;
}
else {
return 0;
}
}
uint32_t CBoxAlgorithmCoherenceAnalysis::getConnectivityIndex(uint32_t i,
uint32_t j)
{
uint32_t index = 0;
uint32_t min, max;
if (i > j) {
max = i;
min = j;
}
else {
max = j;
min = i;
}
uint32_t rowLength = m_nodeCount;
for (uint32_t k = 0; k < min; k++) {
rowLength--;
index += rowLength;
}
index += max - min;
77
index--;
return index;
}
uint32_t CBoxAlgorithmCoherenceAnalysis::getKi(uint32_t i, float64*
connectionMatrix)
{
uint32_t k = 0;
for (uint32_t j = 0; j < m_nodeCount; j++) {
if (i != j) {
if (connectionMatrix[getConnectivityIndex(i, j)] > 0) {
k++;
}
}
}
return k;
}
float64 CBoxAlgorithmCoherenceAnalysis::getCwi(uint32_t i, uint32_t j,
uint32_t k, float64* connectionMatrix)
{
return pow(connectionMatrix[getConnectivityIndex(i, j)] *
connectionMatrix[getConnectivityIndex(i, k)] *
connectionMatrix[getConnectivityIndex(j, k)], 1.0 / 3);
}
78
ResearchGate has not been able to resolve any citations for this publication.
ResearchGate has not been able to resolve any references for this publication.