0 关注者 · 25 帖子

Health Level-7 或 HL7 是指在不同医疗健康提供商使用的软件应用程序之间传输临床和管理数据的一套国际标准

了解更多信息

文章 Kelly Huang · 十月 23, 2025 21m read

概述

快捷式医疗服务互操作资源 (FHIR) 是一个由 HL7 International 开发的标准化框架,旨在以灵活、对开发者友好且现代的方式促进医疗数据的交换。 它利用现代网络技术来确保在医疗保健系统间实现无缝集成与通信。

关键 FHIR 技术

  • 用于资源交互的 RESTful API
  • 用于数据表示的 JSON 和 XML
  • 用于安全授权和身份验证的 OAuth2

FHIR 围绕着称为资源的模块化组件构建,每个组件代表特定的医疗保健概念,包括:

  • 患者 – 受众特征和标识符
  • 观察数据 – 临床测量数据(例如,生命体征、实验室检测结果)
  • 诊疗 – 患者与医疗服务提供者的互动
  • 药物、过敏不耐受、健康状况等

资源单独定义,并且可以引用其他资源,以构成一个完善的数据模型。


InterSystems IRIS for Health:FHIR 支持

InterSystems IRIS for Health 是一个专为医疗保健行业设计的统一数据平台。 它包含对 HL7 FHIR 的原生支持。 它提供内置工具与服务,能够实现 FHIR 资源的存储、检索、转换和交换。IRIS 通过三大 FHIR 处理组件提升系统的互操作性:

1.FHIR 仓库服务器

IRIS 可以快速部署符合 FHIR 标准的服务器,并支持以下功能:

  • 完整的 FHIR 范式
  • 实现 FHIR RESTful API,包括搜索和查询参数
  • 导入并利用 FHIR 软件包和结构定义
  • 使用 FHIR 配置文件
  • 对 FHIR 资源进行原生 CRUD 操作
  • 以 JSON 或 XML 格式检索 FHIR 数据
  • 支持多种 FHIR 版本
  • FHIR SQL Builder 和批量 FHIR 处理功能

2. FHIR 装饰层

FHIR 装饰层是用于在现有架构(通常为非 FHIR 架构)之上提供符合 FHIR 标准的 API 接口的软件架构模式。 它还能简化医疗保健数据系统,包括电子健康记录系统 (EHR)、旧版数据库或 HL7 v2 消息存储库,无需将所有数据迁移到 FHIR 原生系统中。

此实现专门围绕 FHIR Interoperability Adapter 展开。

3. FHIR Interoperability Adapter

InterSystems IRIS for Health 具备高度灵活性和精细控制能力,可以实现 HL7 V2.x、C-CDA 等医疗消息标准与 FHIR 之间的双向转换​​(参见“消息转换示意图”)。 不过,部分 FHIR 实现需要使用专用的 FHIR 仓库服务器。 为支持此类场景,InterSystems IRIS for Health 内置了一套互操作性适配器工具包,无需使用 FHIR 服务器即可实现详细的消息转换。

此适配器能够处理来自外部系统的各种外部请求(例如, REST 或 SOAP API 请求),将这些请求转换为 FHIR 格式,然后路由到下游系统,且无需将数据持久存储在数据库中。

如有需要,该适配器也可以对数据进行转换并将其存储在数据库中。

它能有效提供外部接口层,使非 FHIR 数据库可以像 FHIR 服务器一样运行,从而实现无缝互操作性。

消息转换

SDA:摘要文档架构

摘要文档架构 (SDA) 是 InterSystems 推出的基于 XML 的中间格式,用于在 IRIS 和 HealthShare 产品内部表示患者数据。 利用这种功能强大的原生数据结构,您可以访问离散数据,并轻松实现多种数据格式之间的转换,包括 HL7 V2、CCDA、C32、HL7 FHIR 等。

SDA 结构

SDA(结构化数据架构)主要分为两个组成部分:

  1. 容器 – 包含一个或多个部分的顶层结构
  2. 部分 – 特定医疗元素(例如,患者、诊疗、过敏不耐受)的表示

容器

容器是 SDA 标准的顶层结构,其中包含多个部分(例如,患者、诊疗、过敏不耐受等)。

我们来深入探讨一下 SDA 的内部结构及其组成部分。

容器的类定义:

HS.SDA3.Container 类作为表示 SDA 文档的主要定义。 各个部分(如患者、诊疗)均定义为对象,并作为属性包含在此 class.Sections 中。

“部分”是指容器元素的独立片段,它以 IRIS 类定义的形式表示,并包含容器上的相关数据元素。

  1. 患者 – HS.SDA3.Patient
  2. 诊疗 – HS.SDA3.Encounter
  3. 过敏症 - HS.SDA3.Allergy

SDA 容器结构

以下 XML 结构表示整个 SDA 容器。

<Container><Patient/><Encounters/><Encounters/><AdvanceDirectives/></Container>

 

SDA 数据类型

FHIR 数据类型格式与 IRIS 标准数据类型不同。 因此,SDA 具有特定的自定义数据类型,与 %String、%Integer、%Stream 等标准属性相比,这些数据类型可以更有效地处理部分中的属性。 不过,标准属性也用于 SDA 部分中。

相应数据类型类也在 HS.SDA3* 软件包中定义:

  • HS.SDA3.Name
  • HS.SDA3.CodeTableDetail.Allergy
  • HS.SDA3.PatientNumber
  • HS.SDA3.TimeStamp

SDA 扩展

大多数情况下,SDA 具有充足的属性来管理和生成系统中传输的所有数据,以开发资源。 不过,如果您需要在实现过程中加入额外的数据,IRIS 提供了一种简单直接的方式可以帮助您轻松地将相应数据扩展到 SDA 扩展类中。

例如,HS.Local.SDA3.AllergyExtension 类定义是 HS.SDA3.Allergy 的扩展类。 您可以向此扩展类添加必要的数据元素,从而简化整个实现过程中的访问和操作流程。

下一步是创建容器对象。


创建容器对象

ClassMethod CreateSDAContainer()
{
<span class="hljs-keyword">set</span> SDAContainer = <span class="hljs-keyword">##class</span>(HS.SDA3.Container).<span class="hljs-built_in">%New</span>()

#<span class="hljs-comment">; create patient object</span>
<span class="hljs-keyword">set</span> patientSDA = <span class="hljs-keyword">##class</span>(HS.SDA3.Patient).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> patientSDA.Name.FamilyName = <span class="hljs-string">"stood"</span>
<span class="hljs-keyword">set</span> patientSDA.Name.GivenName = <span class="hljs-string">"test"</span>
<span class="hljs-keyword">set</span> patientSDA.Gender.Code=<span class="hljs-string">"male"</span>
<span class="hljs-keyword">set</span> patientSDA.Gender.Description=<span class="hljs-string">"birth gender"</span>
#<span class="hljs-comment">; create Encounter 1</span>
<span class="hljs-keyword">set</span> encounterSDA  = <span class="hljs-keyword">##class</span>(HS.SDA3.Encounter).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> encounterSDA.AccountNumber = <span class="hljs-number">12109979</span>
<span class="hljs-keyword">set</span> encounterSDA.ActionCode =<span class="hljs-string">"E"</span>
<span class="hljs-keyword">set</span> encounterSDA.AdmitReason.Code =<span class="hljs-string">"Health Concern"</span>
<span class="hljs-keyword">set</span> encounterSDA.AdmitReason.Description = <span class="hljs-string">"general health concern"</span>
#<span class="hljs-comment">; create Encounter 2</span>
<span class="hljs-keyword">set</span> encounterSDA1  = <span class="hljs-keyword">##class</span>(HS.SDA3.Encounter).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> encounterSDA1.AccountNumber = <span class="hljs-number">95856584</span>
<span class="hljs-keyword">set</span> encounterSDA1.ActionCode =<span class="hljs-string">"D"</span>
<span class="hljs-keyword">set</span> encounterSDA1.AdmitReason.Code =<span class="hljs-string">"reegular checkup"</span>
<span class="hljs-keyword">set</span> encounterSDA1.AdmitReason.Description = <span class="hljs-string">"general health ckeckup"</span>
#<span class="hljs-comment">; set the patientSDA into the container.</span>
<span class="hljs-keyword">set</span> SDAContainer.Patient = patientSDA

#<span class="hljs-comment">; set multiple encounters into the container SDA</span>
<span class="hljs-keyword">do</span> SDAContainer.Encounters.Insert(encounterSDA)
<span class="hljs-keyword">do</span> SDAContainer.Encounters.Insert(encounterSDA1)

#<span class="hljs-comment">; convert the SDA object into an XML string.</span>
<span class="hljs-keyword">do</span> SDAContainer.XMLExportToString(.containerString)
<span class="hljs-keyword">write</span> containerString

}


SDA – XML 文档输出

<Container><Patient><Name><FamilyName>stood</FamilyName><GivenName>test</GivenName></Name><Gender><Code>male</Code><Description>birth gender</Description></Gender></Patient><Encounters><Encounter><AccountNumber>12109979</AccountNumber><AdmitReason><Code>Health Concern</Code><Description>general health concern</Description></AdmitReason><ActionCode>E</ActionCode></Encounter><Encounter><AccountNumber>95856584</AccountNumber><AdmitReason><Code>reegular checkup</Code><Description>general health ckeckup</Description></AdmitReason><ActionCode>D</ActionCode></Encounter></Encounters><UpdateECRDemographics>true</UpdateECRDemographics></Container>

 在上一节中,我们探讨了 SDA 及其组成部分。 我们还学习了如何通过 Cache ObjectScript 生成 SDA。

接下来,我们将使用互操作性生产(之前称为 Ensemble)生成 FHIR 资源或捆绑包。

在创建 FHIR 资源之前,我们来简单了解一下互操作性生产。

带 FHIR 适配器的互操作性生产

互操作性生产是一个集成框架,用于连接系统和开发应用程序,以轻松实现互操作性。 它通常分为 3 大组成部分:

  1. 业务服务 – 连接到外部系统,并接收外部系统发出的请求。
  2. 业务流程 – 接收其他业务主机发出的请求、根据您定义的业务逻辑处理请求,并转换相关数据。 会使用多个组件进行数据转换:
    1. BPL – 业务流程语言
    2. DTL – 数据转换语言
    3. BR – 业务规则
    4. 记录映射
  3. 业务操作 – 与外部系统相连,并向外部系统发送响应。

首先,我们来构建 FHIR 消息。

创建 FHIR 资源

存在两种类型的系统:FHIR 服务器和非 FHIR 服务器。 在我们的案例中,我们的目标是使用 FHIR Interoperability Adapter 生成 FHIR 资源,将非 FHIR 的InterSystems IRIS 数据库表示为符合 FHIR 标准的系统。

在本节中,我们将演示如何借助带 FHIR 适配器的 InterSystems IRIS for Health 互操作性工具包,通过存储在 IRIS 数据库中的自定义数据生成 FHIR 资源。

在此实现过程中,我们将创建以下类型的 FHIR 资源:

  1. 标准 FHIR 资源 – 使用内置的 FHIR 类,进行少量修改或不做修改。
  2. 自定义 FHIR 资源 – 涉及向 SDA 模型添加扩展,以及为 FHIR 资源创建自定义数据转换 (DTL)。

每个实现都将通过专用的业务主机启动。

业务服务

RESTful 业务主机负责接收外部系统发出的请求。 您可以根据特定集成要求(例如,HTTP、SOAP 或其他受支持的协议)配置合适的适配器。

接收到外部系统发送的请求后,工作流将立即使用自定义或旧版数据库中持久存储的数据生成相应的 FHIR 资源。

FHIR 业务流程

FHIR 消息生成流程主要包括两个步骤:

  1. 将自定义/专有数据转换为 SDA(将 HL7 版本 2.X 转换为 SDA,将 CCDA 转换为 SDA,等等)。
  2. 将数据元素添加到 SDA,如有需要,创建自定义 DTL。 以下步骤为可选步骤,是否执行取决于具体实现需求,例如自定义 FHIR 资源生成。
  3. 然后,借助 IRIS 内置流程将生成的 SDA 转换为 FHIR 资源。

结构化数据架构 (SDA) 格式充当中介,可以实现灵活的数据转换。 数据以 SDA 格式提供后,即可轻松映射到 FHIR 或其他医疗保健数据标准。

将自定义/专有数据转换为 SDA 格式
使用这种方式时,先创建持久或互操作性请求类,以便转换为 SDA 格式。 此过程涉及定义自定义患者类,用于将您的旧版或自定义数据库结构中的数据映射为符合 SDA 标准的对象。

利用自定义患者类可以提供极高的灵活性:

  • 简化对象处理和操作流程。
  • 以数据转换语言 (DTL) 实现清晰映射。
  • 轻松重用其他转换或业务逻辑层中的对象。

请求外部层的类以转换 SDA:

Class Samples.FHIRAdapt.CustomStorage.Patient Extends (Ens.Request,%JSON.Adaptor)
{
Property Name As%String;Property BirthDate As%String;Property Citizenship As%String;Property Religion As%String;Property PrimaryLanguage As%String;Property Married As%String;Property MRN As%String;
}

 

此请求类作为外部接口层,启动从您的数据库格式转换为 SDA 的流程。 SDA 对象创建完毕后,可以通过标准或自定义 DTL 映射无缝转换为所需 FHIR 资源:

  1. 添加 Samples.FHIRAdapt.CustomStorage.Patient(使用您的类定义)类作为转换的源类。
  2. 确定并选择适合映射的 SDA 目标类。 在本例中,HS.SDA3.Patient 是适合将自定义数据转换为 SDA 格式的类。

DTL 转换示例

Class Samples.FHIRAdapt.DTL.CustomDataToPatientSDA Extends Ens.DataTransformDTL [ DependsOn = (Samples.FHIRAdapt.CustomStorage.Patient, HS.SDA3.Patient) ]
{

Parameter IGNOREMISSINGSOURCE = 1;Parameter REPORTERRORS = 1;Parameter TREATEMPTYREPEATINGFIELDASNULL = 0; XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ] { <transform sourceClass='Samples.FHIRAdapt.CustomStorage.Patient' targetClass='HS.SDA3.Patient' create='new' language='objectscript' > <assign value='$Piece(source.Name,",")' property='target.Name.GivenName' action='set' /> <assign value='$Piece(source.Name,",")' property='target.Name.FamilyName' action='set' /> <assign value='$Piece($Piece(source.Name,",",2)," ",2)' property='target.Name.MiddleName' action='set' /> <assign value='source.Citizenship' property='target.Citizenship' action='set' /> <assign value='"fullname"' property='target.Name.Type' action='set' /> <assign value='$Select(source.Married=1:"married",1:"single")' property='target.MaritalStatus.Code' action='set' /> </transform> }

}

在这一阶段,数据已成功转换为 SDA 文档,并准备好转换为 FHIR 资源。

在生成 FHIR 资源之前,应创建额外的支持 FHIR 资源作为此响应的组成部分。 此外,还需要在 FHIR 输出中包含自定义字段。 要支持这些自定义元素,必须将相应的属性纳入 SDA 结构。

此操作可以借助 SDA 扩展完成,SDA 扩展可以将准确、完整地生成 FHIR 资源所需的自定义数据元素包含在 SDA 结构中。

SDA 扩展

FHIR 遵循 80/20 法则,即核心 FHIR 规范负责处理约 80% 的常见医疗保健用例,而剩余的 20% 则通过自定义约束和扩展来解决。

为说明这一点,我们将使用自定义扩展创建一个 AllergyIntolerance 资源。

在 InterSystems IRIS 中正确实现扩展数据元素需要执行两个关键步骤:

  1. HS.SDA3.*******Extension 用于将额外的数据元素添加到各个 SDA 部分。 例如,类 HS.Local.SDA3.AllergyExtension 通过定义所需自定义属性对 HS.SDA3.Allergy 进行扩展。
  2. 由于预构建的 DTL 映射不包含这些自定义扩展,必须创建自定义 DTL 来相应地转换处理。

Allergy 扩展类

要在用于创建所需过敏症资源的 HS.Local.SDA3.AllergyExtension 类中构建所需字段,请使用以下代码行:

Class HS.Local.SDA3.AllergyExtension Extends HS.SDA3.DataType
{

Parameter STREAMLETCLASS = "HS.SDA3.Streamlet.Allergy";/// Mapped this property due to not being available in the SDA to FHIR conversionProperty Criticality As%String;/// Mapped this property due to not being available in the SDA to FHIR conversionProperty Type As%String(MAXLEN = ""); Storage Default { <Data name="AllergyExtensionState"> <Subscript>"AllergyExtension"</Subscript> <Value name="1"> <Value>Criticality</Value> </Value> <Value name="2"> <Value>Type</Value> </Value> </Data> <State>AllergyExtensionState</State> <Type>%Storage.Serial</Type> }

}

创建扩展只是完成了整个流程的一半,因为标准 DTL 未提供扩展字段的映射。 现在,我们需要构建自定义 DTL,以正确转换 FHIR 响应。


自定义 DTL 创建

在自定义 DTL 类之前,您需要为所有自定义 DTL 实现定义专用软件包。 为此,InterSystems 建议使用名为 HS.Local.FHIR.DTL 的软件包。

要为 Allergy 构建自定义 DTL,请先从现有的数据转换类
HS.FHIR.DTL.SDA3.vR4.Allergy.AllergyIntolerance 开始,该类用于处理从 SDA 到 FHIR 资源的转换。

首先,将此类复制到自定义包中,将其命名为

HS.Local.FHIR.DTL.SDA3.vR4.Allergy.AllergyIntolerance. 然后,将自定义扩展映射到 FHIR 资源生成流程中,以对其进行扩展。

例如,示例类 HS.Local.FHIR.DTL.FromSDA.Allergy 说明了如何便捷地映射 Allergy 扩展字段,同时从基类 HS.FHIR.DTL.SDA3.vR4.Allergy.AllergyIntolerance 继承所有其他映射。

示例自定义 DTL 映射如下图所示:

/// Transforms SDA3 HS.SDA3.Allergy to vR4 AllergyIntoleranceClass HS.Local.FHIR.DTL.SDA3.vR4.Allergy.AllergyIntolerance Extends Ens.DataTransformDTL [ DependsOn = (HS.SDA3.Allergy, HS.FHIR.DTL.vR4.Model.Resource.AllergyIntolerance), ProcedureBlock ]
{

XData DTL [ XMLNamespace = "http://www.intersystems.com/dtl" ] { <transform sourceClass='HS.SDA3.Allergy' targetClass='HS.FHIR.DTL.vR4.Model.Resource.AllergyIntolerance' create='existing' language='objectscript' > <assign value='source.Extension.Criticality' property='target.criticality' action='set' /> <assign value='source.Extension.Type' property='target.type' action='set' > <annotation>11/07/2023; ak; Added this set to populate type in AllergyIntolerance resource</annotation> </assign> </transform> }

}

为自定义 DTL 创建类软件包后(在自定义 DTL 软件包不存在的情况下),必须进行注册,以获得今后的 FHIR 数据转换结果。

set status = ##class(HS.FHIR.DTL.Util.API.ExecDefinition).SetCustomDTLPackage("HS.Local.FHIR.DTL")

 此外,您还可以通过调用类方法获取自定义 DTL 软件包详细信息(如果已定义)。

Write ##class(HS.FHIR.DTL.Util.API.ExecDefinition).GetCustomDTLPackage()


请求消息的流容器类

SDA 及其可选 SDA 扩展的设置,以及构建 SDA 的可选自定义 DTL 创建过程现已完成。 不过,现在必须将 SDA 对象转换为标准化的 Ens.StreamContainer,该容器专门用于 SDA 到 FHIR 的转换业务流程。

下面的简单步骤可以将 SDA 对象转换为 Ens.StreamContainer。

ClassMethod CreateEnsStreamContainer()
{
	set ensStreamCntr=""try {
        #; refer the CreateSDAContainer() method above#dim SDAContainer As HS.SDA3.Container = ..CreateSDAContainer()
		do SDAContainer.XMLExportToStream(.stream)
		#; Create Ens.StreamContainer is the default format for processing the SDA to FHIR processSet ensStreamCntr = ##class(Ens.StreamContainer).%New(stream)
	}
	catch ex {
		Write ex.DisplayString()
		set ensStreamCntr=""
	}
	return ensStreamCntr
}

 创建 SDA 的第一阶段已完成。 第二阶段(即生成 FHIR 资源)已由 InterSystems IRIS 处理。

下文介绍如何将 SDA 文档转换为 FHIR 资源。


SDA 转换为 FHIR

针对 FHIR 创建配置互操作性业务主机

生成 FHIR 的业务逻辑已完成。 现在,我们来配置互操作性生产设置:

  1. 设置入站服务,以接收外部系统发出的请求。
  2. 业务流程 – 这是创建 FHIR 资源的关键步骤。

业务流程实现

此业务流程侧重于 SDA 到 FHIR 的转换。 InterSystems IRIS 包含一套全面的内置业务流程,即 S.FHIR.DTL.Util.HC.SDA3.FHIR.Process,该流程可以促进 SDA 与 FHIR 消息的转换。 通过将生成的 SDA 文档发送到此业务流程,您可以接收以 JSON 响应形式发送的 FHIR 资源。

此流程支持两种类型的 FHIR 响应,具体取决于 SDA 输入。

  1. 捆绑包 – 如果整个 SDA 容器对象以 Ens.StreamConainter 形式发送,该流程会返回包含所有资源的 FHIR 捆绑包。
  2. 资源 – 如果个别 SDA 部分(例如,患者、诊疗、过敏症)以 Ens.StreamConainter 的形式发送,它会以捆绑包的形式发送对应的单个 FHIR 资源。

业务操作

FHIR 捆绑包现已准备就绪,可被返回给请求方或发送到外部系统。

生产设置:


业务服务类

该业务服务类负责处理外部系统发出的请求,以生成 FHIR。

  1. 一旦接收到请求,它就会使用现有逻辑创建 SDA。
  2. 该 SDA 随后会被转换为流对象。
  3. 此流会被转换为标准业务流程预期使用的格式。
  4. 最后,处理好的输入会被发送到业务流程。
Class Samples.Interop.BS.GenerateFHIRService Extends Ens.BusinessService
{

Parameter ADAPTER = "Ens.InboundAdapter";Property TargetConfigName As Ens.DataType.ConfigName [ InitialExpression = "HS.FHIR.DTL.Util.HC.FHIR.SDA3.Process" ]; Method OnProcessInput(pInput As%RegisteredObject, Output pOutput As%RegisteredObject) As%Status { #; create your SDA container object and export to streamdo..CreateSDAContainer().XMLExportToStream(.sdaStream)

#<span class="hljs-comment">; convert to the standard Ens.StreamContainer message format</span>
<span class="hljs-keyword">set</span> ensStreamCtnr = <span class="hljs-keyword">##class</span>(Ens.StreamContainer).<span class="hljs-built_in">%New</span>(sdaStream)

#<span class="hljs-comment">; send to the Business process</span>
<span class="hljs-keyword">do</span> <span class="hljs-built_in">..SendRequestSync</span>(<span class="hljs-built_in">..TargetConfigName</span>,ensStreamCtnr,.pOutput)
<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

ClassMethod CreateSDAContainer() As HS.SDA3.Container {

<span class="hljs-keyword">set</span> SDAContainer = <span class="hljs-keyword">##class</span>(HS.SDA3.Container).<span class="hljs-built_in">%New</span>()

#<span class="hljs-comment">; create patient object</span>
<span class="hljs-keyword">set</span> patientSDA = <span class="hljs-keyword">##class</span>(HS.SDA3.Patient).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> patientSDA.Name.FamilyName = <span class="hljs-string">"stood"</span>
<span class="hljs-keyword">set</span> patientSDA.Name.GivenName = <span class="hljs-string">"test"</span>
<span class="hljs-keyword">set</span> patientSDA.Gender.Code=<span class="hljs-string">"male"</span>
<span class="hljs-keyword">set</span> patientSDA.Gender.Description=<span class="hljs-string">"birth gender"</span>
#<span class="hljs-comment">; create Encounter 1</span>
<span class="hljs-keyword">set</span> encounterSDA  = <span class="hljs-keyword">##class</span>(HS.SDA3.Encounter).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> encounterSDA.AccountNumber = <span class="hljs-number">12109979</span>
<span class="hljs-keyword">set</span> encounterSDA.ActionCode =<span class="hljs-string">"E"</span>
<span class="hljs-keyword">set</span> encounterSDA.AdmitReason.Code =<span class="hljs-string">"Health Concern"</span>
<span class="hljs-keyword">set</span> encounterSDA.AdmitReason.Description = <span class="hljs-string">"general health concern"</span>
#<span class="hljs-comment">; set the patientSDA into the container.</span>
<span class="hljs-keyword">set</span> SDAContainer.Patient = patientSDA

#<span class="hljs-comment">; set encounters into the container SDA</span>
<span class="hljs-keyword">do</span> SDAContainer.Encounters.Insert(encounterSDA)
<span class="hljs-keyword">return</span> SDAContainer

} }


使用 ObjectScript 创建 SDA 到 FHIR 的转换

在上一个示例中,FHIR 资源是借助互操作性框架通过 SDA 生成的。 在本节中,我们将直接使用 ObjectScript 构建 FHIR 捆绑包。


通过 SDA 容器创建 FHIR 捆绑包

CreateSDAContainer 方法会返回 HS.SDA3.Container 类型的对象(我们在上文中提到过)。 在将此 SDA 容器传递给 TransformStream 方法之前,必须先将其转换为流。 TransformStream 方法随后会处理该流,并在 tTransformObj.bundle 中以 %DynamicObject 形式返回 FHIR 捆绑包。

ClassMethod CreateBundle(fhirVersion As%String = "R4") As%DynamicObject
{
	try {	
		Set SDAContainer = ..CreateSDAContainer()
		Do SDAContainer.XMLExportToStream(.stream)
		#; Should pass stream, not a container objectSet tTransformObj = ##class(HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR).TransformStream( stream, "HS.SDA3.Container", fhirVersion)
		return tTransformObj.bundle
	}
	catch ex {
		write ex.DisplayString()
	}
	return""
}


使用 SDA 部分创建 FHIR 捆绑包

使用此方式时,会直接在 ObjectScript 中声明 patientSDA。 此 SDA 对象随后会被传递到 TransformObject 方法,这个方法负责处理此 SDA 对象,并以 %DynamicObject 形式返回 FHIR 捆绑包。

ClassMethod CreatePatientResourceDirectSet()
{
	try {
		#; convert you're custom dataset into SDA by your DTLset patientSDA = ##class(HS.SDA3.Patient).%New()
		set patientSDA.Name.FamilyName = "stood"set patientSDA.Name.GivenName = "test"set patientSDA.Gender.Code="male"set patientSDA.Gender.Description="birth gender"#dim tTransformObj As HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR = ##class(HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR).TransformObject(patientSDA,"R4")
		set patinetBundle = tTransformObj.bundle
	}
	catch ex {
		write ex.DisplayString()
	}
	return patinetBundle
}

使用自定义 FHIR DTL 和 Allergy 扩展创建过敏症资源

  1. 直接在 SDA 对象中填充所有必需字段,包括自定义扩展字段。
  2. 您应当在 TransformObject 方法中将 FHIR 版本类型作为第二个参数提及(“R4”代表 Resource4 FHIR 消息)。
  3. 将完成的 SDA 对象传递给 FHIR 转换类,以生成 AllergyIntolerance FHIR 捆绑包。

注:过敏症资源的自定义扩展已定义,自定义 DTL 映射已注册。

ClassMethod CreateAllergyWithDTL()
{
	#; I already registered the "HS.Local.FHIR.DTL.SDA3.vR4.Allergy.AllergyIntolerance" for extension mapping
	#; fetch the data from the table/global and set it into AllergySDA directly.	set allerySDA = ##class(HS.SDA3.Allergy).%New()
	set allerySDA.Extension.Criticality = "critial"set allerySDA.Extension.Type = "t1"set allerySDA.Comments = "testing allergies"set allerySDA.AllergyCategory.Code="food"set allerySDA.AllergyCategory.Description="sea food"
	#; Set the required and additional properties in SDA, depending on your requirements.
	#; create a FHIR resource from the allergySDA with extension fields that uses a custom "HS.Local.FHIR.*" DTL#dim tTransformObj As HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR = ##class(HS.FHIR.DTL.Util.API.Transform.SDA3ToFHIR).TransformObject(allerySDA,"R4")
	Set patinetBundle = tTransformObj.bundle
}

FHIR 转换为 SDA

自定义数据、HL7 v2.x 或 CCDA 消息之前已被转换为 FHIR。 接下来的实现涉及将 FHIR 捆绑包或资源转换为 SDA 格式,随后可以存储在数据库中或转换为 CCDA 或 HL7 v2.x 格式。

JSON 或 XML 格式的 FHIR 资源接收自外部系统。 收到后,必须将资源转换为内部数据结构并存储在 IRIS 数据库中。

业务服务

可以根据要求通过 HTTP/REST 或其他任何入站适配器接收请求。


业务流程 – FHIR 转换为 SDA

InterSystems IRIS 接收到 FHIR 请求消息后,会提供全面的内置业务流程 (HS.FHIR.DTL.Util.HC.FHIR.SDA3.Process)。 此业务流程会将 FHIR 资源或捆绑包作为输入。 FHIR 输入只能是配置的 FHIR 版本。 此业务流程会将 FHIR 数据转换为 SDA3、将 SDA3 流转发给指定的业务主机、接收业务主机发送的响应,并返回 FHIR 响应。

请注意,您无法将收到的请求直接发送至业务流程。

请求输入应为以下类型:

  1. HS.FHIRServer.Interop.Request – 用于互操作性生产。
  2. HS.Message.FHIR.Request – FHIR 仓库服务器。

这意味着在发送请求之前,必须将请求转换为上述格式之一。

Creating Interop.Request

ClassMethod CreateReqObjForFHIRToSDA(pFHIRResource As%DynamicObject) As HS.FHIRServer.Interop.Request
{
             #; sample message set pFHIRResource = {"resourceType":"Patient","name":[{"use":"official","family":"ashok te","given":["Sidharth"]}],"gender":"male","birthDate":"1997-09-08","telecom":[{"system":"phone","value":"1234566890","use":"mobile"},{"system":"email","value":"tornado1212@gmail.com"}],"address":[{"line":["Some street"],"city":"Manipal1","state":"Karnataka1","postalCode":"1234561"}]}
<span class="hljs-keyword">set</span> stream = <span class="hljs-keyword">##class</span>(<span class="hljs-built_in">%Stream.GlobalCharacter</span>).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">do</span> stream.<span class="hljs-keyword">Write</span>(pFHIRResource.<span class="hljs-built_in">%ToJSON</span>())
#<span class="hljs-comment">; create Quick stream </span>
<span class="hljs-keyword">set</span> inputQuickStream = <span class="hljs-keyword">##class</span>(HS.SDA3.QuickStream).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> inputQuickStreamId = inputQuickStream.<span class="hljs-built_in">%Id</span>()
<span class="hljs-built_in">$$$ThrowOnError</span>( inputQuickStream.CopyFrom(stream) ) 
	
<span class="hljs-keyword">#dim</span> ensRequest <span class="hljs-keyword">as</span> HS.FHIRServer.Interop.Request = <span class="hljs-keyword">##class</span>(HS.FHIRServer.Interop.Request).<span class="hljs-built_in">%New</span>()

<span class="hljs-keyword">set</span> ensRequest.QuickStreamId = inputQuickStreamId

<span class="hljs-keyword">return</span> ensRequest

在 HS.FHIRServer.Interop.Request 消息创建完毕后,立即将其发送至业务流程,以将 FHIR 资源转换为 SDA 捆绑包。

生产设置:


业务服务类

该类通过 HTTP 请求接收 FHIR 资源流,将此流输入转换为标准流程预期使用的格式,即 HS.FHIRServer.Interop.Request,最后调用 FHIR 适配器流程类以生成 SDA。

Class Samples.Interop.BS.FHIRReceiver Extends Ens.BusinessService
{

Parameter ADAPTER = "EnsLib.HTTP.InboundAdapter";Property TargetConfigName As Ens.DataType.ConfigName [ InitialExpression = "HS.FHIR.DTL.Util.HC.FHIR.SDA3.Process" ]; Method OnProcessInput(pInput As%Stream.Object, Output pOutput As%Stream.Object) As%Status { set inputQuickStream = ##class(HS.SDA3.QuickStream).%New() set inputQuickStreamId = inputQuickStream.%Id() $$$ThrowOnError( inputQuickStream.CopyFrom(pInput) )

<span class="hljs-keyword">#dim</span> ensRequest <span class="hljs-keyword">as</span> HS.FHIRServer.Interop.Request = <span class="hljs-keyword">##class</span>(HS.FHIRServer.Interop.Request).<span class="hljs-built_in">%New</span>()
<span class="hljs-keyword">set</span> ensRequest.QuickStreamId = inputQuickStreamId

<span class="hljs-keyword">Do</span> <span class="hljs-built_in">..SendRequestSync</span>(<span class="hljs-built_in">..TargetConfigName</span>, ensRequest, .pOutput)

<span class="hljs-keyword">Quit</span> <span class="hljs-built_in">$$$OK</span>

}

}


使用 ObjectScript 通过 FHIR 资源创建 SDA

在上一个示例中,SDA 文档是借助互操作性框架通过 FHIR 生成的。 在本节中,我们将直接使用 ObjectScript 实现从 FHIR 到 SDA 的转换。

在您收到以请求形式发送到 IRIS 中的 FHIR 资源/捆绑包后,立即将 FHIR JSON 转换为 SDA 容器:

  1. 将 InterSystems %DynamicObject AKA JSON 转换为 %Stream 对象。
  2. 通过 HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3 类执行 TransformStream 方法,这会以响应形式返回 SDA 容器对象。
///Simple, straightforward FHIR JSON resource to SDA conversionClassMethod CreateSDAFromFHIRJSON()
{
	try {
		; have to send as a stream, not a %DynamicObjectset patientStream = ##Class(%Stream.GlobalCharacter).%New()
		do patientStream.Write({"resourceType":"Patient","name":[{"use":"official","family":"ashok te","given":["Sidharth"]}],"gender":"male","birthDate":"1997-09-08","telecom":[{"system":"phone","value":"1234566890","use":"mobile"},{"system":"email","value":"tornado1212@gmail.com"}],"address":[{"line":["Some street"],"city":"Manipal1","state":"Karnataka1","postalCode":"1234561"}]}.%ToJSON())
		#dim SDAObj As HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3 = ##class(HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3).TransformStream(patientStream,"R4","JSON")
		set SDAContainer = SDAObj.container
	<span class="hljs-comment">; XML-based SDA output</span>
	<span class="hljs-keyword">write</span> SDAContainer.XMLExport()
}
<span class="hljs-keyword">catch</span> ex {
	<span class="hljs-keyword">write</span> ex.DisplayString()
}

}


FHIR XML 转换为 SDA 容器。

  1. 将 XML 转换为 %Stream 对象。
  2. 通过 HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3 类执行 TransformStream 方法,这会以响应形式返回 SDA 容器对象。
/// Simple, straightforward FHIR XML resource to SDA conversionClassMethod CreateSDAFromFHIRXML()
{
	try {
		set patientXML = "<Patient xmlns=""http://hl7.org/fhir""><id value=""example""/><text><status value=""generated""/><div xmlns=""http://www.w3.org/1999/xhtml""><p>John Doe</p></div></text><identifier><use value=""usual""/><type><coding><system value=""http://terminology.hl7.org/CodeSystem/v2-0203""/><code value=""MR""/></coding></type><system value=""http://hospital.smarthealth.org""/><value value=""123456""/></identifier><name><use value=""official""/><family value=""Doe""/><given value=""John""/></name><gender value=""male""/><birthDate value=""1980-01-01""/></Patient>"set patientStream = ##Class(%Stream.GlobalCharacter).%New()
		do patientStream.Write(patientXML)
		#dim SDAObj As HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3 = ##class(HS.FHIR.DTL.Util.API.Transform.FHIRToSDA3).TransformStream(patientStream,"R4","XML")
		set SDAContainer = SDAObj.container
	<span class="hljs-comment">; XML-based SDA output</span>
	<span class="hljs-keyword">write</span> SDAContainer.XMLExport()
}
<span class="hljs-keyword">catch</span> ex {
	<span class="hljs-keyword">write</span> ex.DisplayString()
}

}

按照上文详细介绍的步骤,您可以在数据与 FHIR 资源之间进行无缝转换。

其他内置的 FHIR 仓库和 FHIR 装饰选项是公开符合 FHIR 标准的系统、高效处理和存储 FHIR 资源的重要工具。

0
0 16
文章 Nicky Zhu · 十月 10, 2024 7m read

本演示程序用于展示如何采用自定义FHIR profile来验证数据合规性。自定义FHIR实施指南基于FHIR R4版本开发,在本例中实现了对Organization资源的扩展并用于验证数据的合规性。

安装

  1. 通过Git clone下载本项目。
  2. 执行docker-compose up -d构建并启动容器,初次执行时需执行需10~15分钟(视配置变化)。将构建InterSystems IRIS for Health镜像,安装FHIR服务器,导入自定义FHIR规范,使自定义FHIR 规范可用于验证数据。
  3. 在Postman中导入TestCases中的测试用例文件,查看各类FHIR约束的测试效果
  4. 容器启动后可查看自定义IG内容

项目代码结构

FHIRValidation
├─ ExampleIG                        
│  ├─ ig.ini
│  ├─ input
│  │  ├─ fsh
│  │  │  ├─ alias.fsh
│  │  │  ├─ codesystems.fsh
│  │  │  ├─ organization.fsh
│  │  │  └─ valuesets.fsh
│  │  └─ pagecontent
│  │     └─ index.md
│  └─ sushi-config.yaml
├─ README.md
├─ README_zh.md
├─ TestCases
│  └─ FHIR Profile-based Validation  testcases.postman_collection.json
├─ docker-compose.yml
└─ image-iris
   ├─ Dockerfile
   └─ src
      ├─ FullIG
      ├─ IGPackages
      │  ├─ hl7.fhir.uv.extensions.r4#5.1.0.tgz
      │  ├─ hl7.terminology.r4#6.0.2.tgz
      │  └─ package.tgz
      └─ init
         └─ init.sh

ExampleIG

该子目录下的所有文件为本项目所采用的自定义FHIR规范SUSHI源码,供用户定义FHIR规约时参考使用。

TestCases

该子目录下存放基于FHIR REST API的测试用例脚本,需导入到Postman中使用

image-iris

该子目录下存放nterSystems IRIS for Health镜像所需的文件,其中: └─ src ├─ FullIG 该目录中存放SUSHI生成的自定义FHIR IG ├─ IGPackages 该目录中存放自定义FHIR IG的 package 文件 └─ init 该目录中存放IRIS的Docker镜像初始化脚本

FHIR package简介

HL7组织推荐使用实施指南(Implementation Guild)来解释如何使用FHIR规范。除用于开发人员阅读的说明(如html)外,实施指南中通常也包括可直接被机器读取和应用的工件(artifacts),可被用于驱动代码生成和数据验证等任务。
FHIR实施指南采用NPM Package规范管理依赖。指南涉及的所有StructureDefinition,ValueSet等资源将被打包在一块,形成可被FHIR Server用于读取规范,生成客户端代码或执行数据质量校验的资源包。
通过SUSHI工具生成的实施指南中就包含若干package文件。如本例中,image-iris/src/IGPackages/package.tgz即为生成的package包,可被IRIS FHIR Server直接导入使用。应当注意到的是,除核心资源包(如hl7.fhir.r4.core)外,完整的FHIR规范还需要引用术语、扩展等额外的资源包。
目前FHIR规范引用机制的文档尚不完善。如基于R4版的FHIR规范除引用hl7.fhir.r4.core外,还需引用hl7.fhir.uv.extensions.r4#5.1.0hl7.terminology.r4#6.0.2,但这些引用关系在R5版本中方有记录,在R4版文档中并未完整声明,需开发者在开发过程中自行补充。
在本例中这些包已下载在image-iris/src/IGPackages文件夹下,将作为依赖在自定义FHIR实施指南之前加载。

FHIR validation简介

参见FHIR规范Validating Resources一节。FHIR规范已经设计了对数据结构、属性基数、值域、代码绑定和约束等一系列机制在内的数据质量校验机制。HL7组织在FHIR规范中并未强制要求遵循何种强度的质量控制,但建议采用宽进严出的原则处理FHIR数据。
对于保存FHIR资源的FHIR存储库而言,保障FHIR资源的数据质量是使医疗行业具有价值,保障医疗行为安全性的前提条件。因此,在构建基于FHIR存储的数据共享交换方案时,即使不得不保存不满足数据质量要求的数据,也应对其进行校验,标识不符合项,推动数据治理活动的进行,从而保障医疗安全和数据消费者的利益。
在FHIR规范指出的多种数据校验方式中,FHIR Validator和FHIR操作对数据质量校验的覆盖最为全面。
本例将使用InterSystems IRIS for Health所提供的$validate操作,通过profile参数对尚未保存的FHIR数据进行校验。使用者也可修改测试用例,构建HTTP POST参数,对存量FHIR资源进行校验。
还应当注意的是,$validate操作如被正确调用,将通过Http 200返回校验结果,如有不符合项,将在返回的OperationOutcome资源中包裹错误信息,而不通过Http代码标识错误。

对FHIR的扩展

在本例中基于FHIR R4对Organization资源进行了如下扩展:

1. 修改language的绑定强度

将机构主要语言的绑定强度修改为required

2. active字段基数从0..1改为1..1

从而使得数据的状态成为必填字段,有且只有一个元素

3. name字段基数从0..1改为1..1

组织机构名称成为必填字段,有且只有一个元素。参考我国医院除医院名称外,如果具备急救中心、胸痛中心等牌照,还可能具有多个名称。但因注意到,这些牌照通常标识了医疗机构提供的服务能力,而非在组织机构注册系统中具备的法定名称,且此类牌照生命周期与医疗机构自身的生命周期并不一致。因此,从牌照获得的名称宜视为该医疗机构的服务能力而非机构的唯一名称。在FHIR中,通过服务能力获得的名称可通过资源HealthcareService提供,该资源与Organization资源间可建立多对一的引用关系,更适合用来表达上述概念。

4. 增加医疗机构的组织机构类型

根据中国国家标准GB/T 20091-2021 组织机构类型,分别增加了CodeSystem organizationtype-code-system和ValueSet organizationtype-vs,并通过Extension向Organization资源中添加了扩展mdm-organizationTypeExtension,从而使得该资源可用于表示表示标识中国组织机构类型。
该扩展通过对Extension切片实现,且基数为1..1,即医疗机构资源必须具有组织机构类型元素。

5. 约束医疗机构证件号码

FHIR基础标准并未纳入中国组织机构统一社会信用代码的证件类型,为此增加了CodeSystem cs-identifierType-code-system,并对Identifier按其类型进行了切片,使之必须可以表达社会信用代码。且社会信用代码的格式遵循以下约束:

  1. identifier.use必须取值为official,即正式/官方用途
  2. identifier.type必须遵循cs-identifierType-code-system要求,system必须为该codesystem的uri,code必须为“USCC”
  3. identifier.value必须遵循自定义约束uscc-length-18,该字段长度必须为18位,其中前17位必须为数字,最后1位必须为数字或字母

测试用例列表

1. Without profile - All OK

未声明资源对应的profile,因此FHIR Server将不对资源中各属性的值进行校验,仅返回All OK。

2. Unknow field

在资源中加入了未被定义的属性isNational,因此校验引擎返回了Unrecognized element错误。

3. Wrong cardinality - less

在本IG中,修改了Organization资源name属性的基数为1..1,即应有且仅有一个组织机构名称。本测试用例未填写名称,因此数据校验失败。 另外,可以观察到Identifier.type经过扩展,加入了统一社会信用代码作为标识符类型,FHIR R4规范里并不包含这个值,但该字段的代码绑定强度仅为example,不强制约束。因此校验引擎返回了information级的值域代码不符合信息而没有报错。

4. Binding strength

在本IG中,组织机构的language属性的代码绑定强度改为了required,则该字段值域必须符合http://hl7.org/fhir/ValueSet/languages,因此,当该字段取值为wrong language时,因不在required值域中,将导致error级错误

5. Wrong value

在本IG中,组织机构类型的值域来自于organizationtype-code-system,因此,当类型为mdm-organizationTypeExtension的extension元素中code的值为“999”,不在值域中时,将导致error级错误

6. Failing invariant

在本IG中,组织机构的社会信用代码必须遵循自定义约束uscc-length-18(该字段长度必须为18位,其中前17位必须为数字,最后1位必须为数字或字母),因此,当其末位为字符“%”时,违反该约束,将导致error级错误

7. Failing profile

对于一个资源定义的一个profile包含了多个约束,因此,在校验时所有不满足profile的问题都将被检出,例如本例中:

  1. 错误的language代码
  2. 错误的组织机构类型
  3. 缺少name字段 可见上述问题都被检出
0
0 127
文章 Jeff Liu · 四月 17, 2024 1m read

各位开发者好

欢迎观看InterSystems Bilibili官方频道的最新视频 InterSystems Developers Bilibili:

⏯ Understanding the Structure of HL7 FHIR Resources

<iframe allowfullscreen="true" border="0" frameborder="no" framespacing="0" scrolling="no" src="//player.bilibili.com/player.html?aid=1953056184&bvid=BV1iC411G74J&cid=1506782787&p=1"></iframe>

了解 HL7 FHIR 资源的结构。了解如何在 HL7 FHIR 网站上查看和阅读资源的树形表示法,从而了解资源中包含的不同数据元素。此外,还可了解如何查看 XML、JSON 或 Turtle 格式的资源,以及在哪里可以找到 FHIR 资源的通用建模语言 (UML) 图。

观看新视频!

0
0 100
文章 Nicky Zhu · 十二月 27, 2023 7m read

在医疗行业中,处方是个非常重要的临床工作数据概念。因此,在考察用FHIR能如何构造我国所需医疗行业数据模型时,就会需要考虑如何用FHIR表达处方。

 

在2019年,FHIR的工作组已否认需要使用特定的资源来表达处方(不是药嘱)这个概念,见:

https://jira.hl7.org/browse/FHIR-24905

奇妙的是,IHE规范中却明确有处方(Prescription)的定义并需要引用药嘱(Medication Treatment Plan Item)。

https://www.ihe.net/uploadedFiles/Documents/Pharmacy/IHE_Pharmacy_Suppl_PRE.pdf?#page=12

 

FHIR官网指出这种复合式的request有三种表达方式:

• Shared requisition id

• "Based on" chain

• RequestOrchestration

https://build.fhir.org/request.html#compound

 

在FHIR实际应用中,则可以见到多种形态使用容器类资源表达处方并包含药嘱的表达形式,例如:

  1. 中国2023 FHIR Connectathon中使用消息Bundle来进行处方流转
0
0 180
文章 Qiao Peng · 十月 26, 2023 10m read

CDS Hooks是FHIR生态下一个决策支持架构,是SMART(Substitutable Medical Applications and Reusable Technologies, 可替代的医学应用和可复用技术)下的一个项目。

FHIR标准下也有一个决策支持相关的模块 - FHIR的Clinical Reasoning模块。它和CDS Hooks是有区别的:

FHIR的Clinical Reasoning模块提供一系列资源模型和工件,用于构建决策支持相关的规则、医嘱集、临床协议和质量指标,并基于此对特定患者和人群进行评估,进而产生决策行为。它构建的是本地决策支持体系。

而CDS Hooks提供一个决策支持架构,打通外部决策支持系统和本地的决策数据源、业务流程。

CDS Hooks是开源的,基于知识共享 CC BY 4.0,因此也获得了广泛采纳。

CDS Hooks的架构

CDS Hooks是打通外部决策支持系统和客户端应用的决策支持架构,完整的架构包括:

CDS客户端:通常是用户的业务系统,如HIS或电子病历

CDS服务:这是CDS Hooks提供的核心组件,向客户端发布的决策支持服务

FHIR服务器:这是用户侧的FHIR服务器,保存的是用户侧的FHIR资源数据。CDS服务通过访问FHIR服务器获得用户侧的决策依据的完整数据

0
0 166
文章 Qiao Peng · 十月 23, 2023 12m read

FHIR标准提供灵活的扩展与再约束机制 - Profile。到底Profile机制如何工作?什么样的扩展需要用到Profile?怎么建立Profile?


 

FHIR核心资源模型  - FHIR Core

FHIR发布的资源模型是按80/20原则设计的 - 最常用那80%的用例中需要的数据会被涵盖在FHIR核心资源模型中,这些数据需求可能只是所有用例需要数据的20%;通过对核心资源的扩展和再约束,可以让它们适用于不常见的20%用例和未被涵盖的80%的数据需求。

FHIR发布的资源模型是FHIR核心资源模型(FHIR Core),它们有如下特点:

1. 对象模型 - 有继承关系。所有资源都继承自DomainResource

2. 为了保证最大的适用度,资源中的绝大多数属性的最小基数都是0,意味着它们都可以为空

3. 资源的属性可以通过code(值集)、coding、CodeableConcept(术语)进行取值范围约束

4. 为了防止医疗错误,所有的属性都没有且不能有默认值

当需要对核心资源模型进行扩展和再约束时,FHIR提供了profile机制对所做的扩展和再约束进行画像(描述),这就是profile的意思。

这里把对FHIR资源模型的用户自定义扩展区分为“扩展”和“再约束”,差异是:

  • 扩展指需要要增加新的资源属性
  • 再约束指修改核心资源模型的属性的基数、值集绑定、必须支持、切片等
0
0 416
文章 Qiao Peng · 十月 7, 2023 19m read

卫生信息和其它信息化一样,经历了数码化、数字化到当今的数字化转型,卫生信息互操作一直伴随左右。

数码化(digitization):国内90年代开始,HIS全面铺开,卫生信息进入数码化时代。数码化初期业务集中在HIS上,互操作需求不高,点对点接口可以满足绝大多数需求。

数字化(digitalization):在2000年之后,各种专科系统、尤其是电子病历的诞生,医保和新农合的实施,要求卫生信息共享交换,以提高流程自动化水平。互操作需求爆发,2007年集成平台开始进入市场,卫生信息化进入数字化时代。

数字化转型(digital transformation):2014年,国内正式进入移动互联网时代;次年《全国医疗卫生服务体系规划纲要(2015—2020年)》发布,卫生信息化的服务对象(服务于医护技到服务于患者)和业务形态(临床管理到患者服务)都发生了翻天覆地的变化,开始步入数字化转型的时代。它对互操作提出了更高的要求 - 利用互操作,增强全员参与,为卫生服务创造新价值、发展新业务,推动医疗机构持续数字化转型。

可以说,卫生信息互操作在整个的卫生信息产业中愈发重要。

国际卫生信息互操作发展了30年,国内也发展了20年,但卫生信息互操作依然是一个挑战。

知史而明鉴,识古而知今。我们看看国际卫生信息互操作发展的历程,对未来的卫生信息互操作有什么借鉴。

卫生信息互操作标准的要素

0
0 553
文章 Michael Lei · 七月 13, 2023 1m read

前不久,北京市人民政府印发了《关于更好发挥数据要素作用进一步加快发展数字经济的实施意见》的通知。其中提到要“率先探索数据跨境流通”。今年1月,北京市互联网信息办公室也发文公示,首都医科大学附属北京友谊医院与荷兰阿姆斯特丹大学医学中心合作研究项目成为全国首个被北京网信办批准的数据出境安全评估案例(编号20220001)。可以预见,为更好发挥数据要素作用将来可能出现越来越多的跨境数据流通。那么我们今天仅仅看下,在医疗领域国际主要流行的数据标准都有哪些。

以下是国际数字医疗合作组织的主要统计(该组织协同了世界卫生组织WHO,OECD和33个不同的国家和地区)

从上表可以看出,数据共享领域 DICOM,HL7 v2, CDA, FHIR,v3 是主要的标准,在临床术语方面 ICD9/10/11, SNOMED 和Lionc是目前国际上各个国家和地区最主流的医疗数据标准。供大家参考。

相关阅读

FHIR标准和国际基于FHIR的互联互通实践

论集成标准的选择对医院信息集成平台建设的影响

对话:“数据二十条”与FHIR标准

原文链接:https://www.healthit.gov/topic/global-digital-health-partnership

0
0 434
文章 Lilian Huang · 七月 9, 2023 5m read

#Embedded Python #HL7 #InterSystems IRIS for Health

写在回复社区帖子《Python能否动态创建HL7消息》中。

前提条件和设置

使用一个启用了集成的命名空间。
注意:USER命名空间默认不启用互操作性。
如果以下建议创建一个新的互操作性命名空间来探索功能。

# 切换到
ZN "[互操作性名称空间名称]"

# 启动交互式Python shell:
Do $SYSTEM.Python.Shell()

启动脚本

#Load dependencies

import datetime as dt
import uuid

# Cache current time in CCYYMMDDHHMMss format
hl7_datetime_now=dt.datetime.now().strftime('%Y%m%d%H%M%S')

# Create HL7 Message
hl7=iris.cls("EnsLib.HL7.Message")._New()

# Set the doc type
# 2.5.1:ORU_R01 - Unsolicited transmission of an observation message
hl7.PokeDocType("2.5.1:ORU_R01")

这些信息的结构可以从管理门户中获取

0
0 294
文章 Claire Zheng · 六月 8, 2023 1m read

医院管理者、信息中心、业务骨干,每个角色都有独特的业务诉求,InterSystems IRIS医疗版互联互通套件专为国内用户设计,可助力医院用户释放数据价值,推动应用创新!截至目前,InterSystems技术已助力150余家医院通过四级及以上医院信息互联互通标准化成熟度评测,其中,五级乙等用户近30家。

0
0 162
文章 Michael Lei · 三月 27, 2023 11m read

好不好玩,能当真吗?


最近几个月,大型语言模型GPT正在激起一些现象。因此,上周末我不可避免地也在玩 ChatGPT,以探究它是否会成为我正在敲打的一些基于 BERT 的“传统”AI 聊天机器人的补充,或者更确切地说,它是否会淘汰它们。
玩的时候脑子里冒出一个念头。通过略微理论化或哲学化,最终互操作性标准(如 HL7 和 FHIR 等)是一种“语言”,对吗? HL7 有自己的语法、规则、词汇甚至方言——每个系统都有自己的语调。这就是为什么当一台机器与另一台机器对话时,它们需要翻译器(例如 DTL 转换)来实现相互理解。
所以环顾四周,似乎一切都是语言:编码是语言:python,javascript和COS也是语言。 HL7、FHIR 甚至 XML 或 JSON 都是语言,只是它们比自然语言更结构化,那么 GPT 应该更容易上手吗?
那么,我们可以从简单地重用 GPT 的预训练编码语言模型来模拟 DTL 开始吗?我们还没有进行调整,以下是初步结果:


测试


模式:完整
型号:code-davinci-002
温度:0
最大长度:1989
其他:默认
停止序列:###
1、将HL7 ADT A01转A05?

输入:  

0
0 237
文章 Hao Ma · 二月 16, 2023 9m read

A "big" or a "little" ask for ChatGPT?


几周前我尝试了 OpenAI GPT 的编码模型,看看它是否可以在医疗保健系统之间进行一些消息转换。它肯定可以,在相当大的程度上。
已经将近 3 周了,对于 ChatGPT 来说是很长很长的时间,所以我想知道它现在成长得有多快,以及它是否可以为我们做一些集成工程师的工作,例如它是否可以创建一个 InterSystems COS DTL将 HL7 转换为 FHIR 信息?

在不到一两分钟的时间内,我立即得到了一些答案。


测试

首先我想测试一下我是在和它背后的正确“人”说话

问题一:如何将HL7 V2.4报文转为FHIR STU3?

ChatGPT

将 HL7 V2.4 消息转换为 FHIR STU3 涉及多个步骤,因为这两个标准具有不同的数据模型和结构。以下是该过程的高级概述:

2
0 355
文章 Lilian Huang · 一月 19, 2023 10m read

在上一篇文章中,我们看到了最常用的HL7消息类型之一--ADT(入院、出院、转院)的结构,以及ADT^A04的例子和它所有字段的描述。现在让我们来看看另一个数据流,它与测试订单的订购和履行有关。我说的是ORM(从2.5版本开始,你应该使用特定的消息来订购测试,如OMG、OML、OMD、OMS、OMN、OMI和OMP),ORL和ORU消息。在一个非常简化的情况下,数据的交换可能看起来像这样。

让我们更详细地看一下这些消息。

0
0 791
文章 Nicky Zhu · 一月 6, 2023 8m read

国务院于2022年12月19日发布了《中共中央 国务院关于构建数据基础制度更好发挥数据要素作用的意见》(后简称《数据二十条》),如何有效利用数据已经成为下一步的趋势。另一方面,无论是基于数据中台还是数据编织理念,两者也都对如何利用数据提出了构想。因此医疗行业数字化建设的目标已不能再局限于如何收集数据,建立医疗行业数据的流通机制将会是为越来越普遍的需求。

时钟拨回几年前,数据中台概念开始火爆。人们对数据中台的定义、诠释尽管有诸多差异,通过数据中台降低数据共享和利用的成本则是共同的期望。但经过这几年的探索之后,中台已死的观点也在涌现。究其原因,除去中台概念在技术上的不确定,数据流通过程中的责权益的不清晰也是严重的制约因素。毕竟,数据中台自身作为一套技术框架并不能代替法律法规与市场自动将数据转变为商品从而创造出流通价值。

那么,如何能够使数据的流通合规合法,使数据能够如货币和商品一般自由流动,则是我们需要思考和探索的主题,这次《数据二十条》的出现,无疑为医疗信息技术工作者提供了一个明确的思考方向。

0
0 264
文章 Lilian Huang · 十二月 31, 2022 10m read

在上一篇文章中,我们讨论了标准 HL7v2 的起源、结构和消息类型。现在让我们看一下最常用的消息类型之一及其结构示例。我说的是 ADT。

HL7 ADT 消息(入院、出院、转院)用于在医疗机构传达基本患者信息、就诊信息和患者状态。 ADT 消息是使用最广泛且容量最大的 HL7 消息类型之一,因为它为许多触发事件提供信息,包括患者入院、注册、取消、更新、出院、患者数据合并等。

0
0 1215
文章 Lilian Huang · 十一月 30, 2022 5m read

HL7(Health Level 7)是一套技术规范,用于医院信息系统(HIS)之间临床、财务和管理数据的计算机互交换。这些规范被不同程度地被纳入美国(ANSI)和国际(ISO)正式标准的语料库中。

HL7的L7表示它是在OSI模型的第7层,换句话说,在应用层运行的标准。这意味着HL7不需要考虑交换的安全性,也不需要考虑信息传输的安全性(这一点由较低层次的层来保证,例如用于安全的SSL/TLS或用于数据传输的TCP)。更准确地说,第7层支持终端用户进程和应用的通信,以及面向用户的软件应用的数据展示。作为OSI模型的最高层,也是最接近最终用户的层,第7层提供特定的应用功能,如识别通信伙伴和它们之间的服务质量,确定资源可用性,考虑隐私和用户认证,以及同步通信,并将应用与OSI模型的较低层连接起来。

回到HL7标准,HL7第二版标准(也称为Pipehat)最初创建于1989年,但目前仍在使用并定期更新,形成了2.1、2.2、2.3、2.3.1、2.4、2.5、2.5.1、2.6、2.7、2.7.1、2.8、2.8.1、2.8.2和2.9版本。v2.x标准是向后兼容的(例如,基于2.3版本的信息将被支持2.6版本的应用程序所理解),在更高的版本中,你会看到一些字段是专门为它而留的。

0
1 931
文章 John Pan · 九月 9, 2022 5m read

集成平台的关键在于解决系统之间的互联互通和互操作性的问题,是一个多厂商、多协议的体系结构。医院在集成平台实施的过程中,面临的第一件重要的事情就是交互标准的选择,目前的建设中,分为两队:非标准队和标准队。非标准队一般采用视图抓取、xml格式、json等等的自定义格式,标准队一般采用HL7 V3、HL7 V2、FHIR、DICOM等医疗领域标准,下面会简单介绍一下各种方式以及实施落地的难易程度。(以下内容中将以难易程度总分5★来表示,星数量越多代表难度越高)

1、非标准队

与其说非标准,不如定义为院内交互标准,交互仅限于院内,是一种很有限的互操作,而且定制程度很高,需要很好地把握系统的内部知识。方案缺乏通用性,难以规模推广。但由于其技术门槛较低,学习成本较低,在集成系统数量较少时不失为一种经济快速的方法。

      1.1 视图-★

视图可以说是一种"古老"的交互方案了,几乎传统的系统交互都是用视图的方式,有实施周期短,上线速度快的优点,但提供视图一方数据库,在大量数据查询的时候,将面临系统压力过大,数据库速度变慢等问题。在集成平台建设中,使用视图形式,可以由集成平台定时轮询视图,将数据发送给需要的系统。这样可以减轻源系统的压力。但是无论进行怎么样架构设计,视图这种形式的最大的弊端:无法保证数据的实时性。落地难度:1星。

      1.2 XML-★★

2
1 552
文章 Tete Zhang · 九月 14, 2022 5m read
  1. 从消息查看器看到清除周期以外的消息没有被正常清除

这种情况先抽查这些消息所处的会话中是否有未完成操作周期的消息(状态为除“Completed”“Error”“Discarded”之外的状态)。如有,且定期清除任务配置了“KeepIntegrity”,且该环境并不需要保留这些消息,可通过关闭清除任务中的“KeepIntegrity”配置清除这些会话和包含的消息。如果有这类消息,但是定期清除任务未配置“KeepIntegrity”,可能是定期清除任务的逻辑或消息数据问题导致清楚任务查找的时候没有覆盖这些消息,请联系WRC帮助排查具体原因。

有关定期清除任务的更多信息请参见文档

Purging Production Data | Managing Productions | InterSystems IRIS for Health 2022.1

  1. 从消息查看器看不到清除周期之外的消息,但是^%GSIZE显示有global占据了很大的磁盘空间

这种情况需要具体排查每个较大的global。可能有以下原因:

  • 系统定义的global占用很大空间。您可以联系WRC帮助排查具体原因。
  • 自定义的global占用很大空间。这可能是消息中嵌套的持久化数据或流数据,或者是和消息没有直接关系的独立的表里面的数据。请对创建这种global的代码进行复盘,找到创建逻辑并增加相应的数据管理逻辑。
0
0 202
文章 Lilian Huang · 六月 14, 2022 3m read

这篇文章是上一篇文章的延续https://cn.community.intersystems.com/post/首次使用intersystems-iris-互操作性-一个production是什么?

在上一篇文章:https://cn.community.intersystems.com/post/首次使用intersystems-iris-互操作性-一个production是什么?  我们查验了什么是Production. 我们运行了示例代码,并在Visual Trace 页面查验了如何将流动消息的内容引入进Production中。

本文将回顾消息messages的概念和定义,和消息如何在系统集成所需的开发内容中用于组件之间发送和接收数据。

在创建一个Message消息之前,让我们回顾一个案例研究。

一家公司经营着一个购物网站,并且正在为了适应季节而改变显示的产品信息顺序。

0
0 241
文章 Michael Lei · 三月 21, 2022 2m read

IRIS Healthtoolkit Service 软件即服务

Video

轻松实现HL7v2 转 FHIR, CDA 转 FHIR, FHIR 转 HL7v2 即服务.

这个项目的目标是提供 REST API 可以轻松转化不同的医疗行业格式。 在Rest body 发布需要的格式,在答案中获得新的格式。

安装

克隆这个 repository

git clone https://github.com/grongierisc/iris-healthtoolkit-service.git

Docker

docker-compose up --build -d

使用

API 细节

  • HL7 转 FHIR
POST http://localhost:32783/api/hl7/fhir
  • FHIR 转 HL7 ADT
POST http://localhost:32783/api/fhir/hl7/adt
  • FHIR 转 HL7 ORU
POST http://localhost:32783/api/fhir/hl7/oru
  • FHIR 转 HL7 vxu
POST http://localhost:32783/api/fhir/hl7/vxu
  • CDA 转 FHIR
POST http://localhost:32783/api/cda/fhir
  • FHIR repo
GET http://localhost:32783/api/fhir/metadata

支持的 HL7 inbound 格式 :

  • ADT_A01, ADT_A02, ADT_A03, ADT_A04, ADT_A05, ADT_A06, ADT_A07, ADT_A08, ADT_A09, ADT_A10, ADT_A11, ADT_A12, ADT_A13, ADT_A17, ADT_A18, ADT_A23, ADT_A25, ADT_A27, ADT_A28, ADT_A29, ADT_A30, ADT_A31, ADT_A34, ADT_A36, ADT_A39, ADT_A40, ADT_A41, ADT_A45, ADT_A47, ADT_A49, ADT_A50, ADT_A51, ADT_A60

  • BAR_P12

  • MDM_T02, MDM_T04, MDM_T08, MDM_T11

  • OMP_O09

  • ORM_O01

  • ORU_R01

  • PPR_PC1, PPR_PC2, PPR_PC3

  • RDE_O11

  • SIU_S12, SIU_S13, SIU_S14, SIU_S15, SIU_S16, SIU_S17, SIU_S26

  • VXU_V04

如何工作

这个项目基于SDA模型工作.

SDA (Summary Document Architecture) 是InterSystems系联公司的临床数据格式。

SDA <-> FHIR 的对应关系在 这里, CDA -> SDA 的对应在这里.

gif sda pivot

0
0 278
文章 Michael Lei · 九月 9, 2021 2m read

这是一个我开发的名为NiPaRobotica Pharmacy的小应用。 从附件可以看到一个界面,能够接收药房配药请求,并将订单上的行项目转换为发送给机器人的配药对话 。我在3家医院的药房部署了这个接口,其中两家药房有6个机器人被安排来将药物从分配槽配送到药剂师的窗口,每天能服务1200个病人。这些机器人能够将病人平均等待时间从2小时减少一半到1小时.接下来我把这个接口部署到专门为慢病病人建的6个配送点,例如如结核病、艾滋病毒、糖尿病、癫痫、高血压和哮喘等等。这个项目的目标是“把药物带给病人”。 这些点有六个6 ATM形式的药房配药设备 (Pharmacy Dispense Units ,PDU),可以让病人直接与呼叫中心的药剂师沟通。在每个PDU

0
0 250
文章 Claire Zheng · 一月 20, 2021 6m read

简介

最近完成了针对IRIS医疗版2020.1版本的性能及可扩展性基准测试,重点关注HL7v2的互操作性。本文介绍了在各种工作负载下观察到的吞吐量,并提供了IRIS医疗版用作HL7v2消息传输互操作性引擎时的系统常规配置和调整准则。

基准测试模拟了与实际环境接近的工作负载(详细信息请参见“工作负载说明和方法”部分)。本次测试的工作负载包括HL7v2患者管理(ADT)和生命体征结果(ORU)数据,并包含数据内容转换和路由。

IRIS医疗版2020.1版本可以表明,采用第二代Intel®Xeon®可扩展处理器和Intel®Optane™SSD DC P4800X系列SSD存储的商用服务器,每天的持续消息吞吐量超过23亿条(入站和出站总量),与此前的Ensemble 2017.1 HL7v2吞吐量基准测试相比,扩展性提高了一倍多。

2
0 348