A comprehensive list of all HealthVault data types is available from the HealthVault developer center at http://developer.healthvault.com/types/types.aspx. Each type has properties that determine to a great extent how items are created and used. To understand a type better, let’s take a deeper look at the example of the Weight Measurement type.
Figure 4-6 shows
the properties of the Weight Measurement data type that are common to
every data type from the HealthVault developer center (http://developer.healthvault.com/types/type.aspx?id=3d34d87e-7fc1-4153-800f-f56592cb0d17).
Each HealthVault type has a unique identifier; this
id
is used by the HealthVault APIs to identify the
type. In the case of Weight, it is 3d34d87e-7fc1-4153-800f-f56592cb0d17.
A type sets the uncreateable
property to true if no
application can create such a type in a user’s HealthVault record; a
good example of this is the Basic type. The immutable
property is true if no application can modify or update an instance of
that type in the user’s HealthVault record; a good example of this is
the CCR type. The property singleton
is true if only
one instance of that type can exist in a user’s HealthVault record; a
good example of this is the Basic Demographic type.
Additionally, the list of transforms is a property associated with the type. Transforms are built-in XSLT transformations available for a particular thing type. These transforms let you convert the XML associated with a particular type to various formats, such as HTML, to a representation compatible with various popular health care standards, or to an older or newer version of the same type.
Common among all the types are the form
, stt
, and mtt
transforms. form
provides an HTML table representation
of an instance of the entire thing. stt
, which stands for “single type
transform,” provides a row- based representation of the type so that
it can be viewed as a list of instances of the same type. mtt
, or “multiple type transform,”
provides a row-based representation of the type so that it can be
combined and viewed with multiple HealthVault types. Each row in
mtt
has a summary attribute
representing the details of the type. The main difference between
stt
and mtt
is that stt
has an XML attribute for each
meaningful data element of the type, whereas mtt
summarizes all the meaningful data
elements in one string in the summary
attribute.
One can use the HealthVault PowerShell plug-in to view each
source of the transforms. Example 4-2 shows how to save
the form
transform for the Weight
thing type.
Example 4-2. Saving the form XSLT transformation for Weight thing types to a file
PS \> (Get-ThingType 3d34d87e-7fc1-4153-800f-f56592cb0d17).TransformSource["form"] | out-file Weight.xsl
The columns on the type definition page in the HealthVault Type Explorer define the column header, .NET data type, and width for each column. It’s handy to view this information about the type in a data grid.
Example 4-3 shows
the multitype table transformation XML returned by the HealthVault
platform for the Weight type. We can see the columns ranging from
wc-id
(type identification) to
summary
(summary information of
the type).
Example 4-3. Weight mtt XML for the Weight type
<data-xml transform="mtt"> <row wc-id="34655fb4-a6c8-4d47-85f1-dbc6e09b952a" wc-version="0f57073a-0795-4867-9c9f-bcb99d2fa681" wc-note="" wc-tags="" wc-date="2011-12-23 11:17:47" wc-type="Weight Measurement" wc-typeid="3d34d87e-7fc1-4153-800f-f56592cb0d17" wc-source="" wc-brands="" wc-issigned="false" wc-flags="" wc-ispersonal="false" wc-isdownversioned="false" wc-isupversioned="false" wc-relatedthings="" wc-state="Active" summary="173 lbs" /> </data-xml>
In our Quantified Self application, we can use the mtt
transform to easily display multiple
types in the same table for self-analysis. In Example 4-4, Lines – construct
and fetch our query from HealthVault; note that in Line we ask the HealthVault platform to apply
the mtt
transform on the returned
items. In Line , we select the row for
each data-xml mtt
transform. We
then display the wc-date
,
wc-type
, and summary
columns (Lines –). Different
applications can choose to show different columns. Individual type
columns, such as weight
for
Weight, are available in single type transform (stt
), whereas a summary column summarizes
this information in mtt
. The
HealthDataItemGrid
control is
also available from the HealthVault .NET SDK to show this
information automatically.
Example 4-4. Viewing multiple HealthVault types in a data grid
protected void Btn_ShowWeeklyReadingsTextSummary_Click (object sender, System.EventArgs e) { HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher(); HealthRecordFilter filter = new HealthRecordFilter( Emotion.TypeId, DietaryDailyIntake.TypeId, Weight.TypeId, SleepJournalAM.TypeId, Exercise.TypeId); filter.EffectiveDateMin = DateTime.Now.Subtract(new TimeSpan(7, 0, 0, 0)); searcher.Filters.Add(filter); filter.View.TransformsToApply.Add("mtt"); HealthRecordItemCollection items = searcher.GetMatchingItems()[0]; DataTable dataTable = new DataTable(); dataTable.Columns.Add(new DataColumn("Date", typeof(string))); dataTable.Columns.Add(new DataColumn("Type", typeof(string))); dataTable.Columns.Add(new DataColumn("Summary", typeof(string))); foreach (HealthRecordItem item in items) { XmlNode mttDocument = item.TransformedXmlData["mtt"] .SelectSingleNode("data-xml/row"); DataRow row = dataTable.NewRow(); row["Date"] = mttDocument.Attributes["wc-date"].Value; row["Type"] = mttDocument.Attributes["wc-type"].Value; row["Summary"] = mttDocument.Attributes["summary"].Value; dataTable.Rows.Add(row); } Grid_ReadingsTextSummary.DataSource = dataTable; Grid_ReadingsTextSummary.DataBind(); Grid_ReadingsTextSummary.Visible = true; }
Once we have the data grid configured, we can view the summary of all types in the same column structure. Figure 4-7 shows how this information is displayed in our Quantified Self application.
Note
The CCR HealthVault type
(1e1ccbfc-a55d-4d91-8940-fa2fbf73c195) has a tohv
transform that converts the data in
that type to individual HealthVault elements.
In addition to the use of transforms to convert types to
different representations, the HealthVault method schema provides
a <final-xsl>
element in each method header.
final-xsl
converts the data
returned by the method call to built-in transforms, such as
converting to CCR (toccr
), CCD
(toccd
), CSV (tocsv
), or RSS (torss
). final-xsl
also allows the caller to
specify a custom-built XSLT transform that the HealthVault
platform runs on the output before sending it to the
requester.
The final-xsl
element is
specified between the <country>
and <msg-time>
elements in the header
of a method. In the HealthVault .NET SDK, one can call this
functionality by using the GetTransformedItems
method. In the Java
.NET Open Source library, this functionality can be used through a
call to request.setFinalXsl("
transform
name or transform source
")
.
HealthVault data types can have multiple versions. As the HealthVault ecosystem matures, existing types need to be updated or modified to match new use cases. Medications, Basic Demographic Information, and Family History are good examples of types that have multiple versions. You will notice that the older Medication datatype (which is available at http://developer.healthvault.com/pages/types/type.aspx?id=5c5f1223-f63c-4464-870c-3e36ba471def) has an up-version transform, and the newer Medication datatype (http://developer.healthvault.com/pages/types/type.aspx?id=30cafccc-047d-4288-94ef-643571f7919d) has a down-version transform. Through these transforms, HealthVault provides an easy way to move data between an older and newer version of a data type.
Note
Versioning of data types is unique to HealthVault among personal health data platforms. Personal health records are meant to exist over a lifetime, and this feature makes moves seamless from older health items to newer health items.
Now that we understand the high-level properties associated with a type and have used the MTT display transform to show the summary of all data types in our application, let’s take a closer look at what is entailed in a type’s schema, with the specific goal of displaying appropriate values for the Weight type.
Weight is a simple type that scales, and applications can write to or read from it. The XML schema and associated sample representation for this type are shown in Example 4-5.
Example 4-5. XML and schema representation of the HealthVault Weight type
Column1: <schema xmlns:weight="urn:com.microsoft.wc.thing.weight" xmlns:t="urn:com.microsoft.wc.thing.types" xmlns:d="urn:com.microsoft.wc.dates" xmlns="http://www.w3.org/2001/XMLSchema" targetNamespace="urn:com.microsoft.wc.thing.weight"> <import namespace="urn:com.microsoft.wc.thing.types" schemaLocation="base.xsd" /> <import namespace="urn:com.microsoft.wc.dates" schemaLocation="dates.xsd" /> <element name="weight"> <complexType> <sequence> <element name="when" minOccurs="1" maxOccurs="1" type="d:date-time"> </element> <element name="value" minOccurs="1" maxOccurs="1" type="t:weight-value"> </element> </sequence> </complexType> </element> </schema> Column2: <data-xml> <weight> <when> <date> <y>1990</y> <m>1</m> <d>1</d> </date> <time> <h>1</h> <m>0</m> <s>0</s> <f>0</f> </time> </when> <value> <kg>60</kg> <display units="lb">132</display> </value> </weight> <common/> </data-xml>
The Weight type consists of a sequence of date/time and weight values. The use of date/time in HealthVault is defined in the dates.xsd schema file (https://platform.healthvault-ppe.com/platform/XSD/dates.xsd), and the weight values are defined in the types.xsd schema file (https://platform.healthvault-ppe.com/platform/XSD/types.xsd).
The HealthVault .NET Web SDK encapsulates a nice object model on top of this XML and gives a user access to Value and When fields, as shown in Figure 4-8.
Note that the Value field of this type contains display and
units data. HealthVault stores the underlying measurement in
kilograms, but the application can show it to the user in the same
form in which it was entered. In our example Quantified Self
application, we ask the user to input values in pounds. Example 4-6 shows how we convert this
value to kilograms for storage while displaying it to the user as
pounds (lbs
).
Example 4-6. Creating a new Weight value
protected void Btn_SubmitWeight_Click(object sender, EventArgs e) { double weight = double.Parse(Txt_Weight.Text); Weight w = new Weight( new HealthServiceDateTime(DateTime.Now), new WeightValue( weight * 1.6, new DisplayValue(weight, "lbs", "lbs"))); w.CommonData.Source = _appName; PersonInfo.SelectedRecord.NewItem(w); }
The When field or date is a special type called HealthServiceDateTime
. As Line in Example 4-6 shows, an instance of this
date can be created by using the System DateTime
. HealthVault enables a user to
enter varying degrees of date precisions, hence it has a custom
date/time.
In fact, the HealthVault approximate datetime construct allows you to create a date as flexible as “when I was a kid” or “Jan 2011” or “Dec”. All the different kinds of HealthVault dates are defined in dates.xsd, available at https://platform.healthvault-ppe.com/platform/XSD/dates.xsd.
Note
One of the core HealthVault design tenets is to ingest all
kinds of data. Flexible dates enable a user to enter unstructured
data. Furthermore, constructs such as approx-date-time
allow HealthVault to
receive data from standards such as CCR or CCD.
All types share some common data elements. In Line of Example 4-6, we are writing to the common data element that shows the source of the application.
Other commonly used data elements are notes, tags, and related items.
HealthVault provides an extensible mechanism to specify strings
coded for use across various systems through codable-value
. The codable-value
consists of text associated
with the code, which is represented in a structured format called
coded-value
.
Terminologies are used in a HealthVault data element called
codable
. This element provides a
structured way to represent semantically meaningful text.
Example 4-7 shows a codable-value
schema. The family
data field of coded-value
specifies whether the code
belongs to particular code system; for example, wc
refers to the HealthVault code system,
and HL7
refers to a system adopted
by Health Language 7.
Example 4-7. codable-value schema
<complexType name="codable-value"> <sequence> <element name="text" type="string"> </element> <element name="code" type="this:coded-value" minOccurs="0" maxOccurs="unbounded"> </element> </sequence> </complexType><complexType name="coded-value"> <sequence> <element name="value" type="string"> </element> <element name="family" type="string" minOccurs="0"> </element> <element name="type" type="string"> </element> <element name="version" type="string" minOccurs="0"> </element> </sequence> </complexType>
HealthVault has more than 150 terminologies. The wiki http://partners.mshealthcommunity.com/hv_eco/w/wiki/preferred-vocabularies.aspx describes how these terminologies are used by the HealthVault user interface, and the book Meaningful Use and Beyond (Fred Trotter and David Uhlman, O’Reilly) describes how meaningful use, as proposed by federal regulations, dictates the use of these terminologies.
Example 4-8
shows how one can read the Exercise data type for showing calories
burned. The Exercise data type stores various kinds of attributes in
key value pairs. These attributes are listed in the ExerciseDetail
terminology. As Example 4-8 shows, one can
use the code value of CaloriesBurned
from the ExerciseDetail
terminology to look up the
appropriate value and display it in the user interface.
Example 4-8. Listing calories burned in the DisplayExercise function
private void DisplayExercise(List<Exercise> exercises) { DataTable exercise = new DataTable("exercise"); exercise.Columns.Add(new DataColumn("Date")); exercise.Columns.Add(new DataColumn("ExerciseType")); exercise.Columns.Add(new DataColumn("CaloriesBurned")); foreach (Exercise e in exercises) { DataRow row = exercise.NewRow(); row["Date"] = e.EffectiveDate.ToShortDateString().ToString(); row["ExerciseType"] = e.Activity.Text; if (e.Details.ContainsKey(ExerciseDetail.CaloriesBurned_calories)) { row["CaloriesBurned"] = e.Details[ExerciseDetail.CaloriesBurned_calories]; } exercise.Rows.Add(row); } ExerciseView.DataSource = exercise; ExerciseView.DataBind(); }
Get Enabling Programmable Self with HealthVault now with the O’Reilly learning platform.
O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.