Перейти к содержимому

Аналитические заметки для качественного кодирования

Заметки в Potato прикрепляются к объекту, фрагменту текста или нарисованной фигуре и принимают ответы. Заметка, поднятая как вопрос, остаётся открытой, пока вопрос не решат.

Заметки (мемо) в Potato — это записи в свободной форме, прикреплённые к объекту, к выделенному фрагменту текста внутри объекта или к фигуре, нарисованной на изображении. Любой пользователь, который может прочитать заметку, может на эту заметку ответить, а заметка, поднятая как вопрос (issue), остаётся открытой, пока автор, назначенный исполнитель или арбитр не решит этот вопрос. Заметки работают в любом проекте Potato, с QDA Mode или без него, и Potato хранит заметки в базе данных проекта, а не в файлах разметки. Заметки появились в Potato 2.6.0, а ответы и вопросы появились в 2.12.0.

Аналитическая заметка — это запись, которую исследователь делает во время кодирования о данных и кодах, например почему код подходит к фрагменту или где кодбуку нужно новое правило. Написание заметок чаще всего описывают как часть обоснованной теории (grounded theory), а Birks, Chapman и Francis (2008) рекомендуют вести заметки в любых качественных методах. По описанию этих авторов, заметки помогают аналитику перейти от сырых данных к абстракциям, которые эти данные объясняют. В команде кодировщиков заметки ещё и фиксируют решения, стоящие за кодами, а описанный ниже экспорт превращает эти записи в журнал аудита.

Каждая заметка записывает следующее:

  • Привязка. Заметка относится ко всему объекту, к диапазону символов в тексте объекта (показывается со значком quote) или к одной нарисованной фигуре (показывается с меткой и типом фигуры, например car box).
  • Видимость. Заметка бывает private (по умолчанию) или shared.
  • Ветка. Ответы располагаются под первой записью и наследуют видимость первой записи.
  • Статус вопроса. Вопрос бывает open или resolved, может иметь одного назначенного исполнителя и записывает, кто и когда решил вопрос.
  • Хранение. Заметка сохраняется сразу после нажатия Add note в таблицах memos и memo_threads файла <task_dir>/project.sqlite.

Включение заметок

В обычном проекте заметки выключены, а в QDA Mode и Solo Mode включены по умолчанию. Проект включает заметки блоком annotation_ui. Конфигурация ниже настраивает команду, которая кодирует фрагменты интервью схемой span, с приватными заметками. Блок adjudication назначает ведущего аналитика, а арбитр может читать любую заметку в проекте:

yaml
annotation_task_name: Clinic access interviews
task_dir: .
output_annotation_dir: annotation_output/
data_files:
- data/excerpts.json
item_properties:
  id_key: id
  text_key: text
 
annotation_ui:
  memos: true
  visibility: private
 
adjudication:
  enabled: true
  adjudicator_users: [lead_analyst]
 
annotation_schemes:
- annotation_type: span
  name: codes
  description: Highlight a passage and apply a code
  labels: [transport barriers, cost concerns, provider trust]

Схема span важна для экспорта, потому что отчёту с цитатами нужна схема span (см. Экспорт заметок). Заметками управляют четыре ключа:

ПараметрПо умолчаниюОписание
annotation_ui.memosВыключено; включено, когда qda_mode.enabled или solo_mode.enabled равно trueПоказывает панель Notes и включает эндпоинты /api/memos. Явное true или false переопределяет QDA Mode и Solo Mode.
annotation_ui.visibilityprivateВидимость заметки, созданной через API без поля visibility. Любое значение, кроме private или shared, сводится к private.
qda_mode.memos.show_sidebar_by_defaulttrueВ QDA Mode открывает панель Notes на каждом объекте, пока разметчик не закроет панель.
qda_mode.memos.enabledtrueВ QDA Mode значение false оставляет панель Notes закрытой при старте. Заметки остаются доступны; выключает заметки ключ annotation_ui.memos: false.

Вне QDA Mode панель Notes при старте закрыта, и разметчики открывают панель кнопкой Notes у правого края страницы. Если закрыть панель, она остаётся закрытой на следующих объектах до конца сеанса этой вкладки браузера. Когда заметки выключены, Potato не показывает кнопку Notes, а эндпоинты /api/memos возвращают 503. Меню видимости в редакторе заметки в любом проекте начинается с Private, и annotation_ui.visibility это меню не меняет. Команда, которой нужны общие заметки, просит кодировщиков выбирать Shared для каждой новой заметки.

Potato хранит каждую заметку под значением annotation_task_name проекта. Если переименовать задачу в конфигурации, заметки, написанные под старым именем, скрываются. Записи остаются в project.sqlite, и возврат старого имени возвращает заметки.

Как написать заметку в панели Notes

Панель Notes показывает заметки к текущему объекту, от старых к новым, с ответами каждой ветки под первой записью. Чтобы добавить заметку:

  1. Нажмите Notes у правого края страницы разметки.
  2. Чтобы привязать заметку к фрагменту, сначала выделите текст в объекте и отметьте Attach to selected text. Чтобы привязать заметку к нарисованной фигуре, выберите фигуру на холсте изображения и отметьте Attach to the selected shape.
  3. Введите текст заметки в редакторе.
  4. Чтобы поднять заметку как вопрос, отметьте Raise as an issue to resolve. При желании введите в поле Assign to имя пользователя, который должен решить вопрос.
  5. Выберите Private или Shared в разделе Visibility и нажмите Add note.

У каждой заметки видны только те кнопки, которые доступны текущему пользователю. Reply есть у каждой ветки, Resolve или Reopen и Assign есть у вопросов, которые пользователь может менять, а Edit и Delete есть у собственных заметок пользователя. Арбитр также видит Delete у заметок других пользователей. При редактировании первой записи можно изменить не только текст, но и видимость записи.

Текстовая привязка записывает начальное и конечное смещения выделения в символах внутри отображаемого текста объекта, причём конечное смещение не включается. Учитываются только выделения внутри основного текстового блока объекта. Привязка к фигуре записывает схему, тип, метку и нормализованные координаты фигуры, потому что у нарисованных фигур нет сохранённого ID. Щелчок по значку фигуры на заметке снова выделяет фигуру, сопоставляя сохранённые координаты. Если фигуру с тех пор передвинули или удалили, панель сообщает, что фигуры больше нет на изображении в том виде, в каком её нарисовали.

Кто может читать заметку

Приватную заметку могут читать автор и арбитры. Общую заметку может читать любой пользователь проекта. Назначенный исполнитель вопроса может читать ветку вопроса и отвечать в ней, даже если вопрос приватный. Остальные правила для заметок такие:

  • Текст и видимость заметки редактирует только автор.
  • Удаляет заметку автор или арбитр. Удаление первой записи ветки удаляет и ответы.
  • Отвечать может любой, кто может читать ветку. Ответ наследует видимость первой записи, и последующее изменение видимости первой записи распространяется и на ответы.
  • Для заметки, которую пользователь не может читать, любое действие возвращает 404. Potato даёт тот же ответ для заметки, которой не существует.

Для заметок арбитр — это имя пользователя из списка adjudication.adjudicator_users при adjudication.enabled, равном true. Для заметок Potato проверяет только этот список. Пользователь с ролью RBAC admin, которого нет в списке, читает те же заметки, что и любой разметчик.

Приватные заметки приватны только внутри интерфейса разметки. Любой, кто запускает экспорт отчёта с цитатами или открывает project.sqlite, читает все заметки, включая приватные. Расскажите кодировщикам об этом экспорте до начала кодирования.

Общие заметки позволяют кодировщикам читать рассуждения друг друга во время кодирования. Когда два кодировщика независимо кодируют одни и те же фрагменты для проверки надёжности между кодировщиками, общие заметки могут задать якорь для суждений второго кодировщика и поднять согласованность по причинам, не связанным с кодбуком. Держите заметки приватными во время раунда проверки надёжности. После раунда кодировщик может открыть каждую приватную заметку через Edit и переключить заметку на Shared для встречи по согласованию.

Ответы и вопросы

Каждая заметка открывает ветку. У ответа нет собственной видимости или статуса, отдельных от первой записи. Отметка Raise as an issue to resolve даёт первой записи статус open. Вопросы подходят для того, на что нужен ответ, прежде чем кодирование пойдёт дальше, например для границы кода, которую кодбук не определяет. Права для вопросов такие:

ДействиеКто может выполнить действие
ОтветитьЛюбой, кто может читать ветку
Решить вопрос или открыть его сноваАвтор вопроса, назначенный исполнитель или арбитр
Назначить исполнителя или снять назначениеАвтор вопроса или арбитр

Решение вопроса записывает, кто и когда его решил, а повторное открытие очищает оба поля. Снятие назначения лишает исполнителя доступа к приватному вопросу. Когда разметчику назначены открытые вопросы, кнопка Notes показывает их число, например Notes · 2 assigned to you, а панель выводит эти вопросы вверху. Вопрос к объекту из собственной очереди разметчика получает кнопку Go to item, а вопрос к объекту вне очереди помечается как не входящий в очередь. Настройка jumping_to_id_disabled: true убирает кнопки Go to item.

Чтобы отправлять назначения в чат или трекер задач, подпишите вебхук на событие memo.issue_assigned. Событие срабатывает каждый раз, когда у вопроса появляется новый исполнитель, и передаёт ID заметки, ID объекта, исполнителя, пользователя, назначившего вопрос, и статус. Полезная нагрузка не содержит текста заметки, потому что вопрос может быть приватным.

Вопросы в админ-панели

Когда заметки включены, вкладка Overview админ-панели показывает плитку Open issues с числом открытых и числом решённых вопросов. Админ-API выдаёт сами вопросы, включая приватные:

bash
curl -H "X-API-Key: $POTATO_ADMIN_KEY" \
  "http://localhost:8000/admin/api/memo_issues?status=open"

Ответ содержит по одной записи на вопрос, от новых к старым, с текстом заметки, автором, ID объекта, привязкой, исполнителем, статусом и тем, кто решил вопрос. Используйте ?status=resolved для решённых вопросов или опустите параметр, чтобы получить и те и другие. Эндпоинт выдаёт только вопросы. Обычные заметки доходят до руководителя проекта через экспорт или через учётную запись арбитра.

Экспорт заметок

Экспортёр quotation_report пишет по одной строке CSV на каждый закодированный спан. С include_memos=true экспортёр добавляет по строке на каждую заметку и каждый ответ:

bash
python -m potato.export -c config.yaml -f quotation_report \
  --option include_memos=true -o ./export/

Команда записывает ./export/quotations.csv. Строки заметок используют те же девять столбцов, что и строки спанов:

СтолбецЗначение в строке заметки
schema(memo), (memo reply), (issue: open) или (issue: resolved)
codeВидимость ветки, private или shared
textТекст заметки
start, endСмещения в символах для текстовой привязки, иначе пусто
fieldtext для текстовой привязки, иначе пусто
instance_idОбъект, к которому относится заметка
source_docПервые 200 символов текста объекта
coderАвтор заметки

Экспортёр работает, только если в конфигурации есть хотя бы одна схема span. Исследование, закодированное только вопросами radio или multiselect, получает ошибку No span annotation schema found in config. В строке заметки также нет ни отметки времени, ни исполнителя, а заметка, привязанная к фигуре, экспортируется с пустыми смещениями.

Для журнала аудита с датами запрашивайте две таблицы заметок напрямую. Команда sqlite3 ниже выводит все заметки проекта с временем создания в UTC, статусом ветки, исполнителем и тем, кто решил вопрос:

bash
sqlite3 -header -csv project.sqlite "
  SELECT m.instance_id, m.created_by, datetime(m.created_at, 'unixepoch') AS created,
         m.visibility, t.parent_id, t.status, t.assignee, t.resolved_by, m.body
  FROM memos m LEFT JOIN memo_threads t ON t.memo_id = m.id
  WHERE m.project = 'Clinic access interviews'
  ORDER BY m.created_at" > memos.csv

Непустой parent_id обозначает ответ и указывает первую запись ветки. Potato хранит время в секундах Unix, и resolved_at и updated_at преобразуются так же, как created_at.

Заметки не попадают в экспорт REFI-QDA .qdpx. Когда в конфигурации задано annotation_ui.memos: true, экспортёр .qdpx предупреждает, что заметки не включены. В QDA Mode или Solo Mode без этого ключа экспорт пропускает заметки без предупреждения. Когда проект переезжает в другую программу QDA, экспортируйте заметки отдельно через отчёт с цитатами.

Архив, который собирает potato snapshot create, содержит project.sqlite, и архив из potato deploy pull тоже содержит этот файл. Поэтому в обоих архивах лежат все заметки, включая приватные. Хеш содержимого снимка охватывает конфигурацию, файлы исследования и разметку. Хеш не учитывает базы данных, и новая заметка хеш не меняет. См. Снимки проекта.

API заметок

Панель Notes использует REST API по адресу /api/memos с аутентификацией через сеанс входа разметчика. Скрипты могут вызывать те же эндпоинты:

ЗапросНазначение
GET /api/memos?instance_id=<id>Заметки и ответы к одному объекту, которые пользователь может читать, каждая с can_edit, can_delete, can_resolve и can_assign
POST /api/memosНовая заметка из instance_id, body, visibility и anchor, а для вопроса ещё issue: true и необязательный assignee
POST /api/memos/<id>/replyОтвет с body
PATCH /api/memos/<id>Изменение body, visibility, status (open или resolved) или assignee (пусто, чтобы снять)
DELETE /api/memos/<id>Удаление заметки вместе с ответами, если заметка является первой записью
GET /api/memos/issues?status=open&assignee=meВопросы по всему проекту, которые пользователь может читать

Текстовая привязка выглядит как {"start": 48, "end": 98, "field": "text"}, а привязка к фигуре — как {"shape": {"schema": ..., "type": ..., "label": ..., "coordinates": ...}}. Запрос POST с ID объекта, которого нет в проекте, возвращает 400.

Пример

В репозитории Potato есть пример с заметками. Запустите пример из клона Potato:

bash
python potato/flask_server.py start examples/advanced/memos-example/config.yaml -p 8000

Пример включает приватные заметки для четырёх коротких отзывов о товарах с одним вопросом о тональности. В примере нет схемы span, и отчёт с цитатами не может экспортировать заметки этого примера. Пример QDA Mode содержит схему span на основе кодбука. Чтобы попробовать экспорт, запустите examples/advanced/qda-mode-example/config.yaml.

Что почитать дальше

Подробности реализации см. в исходной документации.

Источники

Birks, M., Chapman, Y., and Francis, K. (2008). Memoing in qualitative research: Probing data and processes. Journal of Research in Nursing, 13(1), 68–75. doi:10.1177/1744987107081254