Templates

RIM-based Templates (TRIM)

This paper describes the HL7 RIM-based template structure used by Tolven called Templated RIM, or TRIM. This structure is used by Tolven Clinical Data Definitions, Tolven MenuData, and Tolven Rules.

In TRIM, RIM structures are used to represent templates that hold clinical data definitions (CDDs). CDDs are designed in the community as broadly as possible without destroying the meaning of any particular CDD. As a result, CDDs are “boiled down” to their essence without the burden of workflow, business constraints, or political influence.

A TRIM is essentially the technical formalization of a CDD. It provides the additional structure needed to maximize the reuse and durability of a CDD over time.

RIM and HL7 data types

TRIM is a “pure RIM” implementation in that it implements the RIM objects and the HL7 data types. However, templates are not “messages” and thus have a different implementation approach from that used with messaging. Indeed, TRIM departs significantly from HL7′s Message Development Framework.

The TRIM approach discourages domain-specific or realm-specific development of software components that for all intents and purposes are cross-domain even though those same components might be subject to different use cases in those domains.

Reuse

The template-based approach to CDD development maximizes reuse of CDDs and thus, in the long-run, dramatically simplifies CDD development. TRIM templates allows a single template definition to be used as both a component and a “top-level” object. For example, a Blood Pressure observation used inside of a vital signs set is identical to a free-standing Blood Pressure observation. Actually, they are the same template – the vital sign template simply refers to the Blood Pressure template as a component. However, the Blood Pressure TRIM containing systolic and diastolic components is not made up of separate TRIMs because those components of a Blood Pressure observation are never created independently.

Further, TRIMs can be defined in a very focused way. For example, observation TRIMs can be defined that might be used in many different settings, from a personal health record to patient-provider, or veterinary settings. In other words, what it is (the TRIM) is separated from how it is used (policy, workflow, regulations, usability).

Instantiation

TRIM removes the distinction between a template and an instance of a template. This is done because, in practice, the instantiation process can involve many phases with each phase layering in new data. Even a fully instantiated and processed object can and often is subsequently used as a template. The simple case is the drug refill or reordering a diagnostic test. In these cases, the original instantiate order is in fact the template for the new order.

Approaches that make a strong distinction between metadata and instance data can become very complex and are ultimately impossible to maintain. For example, one could design a separate relational database table for each possible CDDs. This approach would render a database schema that was virtually impossible to maintain because it would require system-level involvement to implement each CDD. Using XML Schemas (XSDs) to represent each CDD would have about the same effect. Adding tools that facilitated rapid development of models would only serve to make the situation worse.

While these schema-driven approaches are very formal, they tend to overlook model evolution and the fact that in many cases instantiation is a step-wise process, not an all-or-nothing affair. For example, an industry-accepted TRIM may leave aspects of a TRIM open for local interpretation. That locality might be a government. A city. A medical society. An institution. An individual provider or practice group. In most cases, it would be a combination of these. Thus, one person’s instance is another person’s template.

This process continues well past the point where one might assume a TRIM is “fully instantiated”. Consider the case where a treatment is reordered for a patient. The previous instance provides a viable “template” for the new order and has the advantage that it has already been bound to the patient. Or, going in the other direction, an instance may serve as the basis for a new, as yet created template.

Due to this natual blur between template and instance, it is very important that templates and instances not require a transformation step. Therefore, TRIM blends the two structures together into a single representation.

RIM Object Elements

HL7 RIM element names are represented by the name of the class code, not the name of the structure. The class names (not class code names and not code names) do not actually have any semantic meaning, they simply represent the range of attributes supportd by a particular “container”. For example, an Observation holds more attributes than an Act. On the other hand, each class code is assigned a specific functional purpose. In the case of Observation the class name and Observation the class code name, both the structure and function are the same. A class code name of Condition, shared the same class, Observation, because condition has no additional attribute requirements than any other observation.

TRIM hides the class name as a technical detail and only uses the more semantically meaningful class code. It assumes that the set of attributes (represented by the class name) is always the same as the corresponding class code name and that and class codes not corresponding to a class name will have the same structure of the immediatly containing class code.

The following examples may help clarify the relationship between the element names, RIM class and superclass, and class codes.

Class Name SuperClass Class code Name
(elementName)
classCode XSD Ttype
InfrastructureRoot - n/a n/a InfrastructureRoot
Act InfrastructureRoot act ACT Act
    organizer ORGANIZER Organizer
    category CATEGORY Category
Observation Act observation OBS Observation
    condition COND Condition
PublicHealthCase Observation publicHealthCase CASE PublicHealthCase
    outbreak OUTB Outbreak
Entity InfrastructureRoot entity ENT Entity
LivingSubject Entity livingSubject LIV LivingSubject

NonPersonLivingSubject

LivingSubject nonPersonLivingSubject NLIV NonPersonLivingSubject
Person NonPersonLivingSubject person PSN Person

 

Slots

The cornerstone of the TRIM design is the expression of slots in RIM objects. For example, a RIM Act has a title attribute. In TRIM, the attribute is represented in two parts, the “slot” which indicates that, in this case, “a title goes here” and the content of the slot. In the case of the title attribute, the RIM data type for it is ED (encapsulated data). So an explicit ED element is used to represent the ED value of the title attribute.

<observation>
    <title>
       <ED>...</ED>
    </title>
   ...
</observation>

The RIM also allows a ST (string) data type to be used in place of ED so it, too, would be explicit in the title slot.

<observation>
    <title>
      <ST>...</ST>
    </title>
   ...
</observation>

In the HL7 RIM, null and null flavor mean two different things. A null attribute means that the attribute is completely missing. In other words, there would simply be no title slot at all. However, a null flavor acts as a placeholder. It is not a value per se but it explains why the value is not there. In the following example, the title was asked for but not answered.

<observation>
    <title>
      <null>ASKU</null>
    </title>
   ...
</observation>

The slot approach makes cardinality explicit. For example, an object may have multiple IDs (RIM notation is SET<II>. Therefore, the id attribute can have one or more Instance Identifier (II) values.

<observation>
    <id>
         <II><root><oid>1.2.3.4.5.6</oid></root><extension>11111</extension></II>
         <II><root><oid>6.5.4</oid></root><extension>11111</extension></II>
    </id>
    <title>
        ...
    </title>
   ...
</observation>

In addition to the attribute slots described above, relationship slots are also defined by TRIM. All of them are listed in this table.

Rim Object Attribute Connected to RIM Object
Participation act Act
  role Role
Act Relationship source Act
  target Act
Role Link source Role
  target Role

 

RIM objects can have identifiers. An ID is required when relating one RIM object to another. An ID is not required when a RIM object is directly embedded within another. For example, in the HL7 Laboratory Result Event RMIM, the order being fulfilled is referenced by ID whereas the reference range act is embedded directly in the result act.

<observation>
    <fulfills>
        <target>
            <reference>id-of-an-order</reference>
        </target>
    </fulfills>
    <hasReferenceValues>
        <target>
            <observation>
                <mood>EVN.CRT</mood>
                ....
            </observation>
        </target>
    </hasReferenceValues>
</observation>

RIM objects can also have an internal identifier. This id is only valid or useful in the computer system in which the object is currently stored. Therefore, the internal id is either removed or transformed to a regular identifier when communicated outside of the computer system in which the internal id has relevance.

<observation>
    <internalId>123456<internalId>
    <id>
    </id>
</observation>

Slot Semantics

Attribute slots can be populated with one or more value facets. Value facets are HL7 data types as used in the examples above. When a slot has a value facet, the slot is considered instantiated.

Relationship slots, such in act relationships and participations, work in a similar way. When a relationship is present, either by direct presence of another act, or by a reference to another act, the relationship slot is considered instantiated.

When all attribute and relationship slots are instantiated, the template is fully instantiated. This process is recursive in that the top-level template may reference other templates that in turn can be instantiated.

A null attribute slot (not a null flavor) or a null relationship slot is represented either by a missing slot or a slot containing no facets. There is no semantic difference between the two representations. In either case, an empty slot or a missing slot means that the slot, although valid in the RIM, is undefined and should not be populated or used in this particular template.

When a RIM attribute slot or relationship slot contains TRIM facets (described below) but does not contain a value, the slot is considered defined, but not instantiated.

If a slot contains both TRIM facets and values (or a null flavor), it is considered both instantiated and defined. TRIM facets can be removed from a slot once the slot is instantiated. One important reason to retain TRIM facets is for audit purposes: Both the value and details of its collection remain available. Another reason is that the instance can be reused as a template such as when re-ordering a treatment.

RIM (value) Facets

Facets in this category represent instantiated components in an attribute or relationship slot.

A datatype facet, as discussed elsewhere, represents a concrete value for a slot. As will be discussed in more detail below, some datatypes contain slots which in turn contain additional facets. Therefore, a datatype is not necessarily “atomic”.

A reference facet references an existing instance. A reference in this regard is an intentional, concrete, and unambiguous reference to a unique existing object. In a message, such concrete references are rare and normally are not used. However, TRIM depends on this constrained definition of a reference while the template/instance is at rest. A reference facet is only valid where a RIM object with an ID can be referenced. That means in the source or target of an act relationship, role link, or in a participation. The id is all that is needed to identify the referenced object. The referenced object must match the semantics of the slot where it is referenced.

<observation>
    <participations>
        <subject>
            <role>
                <reference>pat-123456</reference>
            </role>
        </subject>
    </participations>
</observation>

Since a reference facet is intrinsically internal, if a message were to be sent, it would be replaced by the actual object, not a reference to it. An instance identifier (II) datatype is not the same as a reference.

A null flavor (exceptional value) facet indicates that the intended object is not present and why. A null flavor is a substitute for a datatype facet. [In HL7 XML ITS, null flavor is an attribute of the datatype itself.] A null flavor says nothing about which value it stands for, only that it occupies the slot where a datatype might have otherwise been used.

For example, if the value of the birthTime attribute of a living subject (person) was asked but unknown, then the value of the slot is unknown because there is no value. Nevertheless, a null flavor occupying a slot fully qualifies the slot as instantiated.

<person>
    ...
    <birthTime>
        <null>ASKU</null>
    </birthTime>

</person>

TRIM Facets

Anywhere an instance of a RIM object or Data type (i.e. a value facet) can occur, it can be replaced with one of several special TRIM facets. While TRIM facets facilitate instantiation, they do not qualify the slot as instantiated.

A new facet indicates that a slot requires a datatype to be supplied, presumably by a user. A template used for an CDD should make no presumption about the user interface, only about the constraints applied to the data capture. Nevertheless, the connection between model and specific user interface behavior can be more pronounced in healthcare because, for various reasons, the full meaning of the underlying concept might be influenced by the way the data is captured. For example, the visible length of a text field for the answer to an open-ended question might be a factor in the length of the response entered by the user. When provided in an CDD, such UI parameters are taken as hints by the underlying implementation.

Several examples follow…

The following creates a new PQ datatype by setting the units property to kg and asks for the value property to be input. The input contains an optional validator which checks that the input value is in the range between 1 and 10000 inclusive.

<new datatype="PQ">
    <label language="en">Weight in kg</label>
    <hint language="en">Enter weight, light clothes only...</hint>
    <help language="en">More detailed help...</help>
    <set property="units">kg</set>
    <input type="integer" property="value">
        <validRange low="1" high="10000"/>
    </input>
</new>

The following trim:new creates a new CE datatype with the value selected from a valueSet named injectionSite. The order of the values are presented in the order they occur in the ValueSet definition.

<trim:new datatype="CE">
    <select multiple="false">
        <valueSet>injectionSite</valueSet>
    </select>
</trim:new>

The following trim:new creates a new CE datatype with the value selected from two valueSets named injectionSite and bodySite. Duplicates are eliminated and the result is sorted by description for presentation to the user.

<trim:new datatype="CE">
    <select multiple="false" sort-"description">
        <valueSet>injectionSite</valueSet>
        <valueSet>bodySite</valueSet>
    </select>
</trim:new>

The following trim:new creates a new address (AD). An address consists of several address parts. A use code is specified. In this case, home (H) is used. Although no validation is shown, it would not be unusual to include zip code to city-state validation. Or, perhaps a more complete address would specify conditional address formats based on country.

<trim:new datatype="AD">
        <label language="en">Home Address</label>
        <set property="use">H</set>
    <new datatype="ADXP">
        <input type"string"/>
    </new>
    <new datatype="ADXP">
        <label language="en">Address Line 1</label>
        <set property="partType">SAL</set>
        <input type"string"/>
    </new>
    <new datatype="ADXP">
        <label language="en">Address Line 2</label>
        <set property="partType">SAL</set>
        <input type"string"/>
    </new>
    <new datatype="ADXP">
        <label language="en">City</label>
        <set property="partType">CTY</set>
        <input type"string"/>
    </new>
    <new datatype="ADXP">
        <label language="en">State</label>
        <set property="partType">STA</set>
        <input type"string"/>
    </new>
    <new datatype="ADXP">
        <label language="en">ZIP</label>
        <set property="partType">ZIP</set>
        <input type"string"/>
    </new>
</trim:new>

The following trim:new creates a specific code in a CD. It also provides a way to specify a qualifier within the CD.

<trim:new datatype="CD">
    <label language="en">Home Address</label>
    <set property="code">C12345</set>
    <set property="codeSystemName">UMLS</set>
    <new datatype="CE">

    </new>
    <select multiple="false" sort-"description">
        <valueSet>injectionSite</valueSet>
        <valueSet>bodySite</valueSet>
    </select>
</trim:new>
TBD TBD TBD
<secret/>
    <textarea>
    <range low="1" high"10" step="1"/>
    <upload/>
    <compute property="value">
    <select multiple="true" optional="true" >
    <default></default>
    <constraint property="value"></constraint>
<selectOne>
</selectOne>
    <input property="value" >

    </input>
</new>
<new datatype="CD">
    <property name="code">
    </property>
    <property name="qualifier">
</new>
<new datatype="ST">
    <property name="value">
    </property>
</new>
<new datatype="ED">
</new> 

A bind facet indicates that an instance of the the named CDD is sought. For example, the bind facet is used in many CDDs to indicate that a patient participation is needed. Since a template is ultimately a real RIM object, the type of the bound RIM object must comply with the RIM semantics of where it is used. For example, it is invalid to refer to a role class in the target of an act relationship.

Note: Read <bind>x</bind> as “I am looking for an instance of x”.

Binding can have specific instructions controlling the bind request. A common instruction would be a date range. For example, an CDD for a certain diagnostic procedure might ask for a patient weight taken within the last 24 hours. If such a template instance is found, then a reference to that observation can be added to the slot. If not, then that bind is skipped.

Multiple binds can be specified in a slot.

A choice facet is used when the template is equally valid when one of a choice of facets is used. For example, an CDD template might specify that the weight of the patient can be entered in pounds or in kilograms. So a choice facet surrounds the two

In this case only one CDD is needed because there is a meaningful mathematical conversion between the two types of values. If the actual meaning of the CDD were to change as a result of a choice, then such an CDD should be split into two CDDs.

Continuing the previous example, if a recent patient weight is not found, then a new facet can be added requesting that the weight be entered.

A compute facet is used when the results of a calculation are required.

The choice facet is also used to make null flavors explicit. For example, one of the choices for the value in a patient questionnaire might be unknown. Therefore, three choices are available.

Bind and new facets can also be combined in a choice to good effect. The application might then present successful bind alternative(s) as well as the option of entering a new value if the user decided that the bind was not adequate.

 

Data type Decomposition

Many of the HL7 data types are complex. In order to take full advantage of the contents of complex data types in templates, TRIM decomposes data types in order to provide control over individual aspects of a single attribute. For example, say an address attribute, which is an AD data type, needs the state and country set to a specific value while the rest of the address is to be filled in by the user.

Decomposition facilitates the addition of constraints at the data type level. In the following example, we wan to specify that the value of an observation for patient weight must be supplied in units of kg or lb only. No other weight, mass, or multiplier prefixes are allowed.

<!-- DOES NOT WORK -->
<trim:valueSet name="weightUnits">
    <value>kg<value/>
    <value>lb<value/>
</trim:valueSet>
<rim:observation>
    <value>
        <PQ>
            <value>...</value>
            <unit>$weightUnits</unit>
        </PQ>
    </value>
   ...
</rim:observation>

The approach above overlooks the fact that validation would be different depending on the units. So it would help if the value for this particular observation could be expressed as explicit choices, each with its own validation. In the following, we introduce the choice element. Each child of the choice element is a valid alternative for implementation. The <trim:choice> element would therefore be replaced with one of the children (choices) when the item is instantiated.

<rim:observation>
    <value>
        <trim:choice>
            <PQ>
                <value></value>
                <units>kg</units>
            </PQ>
            <PQ>
                <value></value>
                <units>lb</units>
            </PQ>
            <null flavor="ASKU"/> <!-- Asked but unknown -->
            <null flavor="NAV"/> <!-- Not available -->
        </trim:choice>
    </value>
   ...
</rim:observation>

This example also includes null values as valid choices – that is, no value whatsoever might be available for a particular reason.

Data type Representation

Data type elements are represented by a type name, in all caps.

<TS>20070115121500.000+0800<TS>

Therefore, an attribute containing a TS (point in time) data type contains the attribute name and an explicit data type name.

<effectiveTime>
    <TS>20070115121500.000+0800<TS>
</effectiveTime>

When an attribute implies or specifies alternate data types, then those alternate data types may be specified instead. For example, in the following a time interval use used instead of a point in time.

<effectiveTime>
    <IVLTS>
       <low>20070115121500.000+0800</low>
       <width><value>1</value><units>hour</units></width>
    </IVLTS>
</effectiveTime>

However, the template is always explicit about which data types are allowed in any specific template. An application is not free to make a substitution beyond that which is explicitly offered in the template.

Composite data types are represented by explicit elements (not XML attributes). This facilitates explicit constraints about specific data type properties. In the following example, the code system property might be a fixed literal while the code attribute is allowed to be input from a user application.

<CD>
    <code>1234</code>
    <codeSystem>1.2.3.4</codeSystem>
</CD>

Atomic data types need no further decomposition. Some have simple attributes, as shown. Most attributes are optional or have reasonable defaults such as gregorian calendar for point in time (TS) data types.

<ST language="en">a simple string</ST>
<CS>active</CS>

<TS calendar="GREG">20070115121500.000+0800</TS>
<UID>07E02356DE1A</UID>
<OID>12.34.56</OID>
<BL>true</BL>
<REAL>765.123</REAL>
<INT>45</INT>
<ADXP partType="STR">123 Elm St</ADXP>
<ENXP partType="GIV" qualifier="BR">Evelyn</ENXP>
<MO currency="USD">10.53<MO>

All other data types are composite, generic, or abstract.

Composite data types can generally be treated in the same way as RIM attributes. For example, a person name (PN) is composed of components that can be defaulted, validated, and constrained in the same way as RIM attributes. Therefore, their XML representation is similar. For example, in the PN data type, an property is represented as a normal element which contains attributes such as validTime, use, given, and family.

<name>
    <PN>
        <use>L</use>
        <validTime>
            <IVLTS><low>20070115</low></IVLTS>
        </validTime>
        <given>Evelyn</given>
        <family >Thorne</family>
    </PN>
</name>

A physical quantity (PQ) has a similar structure

Substitutions can be made where there is no design-time ambiguity.

Specified Data type Allowed Substitution Justification
REAL INT Unambiguous conversion
ED ST ST is derived from ED
IVL<TS> TS Promotion allowed
GTS TS Derivation
GTS SET<TS> Derivation
GTS IVL<TS> Derivation
     

These are not conversions, per se, only that the implementation has a way to unambiguously convert the data type, if needed. For example, it would be common to supply an IVL<TS> or a TS where GTS is required.

The BL, CS, ST, INT, and REAL data type also appear as data type attributes. When this occurs, the data type is implied by TRIM. For example, the ST data type accepts a language attribute containing a CS data type which is itself contains an ST. However, in practice, this use of CS in a data type is taken to mean a simple string and in this example is implicitly validated against RFC 2277 for language codes.

<ST language="en">Spaghetti and French bread for dinner.</ST>

When the language attribute applies to the data type used in a slot, that slot can include multiple occurrences of the data type, one for each language. If a data type does not have a language attribute, it means the language is either unknown or applies as a default. In the following example, “Dude” is used when the language requested is not found in the list. The content of a string without a language attribute does not imply any particular language. It is up to the reader to determine if they can understand the contents of such a string. Therefore, its use is discouraged.

<ST language="es">Paciente</ST>
<ST language="en">Patient</ST>
<ST language="de">Patient</ST>
<ST language="nl">Patiënt</ST>
<ST language="ja">患者</ST>
<ST language="zh">病人</ST>
<ST>Dude</ST>

TRIM namespace

A RIM object template is created by adding a template element to a regular RIM element. The “trim:” namespace is used here to denote “templated RIM” elements. rim: is used where necessary to “toggle back” to normal RIM elements.

<observation>
    <templateId>urn:wikihit.org:GCS:2914</templateId>
    <trim:template>
            <description>
                <ST language="en">Glasgow Coma Scale</ST>
                <ST language="de">Glasgow Coma Scale</ST>
                <ST language="es">Escala Glasgow</ST>
                <ST language="fr">Échelle de Glasgow</ST>
                <ST language="zh">昏迷指數</ST>
                <ST language="vi">Thang điểm hôn mê Glasgow</ST>
            </description>
    </trim:template>
    ...
</template>

In this way, template elements modify or enhance the behavior of RIM elements.

 

Template Blending

It would be tedious and error prone to exhaustively define every aspect of every individual CDD. Indeed, large numbers of CDDs will typically fall into categories that have identical requirements. A very simple example is that most CDDs probably needs to be associated with a patient. But, instead of adding patient to each CDD definition, an easier and more flexible approach would be to build CDDs on top of skeleton CDDs. Now, the term skeleton is relative – the CDD itself is a skeleton as well. But that kind of layering has its own problems so we won’t “build on top of” but rather use a blending or mix-in technique.

For illustration, consider four over-simplified CDDs: an observation event CDD, a patient act CDD, a patient height observation CDD, and a height CDD.

HL7 allows us to define many moods around such an observation but for the moment we will limit this example to what the RIM calls an Event mood act, which is the actual measurement.

In the height CDD, we would like to focus on the details of the a height observation such as the allowable units of measure and the method by which the height was acquired. to the extent possible, we would like the height CDD to be as broadly applicable as possible without diluting its core meaning.

We do not want to be distracted by details common to all similar acts such as the fact that it must be associated with a patient or that it should be associated with an author and/or performer. We can also safely assume that all observation events involve a time of observation (effectiveTime) and may indicate when the observation became available in the patient record. Even if all those details have been worked out, we do not want to copy them into the height CDD for fear of diluting the central meaning and purpose of that CDD.

In this approach, two or more templates can be blended together to create a new template. We use this technique to create our final CDD, the patient height observation CDD which is a combination of the patient, observation and height CDDs. Now, this is not a parent/child type composition. Technically, each of the templates describes the same exact object. It just contributes different aspects of that object.

Here is some abbreviated XML for each CDD involved in the above scenario:

  <!-- Height -->
01 <act>
02     <templateId>urn:wikihit.org:HEIGHT:0</templateId>
38     <moodCode>EVN</moodCode>
38     <classCode>OBS</classCode>
03     <code>
04         <code>C0487985</code>
05         <codeSystemName>UMLS</codeSystemName>
06         <codeSystemVersion>2006AC</codeSystemVersion>
07     </code>
07   <observation>
07     <value>
08        <trim:new datatype="PQ">
09            <label language="en">Height in cm</label>
10            <set property="units">cm</set>
11            <input type="integer" property="value"/>
12        </trim:new>
13        <trim:new datatype="PQ">
14            <label language="en">Height in inches</label>
15            <set property="units">in</set>
16            <input type="integer" property="value"/>
17        </trim:new>
17     </value>
17   </observation>
17 </act>
17
   <!-- Patient Act -->
18 <act >
19     <templateId>urn:wikihit.org:PAT-ACT:0</templateId>
20     <participations>
21         <subject>
22         <trim:bind>
23             <templateId>urn:wikihit.org:PAT:0</templateId>
24         </trim:bind>
24         </subject>
25     </participations>
26 </act>

   <!-- Observation (point in time only)-->
27 <act>
38     <mood>EVN</mood>
38     <classCode>OBS</classCode>
28     <trim:template>
28        <templateId>urn:wikihit.org:OBS:0</templateId>
28     </trim:template>
31     <effectiveTime>
32        <new datatype="TS" default="now">
33            <label language="en">Observation time</label>
34            <input type="time"/>
35        </new>
36     </effectiveTime>
37 </act>

   <!-- Patient Height Observation Event -->
38 <act>
38     <mood>EVN</mood>
38     <classCode>OBS</classCode>
39     <trim:template>
39        <templateId>urn:wikihit.org:PAT-HEIGHT-OBS:0</templateId>
39     </trim:template>
40   <trim:blend>
41     <templateId>urn:wikihit.org:OBS:0</templateId>
42     <templateId>urn:wikihit.org:PAT-ACT:0</templatId>
43     <templateId>urn:wikihit.org:HEIGHT:0</templatId>
44   </trim:blend>
45 </act>

Several things to notice:

Act (18) is compatible with observations for blending (42) because in the RIM, Act is more abstract than Observation. Thus, everything in an Act “fits” into an Observation.

Note: It is not possible to blend an Observation into an Act – it doesn’t fit. TRIM does not not allow such blending even if a particular Observation instance has only the subset of attributes allowed in an Act. In other words, the restriction is applied at design time, not run-time.

A <bind> is used at line 22 to indicate that an instance of a template is needed.

The only attributes that should require input are the height value, line 7-17, and the effective (observation) time line 31-36, which is defaulted with the current time.

The height observation is focused only on what is critical to its core meaning. Thus, if height retains its meaning in different settings, then the CDD should be unique. The blending process is then used to apply this CDD into different situations. For example, the same CDD might be used in both an event (such as described here) and a goal.

Used in a goal, the height CDD would be blended with a goal template rather than an event template. Not only will the goal have a different mood code but the dates, while structurally similar to the event, could have a different meaning such as on-or-before the specified date.

If the height CDD itself also changes, then there must be a separate CDD. For example, the height CDD implies a specific height. A growth chart would use a height range which would have to be a separate CDD.

HL7 note: This style of template is very different from CMETs. a CMET can be used to relate additional objects to the focal object whereas a TRIM template can be used to add attributes to the focal object itself.

The blend operator (40-44) in this case is unconditional: All three templates are blended together resulting in an object that, if it were to be instantiated, would look something like this (most TRIM elements removed for clarity):

<observation>
    <internalId>1234654</internalId>
    <trim:template>
       <templateId>urn:wikihit.org:PAT-HEIGHT-OBS:0</templateId>       <including>
           <templateId>urn:wikihit.org:HEIGHT:0</templateId>
           <templateId>urn:wikihit.org:PAT-ACT:0</templateId>
           <templateId>urn:wikihit.org:OBS:0</templateId>
       </including>
    </trim:template>
    <mood>EVN</mood>
    <classCode>OBS</classCode>
    <effectiveTime>
        <TS>20070115151300</TS>
    </effectiveTime>
    <availabilityTime>
        <TS>20070115151300</TS>
    </availabilityTime>
    <code>
        <code>C0487985</code>
        <codeSystemName>UMLS</codeSystemName>
        <codeSystemVersion>2006AC</codeSystemVersion>
    </code>
    <value>
        <PQ><unit>kg</unit><value>75</value></PQ>
    </value>
    <participations>
        <subject>
            <target>
                <reference>pat-123456</reference>
            </target>
        </subject>
    </participations>
</observation>
 

The fact that this object has been blended is obvious by the <including> entries in the trim:template element. Although we wouldn’t normally use a blended object as an CDD, it would almost always appear in the result of an instantiation in the medical record.

Notice that the dates have been filled in and that the subject participation has been bound to a specific patient.

Blending vs Composition

When CDDs are combined using composition, such as a vital sign CDD being composed of a BP, temperature, pulse, and other CDDs, that process is composition. To show how blending and composition work together, consider a Blood Pressure CDD which is composed of two other CDDs, a systolic and diastolic observation. (Ignore the fact that BP is often part of a Vital Signs CDD for the moment). Blending is not used to define the BP CDD because BP by definition contains the two readings. And we will assume for the moment that the individual readings would never appear alone (although a BP observation might be made with one of the readings missing).

  <!-- Blood Pressure -->
01 <observation>
02     <trim:template>
02        <templateId>urn:wikihit.org:BP:0</templateId>
02     </trim:template>
03     <code>
04         <code>C0487985</code>
05         <codeSystemName>UMLS</codeSystemName>
06         <codeSystemVersion>2006AC</codeSystemVersion>
07     </code>
08     <relationships>
09         <component>
10             <trim:bind>
11                 <templateId>urn:wikihit.org:BP-SY:0</templateId>
12             </trim:bind>
13         </component>
14         <component>
15             <trim:bind>
16                 <templateId>urn:wikihit.org:BP-DI:0</templateId>
17             </trim:bind>
18         </component>
19     </relationships>
20 </observation>
21
   <!-- Systolic BP -->
24 <observation>
25     <trim:template>
26        <templateId>urn:wikihit.org:BP-SY:0</templateId>
27     </trim:template>
28     <code>
29         <code>C0487985???</code>
30         <codeSystemName>UMLS</codeSystemName>
31         <codeSystemVersion>2006AC</codeSystemVersion>
32     </code>
33     <value>
33           <PQ>
34               <unit>mmHg</unit>
35               <value>
34                   <trim:validateRange low="0" high="1000"/>
35               </value>
36           </PQ>
37     </value>
38 </observation>

   <!-- Diastolic BP -->
41 <observation>
42     <trim:template>
43        <templateId>urn:wikihit.org:BP-DI:0</templateId>
44     </trim:template>
45     <code>
46         <code>C0487985???</code>
47         <codeSystemName>UMLS</codeSystemName>
48         <codeSystemVersion>2006AC</codeSystemVersion>
49     </code>
50     <value>
51         <bind>
52             <PQ><unit>mmHg</unit></PQ>
53         </bind>
54     </value>
55 </observation>

<!-- Patient BP Observation Event -->
58 <observation>
59     <trim:template>
60        <templateId>urn:wikihit.org:PAT-BP-OBS:0</templateId>
61     </trim:template>
62   <trim:blend>
63     <templateId>urn:wikihit.org:OBS:0</templateId>
64     <templateId>urn:wikihit.org:PAT-ACT:0</templateId>
65     <templateId>urn:wikihit.org:BP:0</templateId>
66   </trim:blend>
67 </observation>

In this example, the BP CDD directly references both the systolic and diastolic CDDs. The blending template, at the bottom, creates a complete CDD composed of the BP and it requests to include attributes from Observation and Patient act. However, there is no similar blending CDD that blends either of the two child CDDs because, in this case, those components do not make sense as stand-alone CDDs.

ValueSet

Value sets are used to facilitate select operations by constraining the choices available to a particular input select which is used for a particular attribute. A valueSet has a unique name. The contents of a ValueSet usually depends on the DataType of where it will be used. For example, a CD attribute slot will require a value set containind CDs. The CD datatype can contain other value sets (laterality, severity, color, etc).

Another variation of ValueSet is a category ValueSet which contains a list of templates. Categories are often used in creating a relationship between one CDD and another CDD. For example, when entering a reaction for an allergy, a list of all symptoms can be presented.

Technically, there are two versions of ValueSetValues. The primary version is hierarchical such that a valueSet can contain values as well as other ValueSets as would be the case in a hierarchy. Cakes would be defined in the the Cake category, pies in the Pie category. The Dessert category would contain just two entries, the Pie category and the Cake category.

The FullValueSetValues is constructed automatically from the hierarchical ValueSetValues by including each value in each valueSet contained within it. Thus, the Pie and Cake categories would look the same as the hierarchical ValueSet list. But the Dessert valueSet would contain all of the combined entries from both Pie and Cake rather than just the two Category entries. This FullValueSetValue list is not separately editable.Duplicates are eliminated when combined in this list.

TRIM Operators

The templated RIM approach to CDD development is intended to be relatively simple to learn and use. As such, language constructs are kept to a minimum to delegated to specialized areas when possible.

Form

For example, there is no doubt that most CDDs will be used in a user interface application and will thus need additional decoration with form behavior. Such behavior can be layered onto an CDD without having to be embedded in the template language.

Bind

Bind expresses a formal need for information not currently present in a template. For example, a vital signs set will bind to separate CDDs that make up its components. Binding provides a level of separation that avoids

By default, binding is left to the interpretation of the application.

BELOW is [TBD]

Blend

 

Harvest

 

Choice

 

BELOW is [TBD]

HL7 Differences

The TRIM design represents exact HL7 RIM and data type semantics. However, there are many differences in the ITS areas.

The careful observer will notice the removal of clone names from the XML Schema used by TRIM. For example, the subject of an act participation is explicit in the TRIM schema:

<participation>
    <type>SBJ</type>
    ...
</participation> 

whereas the HL7 XML ITS uses a clone name

<subject>
    ...
</subject>

which requires intrinsic knowledge of the domain model to know what the element means. This can result in semantic drift when different models use different clone names to represent the same RIM object.

At first blush, the clone approach seems more compact even though it requires knowledge outside of the template to know how it equates to the RIM. However, this brevity is soon lost by the need for more model elements to represent small variations or alternatives in the model.

For example, participation type (record target and subject in this case) might be the only difference in the following fragment:

<participation>
    <trim:choice>
        <rim:type>SBJ</rim:type>
        <rim:type>RCT</rim:type>
    </trim:choice>
    ...
    <role>
        <trim:bind>
            <templateId>urn:wikihit.org:PAT:0</templateId>
        </trim:bind>
    </role>
</participation>

Being able to provide variation only where it is needed significantly reduces the overall bulk.

 

Functions

The following functions manipulate templates often transforming a template to an instance.

New Version

Merge Templates

Add local behavior to a template such as how to generate new instance IDs.

 

Back to the top
Back to the top

Support & Consulting

Tolven offers a number of training packages and access to an ongoing Webinar series to enable you to make the most of the Tolven Platform and application framework. For ongoing support and maintenance, we offer four levels of technical support to enable you to select what's right for your organization.

Visit TolvenHealth.com

In Production

The Tolven Platform is rapidly becoming the most widely adopted open source solution for healthcare information technology globally. Tolven clients in Europe, North America, and Asia are leveraging the breadth of solutions the Tolven technology can support to serve their needs.

See sample client descriptions

The Tolven Platform

The Tolven Platform takes advantage of a broad, flexible, and open source architecture that gives healthcare and life sciences professionals as well as patients the information they need in an open and extensible solution. The Tolven Platform and applications have global applicability.

Read more