CDAKit 1.0.2

CDAKit 1.0.2

测试已测试
语言语言 SwiftSwift
许可证 Apache 2
发布最后发布2016年3月
SPM支持SPM

Eric Whitley维护。



 
依赖项
GRMustache.swift~> 0.11.0
Fuzi= 0.3.0
尝试~> 1.0.0
 

CDAKit 1.0.2

  • Eric Whitley

CDAKit Logo

CDAKit

CDAKit for iOS,一个开源的临床文档架构库,具有HealthKit连接功能。帮助您快速管理CDA结构化健康数据。

CDAKit提供C32和C-CDA的导入和导出功能,以及将CDA概念与HealthKit样本连接的能力。这允许在CDA和HealthKit之间桥接,以便您可以与电子病历系统集成。

CDAKit的模型、导入器和导出器基于RubyHealth-Data-Standards项目(HDS),该项目由美国国家协调员办公室的健康信息技术办公室(ONC)资助并由MITRE公司(MITRE)主要构建。

您可以在以下链接中了解更多关于CDAKit背后的某些理念:LinkedIn文章

CDAKit团队

特别感谢

CDAKit不会存在,如果没有Ruby Health-Data-Standards库。特别是以下个人,他们的领导、承诺和辛勤工作有助于推动医疗保健互操作性

功能

  • 创建 CDA 文档(C32 和 CCDA)
  • 导入 CDA 文档(C32 和 CCDA)
  • 与健康管理系统之间的桥接(用于 CDA 的导入和导出)

快速通道

let doc = ((supply your CDA XML string))

do {
  //let's try to import from CDA
  let record = try CDAKRecord(fromXML: doc)

  //let's create a new vital
  // use the coded values to govern "meaning" (height, weight, BMI, BP items, etc.)
  let aVital = CDAKVitalSign()
  aVital.codes.addCodes("LOINC", code: "3141-9") //weight
  aVital.values.append(CDAKPhysicalQuantityResultValue(scalar: 155.0, units: "lb"))
  aVital.start_time = NSDate().timeIntervalSince1970
  aVital.end_time = NSDate().timeIntervalSince1970

  //append our height to our record
  record.vital_signs.append(aVital)

  //OK, let's convert our CDAK record to HealthKit
  let hkRecord = CDAKHKRecord(fromCDAKRecord: record)

  //let's explicitly set our preferred units to metric for a few things
  CDAKHealthKitBridge.sharedInstance.CDAKHKQuantityTypeDefaultUnits[.HKQuantityTypeIdentifierHeight] = "cm"
  CDAKHealthKitBridge.sharedInstance.CDAKHKQuantityTypeDefaultUnits[.HKQuantityTypeIdentifierBodyMass] = "kg"

  //now let's convert back from HealthKit to our model
  let cdakRecord = hkRecord.exportAsCDAKRecord()

  //render from our model to CDA - format set to .ccda (could also do .c32)
  print(cdakRecord.export(inFormat: .ccda))
}
catch {
  //do something
}

安装

要求

  • iOS 8+
  • Xcode 7
  • Swift 2.1

依赖项

CDAKit 自豪地使用以下项目

  • Fuzi - "Swift 中的快速且轻量级 XML & HTML 解析器,支持 XPath & CSS" 用于所有基于 XPath 的 CDA XML 解析。
  • GRMustache - “适用于 Swift 的灵活 Mustache 模板” Swift 版本的 Mustache 模板引擎。用于 CDA XML 生成。
  • Try - “使用 Swift 的错误处理系统处理 Objective-C 异常” 在一个特定的地方(尝试从字符串创建 HKUnit)中,我们需要使用更传统的“try”(并带有失败)来处理 Swift 尚未处理到的异常。

使用

在您的应用程序中引用 CDAKit

import CDAKit

基本模型

CDAKit Record Model

CDAKit 使用一个表示核心 CDA 文档的“Record”对象(CDAKRecord)。在记录中包含单独的条目(CDAKEntry),它们具有更精确的类型,用于元素如就诊、药物、过敏等。

  • CDAKRecord: 中央记录

    • 记录头部元数据
    • 患者姓名、医疗记录号、人口统计学、性别等。
    • 按类型(过敏、就诊等)排列的特定类型的子 CDA 条目数组

  • CDAKEntry: 您详细 CDA 内容。这些可能是 CDAKEntry 或更具体的子类,如 CDAKAllergyCDAKMedicationCDAKEncounter 等。

  • CDAKCodedEntriesCDAKCodedEntry: 这些代表医学术语系统和概念代码之间的配对(或配对集合)。

  • CDAKPhysicalQuantityResultValue: 一个计量单位(磅、英寸、毫米等)及其相关值(1、2.3、75等)的配对。

编码数据

条目可以包含表示词汇编码的概念代码的 codes。例如,“BMI”(体重指数)可以用 LOINC:39156-5(身体质量指数(BMI)[比率])表示。在没有编码数据的情况下,该概念对互操作性而言实际上是“无意义的”。虽然我们可以阅读文本描述“BMI”,但编码词汇条目对于机器理解信息片段的意图含义至关重要。

向条目添加编码数据

  let aVital = CDAKVitalSign()
  aVital.codes.addCodes("LOINC", code: "3141-9") //weight

词汇密钥是灵活的,但也有些固定密钥有助于确保有“首选”词汇的概念能够能够解决首选与翻译条目之间的选择。

通过 CDAKVocabularyKeys 可以获得已知常用密钥的列表。

然后,您可以像下面这样使用这些常量:

      let aVital = CDAKVitalSign()
      aVital.codes.addCodes(CDAKVocabularyKeys.LOINC, code: "3141-9") //weight

这可能是首选的方法,以确保一致性并确保相关 OID 查找成功。

您还可以提供一个可选的描述性 displayName,它将出现在最终编码的结果中。

      let aVital = CDAKVitalSign()
      aVital.codes.addCodes(CDAKVocabularyKeys.LOINC, code: "3141-9", displayName: "Body Weight") //weight

基本方法

从 CDA XML 导入

从任何位置导入您的 CDA XML。如果您需要一些示例 CDA 文件,波士顿儿童医院已设置了一个优秀的存储库

一旦您有了 XML,您可以通过解析 String 创建一个 CDAKRecord。预期 XML 是一个格式良好的 XML 文档,其根元素为 ClinicalDocument

let myXML:String = ((Get some CDA XML))
do {
  //try to import some CDA XML
  let record = try CDAKRecord(fromXML: myXML)
}
catch {
}

CDA 解析特定错误可能有几种类型,都定义在 CDAKImportError

public enum CDAKImportError : ErrorType {
  case NotImplemented
  case UnableToDetermineFormat
  case NoClinicalDocumentElement
  case InvalidXML
}
  • NotImplemented:这是一个已知的 CDA 文档类型,但导入器(尚未)处理此格式。
  • UnableToDetermineFormat:这似乎是一个有效的 XML 文件,也是一个有效的 ClinicalDocument,但它不包含任何已知的模板 OIDs。
  • NoClinicalDocumentElement:找不到 ClinicalDocument 根元素。
  • InvalidXML:没有 XML 标头。

导出到 CDA XML

一旦您的 CDAKRecord 被填充,您就可以将其导出到支持的 CDA XML 格式之一。

格式如下所示:

  • .c32
  • .ccda
let myOutboundCDAXML = cdakRecord.export(inFormat: .ccda)
print(myOutboundCDAXML)

导入:启用对“不确定”的 CDA 格式的支持

CDAKit 使用 XML 文件 ClinicalDocument 标头中的 templateId OIDs 确定格式(在 bulk_record_importer 中找到)。

  • C32: 2.16.840.1.113883.3.88.11.32.1
  • CCDA: 2.16.840.1.113883.10.20.22.1.2
  • QRDA1:2.16.840.1.113883.10.20.24.1.2(尚未支持并将故意抛出错误)

默认情况下,无法检测任何这些 OIDs 将导致文档解析异常。某些文档模板可能包含有效的 CDA,但不会使用这些 OIDs。它们可能只使用“US General Realm”标头。

  • “MAYBE”:2.16.840.1.113883.10.20.22.1.1(US General Realm 标头)

您可以在尝试导入之前指定全局 CDAKit 单例中的 attemptNonStandardCDAImport 标志来尝试找到任何“可能支持”的文件。

CDAKGlobals.sharedInstance.attemptNonStandardCDAImport = true

然后,您可以尝试导入未指定的 CDA 文件。

CDAKGlobals.sharedInstance.attemptNonStandardCDAImport = true //enable wider support

let myCDAXMLWithoutTheRightType:String = ((Get some non-standard CDA XML))
do {
  //try to import some CDA XML
  let record = try CDAKRecord(fromXML: myCDAXMLWithoutTheRightType:String)
}
catch {
}

HealthKit 桥

您可以在 CDA 模型和 HealthKit 模型之间进行转换,以建立两种不同表示之间的关系。有关方法的详细讨论,请参阅此处

此过程使用一个中间的 CDAKHKRecord 模型来存储 HealthKit 样本。如果您有现有的 HealthKit 样本,只需将它们添加到 samples 集合中。理想情况下,您还能提供一些基本的名字和性别信息。

您可能会遇到两个挑战

  • 概念/临床代码映射:什么是“身高”?CDA 文件中的身高如何与 HealthKit 中的身高相协调?
  • 单位映射:如果我在 CDA 中有“98.6 华氏度”的测量值,我如何将其转换为 HealthKit 样本可以使用的东西?

HealthKit 桥为这两个问题都提供了默认行为,但您几乎肯定会希望根据您的具体需求对其进行修改。

CDA转换为HealthKit

将从CDA导入到HealthKit可以迅速完成,方法是转换CDA导向的CDAKRecord为与HealthKit兼容的记录。为此,您只需从CDA的CDAKRecord初始化一个(HealthKit) CDAKHKRecord

let doc = ((my CDA XML))
do {
  //try to import some CDA XML
  let record = try CDAKRecord(fromXML: doc)

  //OK, let's convert our CDAK record to HealthKit
  let hkRecord = CDAKHKRecord(fromCDAKRecord: record)

  for sample in hkRecord.samples {
    print(sample)//these are all HKQuantitySamples
  }
}
catch {
}

HealthKit到CDA

您可以使用exportAsCDAKRecord方法快速将一个HealthKit CDAKHKRecord转换为CDA导向的CDAKHKRecord。该方法会读取HealthKit桥接记录中的所有samples并尝试将临床概念和相关单位表示转换为CDA结构。

//our wrapping record for HealthKit stuff
let hkRecord = CDAKHKRecord()

//Let's create a HealthKit height
let aUnit = HKUnit(fromString: "in")
let aQty = HKQuantity(unit: aUnit, doubleValue: 72 )
let aQtyType = HKQuantityType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeight)
let hkHeight = HKQuantitySample(type: aQtyType!, quantity: aQty, startDate: NSDate(), endDate: NSDate())

//store the sample in our record
hkRecord.samples.append(hkHeight)

//convert the HealthKit record to CDAKRecord
let cdakRecord = hkRecord.exportAsCDAKRecord()

显式覆盖基于CDA的单位

HealthKit桥接默认输出单位为通过首选项文件管理的设置。

如果您希望为给定的一组数量类型设置默认单位,可以按HealthKit样本类型标识符进行。

CDAKHealthKitBridge.sharedInstance.CDAKHKQuantityTypeDefaultUnits[.HKQuantityTypeIdentifierHeight] = "cm"

您可以通过更改CDAKHKQuantityTypeDefaultUnits修改大量默认单位,这是在运行时存储单位映射的字典。

示例

["HKQuantityTypeIdentifierBasalBodyTemperature", "degF"]

这最初是从CDAKit中的本地CDAKitDefaultSampleTypeIdentifierSettings资源文件中加载的。

该plist使用unit键及其关联的string值。

  <key>HKQuantityTypeIdentifierBasalBodyTemperature</key>
  <dict>
  <key>unit</key>
  <string>degF</string>

基于用户偏好在覆盖单位

如果您想导出HealthKit对象,可能希望让用户的个人单位设置驱动HKUnit选择(如果可能的话)。例如,我们可能将“体重温度”以华氏度导入,但用户可能希望看到以摄氏度呈现的信息。如果他们的个人数量类型的单位设置被设置,这将覆盖全局默认设置。

此功能使用HKHealthStore。假设所有授权都将由您的应用程序管理。

此功能修改了HealthKit样本 - NOT存储在CDAKRecord中的原生CDA数据。您必须在导出HKRecord(exportAsCDAKRecord)之前设置单位偏好。一旦导出到CDAKRecord,任何更改桥接的单位类型将不会被反映。CDA单位类型是固定字符串。

HealthKit在后台线程上做这个,所以在处理UI时请小心。

//create an instance of the HealthKit management service
let healthKitStore:HKHealthStore = HKHealthStore()
//NOTE: you'd need to handle authorizations for your specific sample types

//attempt to set the HealthKit bridge's desired target units to whatever the user's device preferences might be
CDAKHealthKitBridge.sharedInstance.setCDAKUnitTypesWithUserSettings(self.healthManager.healthKitStore)

词汇表和单位映射

这是HealthKit和CDA之间映射中最复杂和“个人偏好”的方面。例如,当您将HealthKit葡萄糖HKQuantityTypeIdentifierBloodGlucose样本导出到CDA时,您希望使用哪个临床词汇表和概念代码?哪个测量单位最为合适?同样,当从CDA导入到HealthKit时,您如何推断“LOINC:2345-7”是一个血糖测量值?以及如何将基于CDA的多种UCUM单位转换为Apple期望的“mg/dl”?

CDAKit提供了两个关键机制来帮助:

  • 一个词汇表映射系统:这简单地从一个HealthKit样本类型标识符如HKQuantityTypeIdentifierBloodGlucose asserting一个特定的词汇表类型和编码值集合
  • 一个单位映射闭包:这试图解释传入的CDA单位的多样性并将其转换为与HealthKit兼容的表示。这是默认的,但cdaStringUnitFinder闭包变量可以被开发人员使用以更改此行为以适应他们的特定需求。

词汇映射

词汇映射尝试将HealthKit数量样本类型标识符与一组已知的词汇类型和相关代码关联起来。

在CDA中,你可能会收到以下编码条目XML格式的检验结果

<code 
  codeSystem="2.16.840.1.113883.6.1"
  codeSystemName="LOINC" 
  code="2345-7" 
  displayName="Glucose, Serum" />

我们如何将其转换成HKQuantityTypeIdentifierBloodGlucose呢?

我们简单地提供了一个从“LOINC:2345-7”到HKQuantityTypeIdentifierBloodGlucose的映射。

CDAKit提供了两个映射来帮助处理这个问题

  • import:仅在从CDA导入值到HealthKit时使用
  • export:仅在从HealthKit导出值到CDA时使用

CDAKit提供了默认的精选“启动”映射,但你可以通过loadHealthKitTermMap方法覆盖所有值。此方法接受基于以下结构定义的Swift字典[String:AnyObject]

  • 主键是你希望绑定的HealthKit样本类型标识符。
  • 在这个结构中,有一个子数组与CDAKit用于映射到词汇的关键/标签绑定。例如:“LOINC”或“SNOMED-CT”。这表明数组中所有后续的编码条目将是该指定词汇。
  • codedisplayName和映射限制的详细说明。code是与displayName(如:“体质指数(BMI)(比率)”)相关的词汇概念代码(如:39156-5)。
   <key>HKQuantityTypeIdentifierBodyMassIndex</key>
   <dict>
            <key>LOINC</key>
            <array>
   <dict>
   <key>code</key>
   <string>39156-5</string>
   <key>displayName</key>
   <string>Body mass index (BMI) [Ratio]</string>
   <key>mapRestriction</key>
   <string>both</string>
   </dict>
            </array>
   ... (more vocabularies)
   </dict> 

单位映射

默认单位映射是一个原型,非常脆弱。它仅仅使用正则表达式和“最佳猜测”的组合来尝试将一组类似UCUM的单元字符串转换成HealthKit可以使用的格式。

如果开发者有他们希望处理的已知CDA结构,建议他们覆盖默认的单位匹配算法。

要做到这一点,只需通过cdaStringUnitFinder变量提供自己的自定义闭包。

  public var cdaStringUnitFinder : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?)?

这个模拟示例会简单地查找任何类似“跳动”的东西,并将其转换成HealthKit兼容的“/min计数”。

var cdaStringUnitFinder : ((unit_string: String?, typeIdentifier: String? ) -> HKUnit?) = {
   (unit_string: String?, typeIdentifier: String?) -> HKUnit? in

   if unit_string == "beats" {
     return HKUnit(fromString: "count/min")
   }

   return nil
}

    //Tell CDAKit to use your custom unit finder
    CDAKHealthKitBridge.sharedInstance.cdaStringUnitFinder = cdaStringUnitFinder

搜索从CDA导入的HealthKit样本

CDAKit的记录导入过程创建的HKQuantitySample将包括一些自定义元数据键。这些旨在帮助您识别和管理基于CDA的样本(合并、删除等)。

public enum CDAKHKMetadataKeys: String {
  case CDAKMetadataRecordIDRoot
  case CDAKMetadataEntryHash
}
  • CDAKMetadataRecordIDRoot:源CDA XML文件中找到的根
  • CDAKMetadataEntryHash:CDA条目的哈希值

您还可以提供自己的Swift [String:AnyObject]字典以添加更多自定义元数据。

许可证

这项工作受Apache 2协议许可。