in progress
Инструкция по написанию профиля ресурса
1. Состав описания профиля 1.1. Профиль должен содержать описание самого профиля и описания примеров, в том числе как минимум один краткий и один полный. В кратком заполнены только обязательные атрибуты. В полном заполнены все атрибуты, по возможности правдоподобной информацией.
2. Именования 2.1. Наименование профиля пишем в формате Upper Camel Case, первое слово – код руководства, следующее – профилируемый ресурс, далее при необходимости уточнения.
2.2. Для профиля ресурса или типа данных следует привести два примера – краткий и полный.
2.3. Наименование экземпляра пишем как идентификатор, в нижнем регистре, через дефис, первые слова –– наименование артефакта, экземпляр которого приводится, затем Instance, затем Short/Full, далее при необходимости уточнения.
2.4. Наименование срезов (slice) рекомендуется формировать в формате lower camelCase, согласно рекомендациям FHIR (https://build.fhir.org/ig/HL7/fhir-shorthand/reference.html#step-2-define-the-slices))
3. Указание фиксированных значений При указании фиксированного значения, являющегося значением по справочнику, рекомендуется использовать сокращенную нотацию, указав справочник (можно псевдоним) и код по справочнику. Например:
* identifier[birthCertificate].type = $МЗРФ_Справочник_ДокументыУдостоверяющиеЛичность#6Такая запись не только короче, но позволяет не описывать набор значений, который в данном случае не используется, но формально должен быть указан при «полной» нотации:
* identifier[BirthCertificate].type
* coding 1..1
* coding from $Ядро_НаборЗначений_ДокументыУдостоверяющиеЛичность (required)
* code = #6
* system = "http://fhir.ru/core/CodeSystem/nsi-identity-document"4. Форматирование текста описания 4.1. Атрибуты верхнего уровня разделяем пустой строкой. Атрибуты следующего уровня описываем «лесенкой».
Слайсинг( Срез, Нарезка) является продвинутой, но необходимой функцией FHIR. В FSH нарезка выполняется в три этапа:
Для нарезки в FHIR требуется указать путь, тип и правила дискриминатора. Кроме того, авторы могут по желанию объявить фрагмент как упорядоченный или неупорядоченный (по умолчанию: неупорядоченный) и / или предоставить описание.
Путь дискриминатора (discriminator.path) определяет элемент, подлежащий нарезке, который обычно представляет собой элемент с несколькими элементами (массив). Примечание: Иными словами, это путь до атрибута, значение которого нужно проверять для разведения срезов. В приведенном ниже примере это Observation.component.code.
Тип дискриминатора (discriminator.type) определяет, как срезы различаются, например, по значению, шаблону, существованию срезанного элемента, типу данных срезанного элемента или соответствию профиля. Примечание: Иными словами, это критерий по которому можно разделить один срез от другого.
Существует пять различных типов:
| ТИП | ОПИСАНИЕ | КОММЕНТАРИЙ |
|---|---|---|
| value | Срезы различаются по значению. Например - срез по значению, Patient.telecom.system для значений phone, email и т.д. | Наиболее часто используемый тип дискриминатора. Чаще используется для примитивных типов элементов - code, uri. |
| exists | Срезы различаются по наличию или отсутствию указанного элемента. Например - фрагмент по шаблону Observation.code и наличию Observation.component | В основном используется в качестве дополнительного критерия нарезки. Чаще используется для сложных базовых элементов |
| pattern | Срезы различаются по значению. Например - срез по значению Observation.code, для значений LOINC-кодов 1234-5, 4235-8 | Чаще используется с элементами типа CodeableConcept, где элементы отличаются наличием определенного кода, но ожидается присутствие других кодов |
| type | Срезы различаются по типу назначенного элемента. Например - слайсинг по типу List.item.resolve() для типов Patient,RelatedPerson. | В основном используется с типами ресурсов в ссылках |
| profile | Срезы различаются по соответствию назначенного элемента указанному профилю. | Требует наибольшей обработки (> в 1000 раз по сравнению с другими). Разработчики должны использовать это только там, где это абсолютно необходимо |
Правила дискриминатора (slicing.rules):
Обратите внимание: Желательно использовать открытый режим (#open) нарезки, тем более в корневых профилях (Ru Core), чтобы разрешить последующее профилирование.
Пример: Написание слайсинга, который будет отличаться по кодам Observation.component :
* component ^slicing.discriminator.type = #pattern
* component ^slicing.discriminator.path = "code"
* component ^slicing.rules = #open
* component ^slicing.ordered = false // can be omitted, since false is the default
* component ^slicing.description = "Slice based on the component.code pattern"
Вторым шагом в нарезке является заполнение массива, который должен быть нарезан, с помощью ключевого слова contains .
* contains {name} {card} {flag(s)}
* contains
{name1} {card} {flag(s)} and
{name2} {card} {flag(s)} and
{name3} {card} {flag(s)} ...
В этом шаблоне
Имена (name, name1 и т.д.) создаются автором правила для описания фрагмента в контексте профиля. Эти имена используются для обозначения фрагмента в более поздних правилах.
По соглашению, названия фрагментов ДОЛЖНЫ быть в нижнем регистре.
Каждый фрагмент будет соответствовать типу данных массива, который он разделяет, или ограничивать его.
В частности:
Примеры: Разрежьте массив Observation.component для измерения артериального давления:
* component contains
systolicBP 1..1 MS and
diastolicBP 1..1 MSПримечание: Каждый из нарезанных фрагментов в свою очередь может быть нарезан (второй уровень нарезки).
Пример второго уровня нарезки: При наблюдении за оценкой по шкале Апгар разделите компонент оценки дыхания по шкале Апгар (respirationScore) на одно-, пяти- и десятиминутные оценки:
* component contains
appearanceScore 0..3 and
pulseScore 0..3 and
grimaceScore 0..3 and
activityScore 0..3 and
respirationScore 0..3
* component[respirationScore] contains
oneMinuteScore 0..1 and
fiveMinuteScore 0..1 and
tenMinuteScore 0..1Последним шагом является определение разграничения фрагмента. Синтаксис правила такой же, как и для ограничения любого другого элемента, но для указания пути используется синтаксис пути среза:
* [{slice name}]. {constraint} Правила разграничения ДОЛЖНЫ отображаться после правила contains, которое создает фрагменты.
Пример: Ограничить содержание срезов систолического АД и диастолического АД:
* component[systolicBP].code = $LNC#8480-6 // Систолическое артериальное давление крови
* component[systolicBP].value[x] only Quantity
* component[systolicBP].valueQuantity = $UCUM#mm[Hg] "mmHg"
* component[diastolicBP].code = $LNC#8462-4 // Диастолическое артериальное давление крови
* component[diastolicBP].value[x] only Quantity
* component[diastolicBP].valueQuantity = $UCUM#mm[Hg] "mmHg"Как минимум, каждый фрагмент ДОЛЖЕН быть ограничен таким образом, чтобы его можно было однозначно идентифицировать с помощью дискриминатора (см. Шаг 1).
Например, если путь дискриминатора указывает на элемент, являющийся CodeableConcept, и он различает по значению или шаблону, то каждый фрагмент должен ограничивать этот CodeableConcept, используя правило присваивания или правило привязки, которое однозначно отличает его от других фрагментов.
Разделите компоненты наблюдения, чтобы представить размеры опухоли:
Profile: TumorSize
Parent: Observation
Id: example-tumor-size
Title: "Tumor Size"
Description: " Значения от одного до трех измерений опухоли "
* code = $LNC#21889-1 //"Размер опухоли"
// Шаг 1 путь, тип и правила дискриминатора
* component ^slicing.discriminator.type = #pattern
* component ^slicing.discriminator.path = "code"
* component ^slicing.rules = #open
* component ^slicing.description = "Нарезка по значению component.code"
// Шаг 2 определение элементов информации в нарезке
* component contains tumorLongestDimension 1..1 and tumorOtherDimension 0..2
// Шаг 3 Определение каждого среза
* component[tumorLongestDimension] ^short = "Longest tumor dimension"
* component[tumorLongestDimension] ^definition = " Наибольшее измерение опухоли в см или мм"
* component[tumorLongestDimension].code = $LNC#33728-7 // "Size.maximum измерения опухоли"
* component[tumorLongestDimension].value[x] only Quantity
* component[tumorLongestDimension].valueQuantity from TumorSizeUnitsVS (required) // value set defined elsewhere
* component[tumorOtherDimension] ^short = "Other tumor dimension(s)"
* component[tumorOtherDimension] ^definition = "Последующее измерение опухоли в см или мм "
* component[tumorOtherDimension] ^comment = "Additional tumor dimensions should be ordered from largest to smallest."
* component[tumorOtherDimension].code = $LNC#33729-5 // " Дополнительное измерение опухоли "
* component[tumorOtherDimension].value[x] only Quantity
* component[tumorOtherDimension].valueQuantity from TumorSizeUnitsVS (required)