“Data is a precious thing and will last longer than the systems themselves.”
The Quantified Self (http://quantifiedself.com/about/) community enables self-knowledge through self-tracking. Self-tracking, when powered by appropriate data analysis, has been proven to trigger behavioral change. The act of self-tracking creates awareness and feedback. The hunger for, and success of, self-knowledge is evident from the growing number of self-quantifiers (currently 6,000+ in 41 cities and 14 countries).
Self-knowledge is possible only with a substantial collection of data about oneself. HealthVault provides more than 80 granular data types that enable tracking data regarding everything from daily exercise to genome sequences. In this chapter, we will build upon the understanding of the HealthVault API covered in Chapter 3 and extend it to develop a data-intensive self-quantifying application. Through the Quantified Self application, we will gain an understanding of HealthVault data types and application development.
In Chapter 1 we analyzed weight data, and in Chapter 2 we worked with sleep information and correlated it with exercise. HealthVault offers a data type for tracking emotional state and daily dietary intake as well. Let’s consider building a simple Quantified Self utility that helps a user keep track of his emotional state, daily dietary intake, weight, sleep, and exercise. Tracking these types of data and their relation to each other would allow our user to form and prove interesting hypotheses such as: “I’m happier if I sleep well, and I sleep well if I drink less alcohol and exercise sufficiently.”
Self-tracking fosters awareness and a feedback loop; numerous participants in the Quantified Self movement have attributed improvement to insights generated by the data and the act of data collection. Our Quantified Self application will aim to emulate this pattern. Figure 4-1 summarizes the data pattern we wish to capture.
Let’s start by making a Quantified Self application with a unique application identifier. In this chapter we will use the HealthVault .NET SDK in order to focus on understanding the HealthVault data types. However, as HealthVault SDK and Open Source Libraries outlines, you can use other languages and HealthVault libraries as well.
The first step in creating the application is to download and install the HealthVault SDK from MSDN (http://msdn.microsoft.com/en-us/healthvault). After installing the SDK, you will notice a utility called Application Manager. From the Windows Start button, this utility can be accessed through All Programs→Microsoft HealthVault→SDK→HealthVault Application Manager.
Once you open the Application Manager, you will notice the Create New Application button, which you should use now to create a new application. As Figure 4-2 shows, the new application creation process asks you for an application name and other details, and creates a Visual Studio solution with the application starting point.
The second step in the process is to register your application. Application Manager automatically opens a new browser window that signs you into the HealthVault Application Configuration utility (https://config.healthvault.com) and creates the appropriate application in the HealthVault Development environment. The development environment is frequently referred to as PPE, which stands for preproduction environment. In the next chapter we will learn how the Application Configuration Center can be used to create a development application without using the Application Manager.
On the dashboard of the HealthVault Application Configuration Center, you will see the application you just created, as depicted in Figure 4-3.
HealthVault offers more than 80 granular items to which a user can authorize access. They fall into categories such as fitness, condition, medications, health history, measurements, personal profile, files, and custom data. A developer can obtain access for particular health data items by configuring an application’s authorization rule set. For our application, we need access to weight, sleep, and exercise data, which come directly from various devices. We also want the user to be able to track emotional state and daily dietary intake, which is information that she will enter manually.
To start the necessary configuration, click on the application ID in the HealthVault Application Configuration Center. Figure 4-4 illustrates the view of our Quantified Self application after clicking on the “Online rules” tab. In this menu, select the appropriate data types for the application (weight measurement, sleep, exercise, etc.), select all permissions (read, write, update, delete), provide a reason why the application needs access to these types, and name the rule. A rule can also be configured as optional and can have display settings. Why String, Is Optional, and Display Flags items are currently not active for most HealthVault applications.
We are using HealthVault as the user authentication provider for our application, so we choose to operate in the online mode and create an authorization rule for such access. If we wanted our application to work through a backend system provided by one of the other types of architecture discussed in Chapter 3, we would configure the offline rules for access to appropriate data types.
We are finished selecting the appropriate data types for our application, and can now try accessing them through the application.
The application manager utility creates a template application. Figure 4-5 shows the initial solution created by this utility.
The solution makes sure that your application is configured properly with an appropriate application ID, points it to the appropriate HealthVault platform and shell development environments, and configures the application’s redirect URL; all of these configurations live in the Web.Config file. The Default.aspx page is derived from the HealthServicePage and handles authorization with the HealthVault Platform, whereas the Redirect.aspx page is derived from the HealthServiceActionPage and handles authentication and interaction with HealthVault Shell. The bin folder contains HealthVault SDK libraries: Microsoft.Health.dll, which encapsulates the core HealthVault functionality; Microsoft.Health.Web.dll, which broadly encapsulates browser interaction; and Microsoft.Health.Itemtypes, which encapsulates an object model for all HealthVault data types.
The main solution doesn’t add a master page. In order to make it easy to extend functionality, we create a MasterPage named QuantifiedSelf.master, create a fresh Default.aspx page after deleting the old one, and ensure this page is derived from HealthServicePage.
As discussed in Chapter 3,
we can use the HealthVault GetThings API to access health items in a
user’s health record. The code shown in Example 4-1 accesses Emotion
, DietaryDailyIntake
, Weight
, Sleep
, and Exercise
from HealthVault. As shown in the two
lines at , we make sure to fetch these
elements for the last seven days only.
Example 4-1. GetThings call to access multiple things
protected void Page_Load(object sender, EventArgs e) { Lbl_UserName.Text = this.PersonInfo.SelectedRecord.DisplayName; HealthRecordSearcher searcher = PersonInfo.SelectedRecord.CreateSearcher(); HealthRecordFilter filter = new HealthRecordFilter( ApplicationSpecific.TypeId, 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); HealthRecordItemCollection items = searcher.GetMatchingItems()[0];
Before we display these types, let’s dig deeper to understand a HealthVault data type.
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.
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.
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.
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(); }
Applications frequently have to represent something that is not encapsulated by the data structure of the HealthVault data types. Out of the box, HealthVault provides a mechanism by which a data type can be extended.
Every application can choose to write XML information in the extension tag within the common data section of a data type. It is recommended that applications distinguish their extension elements by using a unique source attribute on the extension element.
In our example, let’s assume we are extending the daily dietary intake type to add information on alcohol consumption.
We would like to track the amount of alcohol consumed in a simple element called “alcoholic-drinks”. To simplify things further, we assume this element represents the number of alcoholic drinks including wine, beer, cocktails etc., and is normalized to mean average alcohol per unit.
The first step is to write an alcoholic-drinks XML element within
the extension tag using a unique source (_appDailyAlcoholExtensionName
) in the
extension element. Lines – in Example 4-9 show how one can do it in the
.NET SDK.
Example 4-9. Creating a type extension
protected void Submit_Daily_Diet_Click(object sender, System.EventArgs e) { //Post Diet DietaryDailyIntake diet = new DietaryDailyIntake(); int totalCarbs; int.TryParse(Txt_DailyDietCarbs.Text, out totalCarbs); diet.TotalCarbohydrates.Kilograms = totalCarbs * 1000; diet.CommonData.Note = Txt_DailyDietNote.Text; //Adding extension data string drinks = Txt_DailyDietAlcohol.Text; HealthRecordItemExtension extension = new HealthRecordItemExtension(_appDailyAlcoholExtensionName); diet.CommonData.Extensions.Add(extension); XPathNavigator navigator = extension.ExtensionData.CreateNavigator(); navigator.InnerXml = @"<extension source=""" + _appDailyAlcoholExtensionName + @"""> <alcoholic-drinks>" + drinks + "</alcoholic-drinks>"; PersonInfo.SelectedRecord.NewItem(diet); }
The second step is to read information from the extension. In our application, the user enters alcoholic drink information through a text box associated with the Daily Dietary intake section, as shown in Figure 4-9.
Lines – in Example 4-10 show how one can read
<alcoholic-drinks>
XML. To
parse this information we use XPath, and in the data type document, the
element of interest resides at extension/alcoholic-drinks
. Using the .NET
XPathNavigator
class, we select a
single note signifying this value (Lines –). Line fetches the note associated with this instance
of daily dietary intake. The user can potentially input clarifying
information—for example, “drank 3 tequila shots”—in this element.
Example 4-10. Consuming a type extension
private void DisplayDailyDiet(List<DietaryDailyIntake> dailydiets) { DataTable dailydiet = new DataTable("DailyDiets"); dailydiet.Columns.Add(new DataColumn("Date")); dailydiet.Columns.Add(new DataColumn("Carbs (in gm)")); dailydiet.Columns.Add(new DataColumn("Alcohol (#drinks)")); dailydiet.Columns.Add(new DataColumn("Note")); foreach (DietaryDailyIntake e in dailydiets) { DataRow row = dailydiet.NewRow(); row["Date"] = e.EffectiveDate.ToShortDateString().ToString(); row["Carbs (in gm)"] = e.ToString(); foreach(HealthRecordItemExtension extension in e.CommonData.Extensions) { if (extension.Source == _appDailyAlcoholExtensionName) { XPathNavigator navigator = extension.ExtensionData.CreateNavigator(); XPathNavigator alcoholicDrinksNavigator = navigator.SelectSingleNode("extension/alcoholic-drinks"); if (alcoholicDrinksNavigator != null) { row["Alcohol (#drinks)"] = alcoholicDrinksNavigator.Value; } } } row["Note"] = e.CommonData.Note; dailydiet.Rows.Add(row); } DailyDietView.DataSource = dailydiet; DailyDietView.DataBind(); }
Applications may choose to combine and formalize the two steps just shown and create an extension class, which then could be registered with HealthVault SDK so that every time the extend type is accessed by the application, the appropriate extension properties are available.
Extending a HealthVault data type might not always solve your data needs. Many times there are legitimate use cases for which the application needs a unique data repository. For example, in our Quantified Self application, we need a repository to store all of the user’s self-experiments.
HealthVault provides a mechanism called an application-specific type for this purpose. This type is not shareable with other applications. Once application developers find a broader use for their data, they can work with Microsoft to create a first-class data type for their needs.
Example 4-11 shows
how one can use an application-specific type to store self-experiment
hypotheses for the Quantified Self application. In our application we are
asking a user to create a hypothesis using a simple text box. The value of
this text box is read as the hypothesis string in Line . In Lines –, we create an XML document with the data for this
specific type and then add it to the document using
Application
Specific
Xml
in Line
. Each application-specific type requires a
SubtypeTag
and Description
(Lines –). We also specify
the application creating this type in Line .
Additionally, we use the common note element to capture the status of the
type in Line , and the When
element captures the date.
Example 4-11. Writing an application-specific custom type
protected void Btn_Submit_Hypothesis_Click(object sender, System.EventArgs e) { ApplicationSpecific appSpecific = new ApplicationSpecific(); string hypothesis = Txt_Hypothesis.Text; appSpecific.ApplicationId = this.ApplicationConnection.ApplicationId.ToString(); XmlDocument xml = new XmlDocument(); xml.LoadXml( string.Format("<self-experiment><hypothesis>{0}</hypothesis> </self-experiment>", hypothesis)); appSpecific.ApplicationSpecificXml.Add(xml); appSpecific.SubtypeTag = "self-experiment"; appSpecific.Description = hypothesis; // Default the status note to active when the hypothesis is created appSpecific.CommonData.Note = "Active"; appSpecific.When = new HealthServiceDateTime(DateTime.Now); PersonInfo.SelectedRecord.NewItem(appSpecific); }
On the other hand, we can show the list of self-experiments by
reading the ApplicationSpecificXml
using an XPath navigator. In Example 4-12, note that in Lines
–, we assume
that the document for this type contains only one element and that the
first node is the hypothesis.
Example 4-12. Reading an application-specific type
private void DisplaySelfExperiments(List<ApplicationSpecific> selfExperiments) { DataTable selfExperiment = new DataTable("SelfExperiments"); selfExperiment.Columns.Add(new DataColumn("Date")); selfExperiment.Columns.Add(new DataColumn("Hypothesis")); selfExperiment.Columns.Add(new DataColumn("Status")); foreach (ApplicationSpecific s in selfExperiments) { DataRow row = selfExperiment.NewRow(); row["Date"] = s.EffectiveDate.ToShortDateString().ToString(); row["Hypothesis"] = s.ApplicationSpecificXml[0].CreateNavigator(). SelectSingleNode("hypothesis").Value; row["Status"] = s.CommonData.Note; selfExperiment.Rows.Add(row); } SelfExperimentsView.DataSource = selfExperiment; SelfExperimentsView.DataBind(); }
Knowing the origin of data is often critical for an application that is using it for sensitive purposes. Some use cases warrant working with only trusted data, some warrant knowing whether the data is from a device or self-entered by the users, and in some cases the application might just want to work with known data providers.
HealthVault provides several ways to look at data provenance.
Applications can look at the created_by
and updated_by
fields of a data type
and see whether they were updated by devices or known applications.
Additionally, HealthVault provides digital signing of data, which can
create a very secure ecosystem of trust.
In our example, we look at the Source
attribute of Weight items to see whether
they were uploaded by a Withings scale or added manually by the
user.
HealthVault data types are intended to be self-contained units of health information. The data types have distinct health items, such as medications, immunizations, and weight readings. This approach is characteristically different from relational data modeling in which the data is normalized and stored in distinct tables that have explicit relationships with each other. For example, in a relational model, medications may be expressed as separate medication name and medication dosage tables.
Often there is a need to represent relationships between individual health items. For example, a Medication is inherently related to Medication Fill. Medications are associated with a person’s profile as prescribed by a physician, and Medication Fill is used by a pharmacy to prescribe units of medications to a consumer as she consumes the prescribed medications.
The relationship between Medication and Medication Fill is expressed by related items. HealthVault offers related items as an inherent mechanism to link and associate data types. A related item is a special chunk of XML that resides in the common data of a health item. Relationships are usually described in the dependent item and link to the more independent one. For instance, to express the relationship between Medication Fill and Medication, one places related items in the Medication Fill type and points to the Medication type.
Another interesting use of related items is to link together a set of readings that are uploaded from a single device. For example, a device calculating body fat percentage and cholesterol can associate them through related items while uploading them. Because this association is done before uploading to HealthVault, a special unique identifier called a client ID can be used. Client IDs are usually unique identifiers associated to instances of HealthVault data types and are created by the client uploading the data.
One can take relationships even further and associate a set of medical images, medications, and conditions as a result of a particular health incident, maybe an accident. The Mayo Clinic Health Manager application provides a way to create a web of related HealthVault items.
Related items lie beyond the scope of this book, but the reader is encouraged to explore them and contribute interesting uses and examples at http://enablingprogrammableself.com.
In our example, we picked some HealthVault types to be used in the application based on our device, data availability, and purpose. Every application programmer needs to go through this data exploration based on your needs and goals. This section gives an overview of all HealthVault types so that the reader can have a good understanding of what is available in the system.
HealthVault stores personal health information ranging from fitness data to medical images. Table 4-1 shows the categorization of the data as displayed to the end user.
Table 4-1. End user categorization of HealthVault data
Category | HealthVault types |
---|---|
Fitness | Aerobic Exercise Session, Aerobic Profile, Aerobic Weekly Goal, Calorie Guideline, Daily Dietary Intake, Exercise, Exercise Samples, Weight Goal |
Conditions | Allergy, Concern, Condition, Contraindication, Emotional State, Pregnancy, Problem, Respiratory Profile |
Medications | Asthma Inhaler, Asthma Inhaler Use, Daily Medication Usage, Insulin Injection, Insulin Injection Use, Medication, Medication Fill |
Health History | Allergic Episode, Annotation, Cardiac Profile, Diabetic Profile, Discharge Summary, Encounter, Explanation of Benefits, Family History, Family History Condition, Family History Person, Health Assessment, Immunization, Procedure, Question Answer |
Measurements | Blood Glucose, Blood Oxygen Saturation, Blood Pressure, Body Composition, Body Dimension, Cholesterol Profile, Device, Genetic SNP Results, HbA1C, Heart Rate, Height, Lab Test Results, Microbiology Lab Results, PAP Session, Peak Flow, Radiology Lab Results, Sleep Journal AM, Sleep Journal PM, Spirometer, Vital Signs, Weight |
Personal Profile | Advance Directive, Appointment, Basic, Contact, Healthcare Proxy, Life Goal, Payer, Person (emergency or provider contact), Personal Demographic Information, Personal Image |
Files | Clinical Document Architecture (CDA), Continuity of Care Document (CCD), Continuity of Care Record (CCR), File, Medical Image Study, Password-Protected Package |
Custom Data | Application Data Reference, Application Specific, Group Membership, Group Membership Activity, Link, Status |
HealthVault offers a range of fitness types. The most commonly used fitness data type is Exercise. Exercise provides a terminology-based categorization of kinds of exercise, e.g., walking or running. Each activity can also be associated with terminology-driven units: Count, Mile, etc.
Devices such as FitBit and Withings work with this type. The exercise activities terminology lists a range of exercise values, including running, walking, swimming, etc. Devices that fetch detailed information on exercise can write individual samples to the Exercise Sample type. For instance, exercise watches developed by Polar write to exercise samples in addition to summarizing the workout in the Exercise type.
This category of types is implemented in a fairly generic way so that various industry formats, such as the one used by Garmin’s Connect website (http://connect.garmin.com/), can translate easily to these types. ISO units can also be translated easily to HealthVault units.
Health problems, allergies, contra-indications, and mental health (emotional state) are categorized in the Condition set of types. Conditions are sensitive health problems that usually have an onset date and a status associated with them.
The HealthVault Shell uses the Condition type to record conditions. Conditions entered through the user interface are mapped to SNOMED-CT terminology.
Medications are the center of modern medicine. HealthVault offers a number of granular types to capture the essence of medications.
A number of pharmacies, including CVS and Walgreens, offer applications for importing prescription data into HealthVault, but the user interface and integration for these applications is a bit challenging.
The most frequently used data types in this category are Medication and Medication Fill. Each prescription could be broken into Medication and Medication Fill. Medication Fill is the recurring part of one’s prescription. As you may recall from Relating HealthVault Data Types, the Medication Fill type is usually related to Medication using the related-item semantics when entered through the HealthVault Shell.
Medications are mapped or coded to the RxNorm Active Medicines terminology.
Immunizations, procedures, family history, health events, etc. form the basis of the Health History category.
The most notable application using types in this category is the Surgeon General’s Family History application (https://familyhistory.hhs.gov/fhh-web). This powerful application enables individuals to easily create a family health history tree.
Measurements are the most extensive category of HealthVault data types. Measurements range from the output of various fitness devices to lab results. For instance, the Withings weighing scale writes to the weight measures, and FitBit writes to sleep measures. The measures are granular records of daily activity and consequently are traceable.
On the other hand, the Lab Test Results type, one of the most complicated HealthVault types, represents results from labs. It can be used in conjunction with industry-standard terminologies.
The Personal Profile category of HealthVault types contains data pertaining to health care proxies, personal images, and demographics. Almost every HealthVault application that shows a user’s picture or looks at ages or other demographic information uses types in this category.
HealthVault, unlike most personal health records, allows you to
upload a number of types of files, and therefore supports data types
for these files. Example 4-14 shows
the file extensions supported, displayed through a GetServiceDefinition
call in PowerShell.
This information can also be viewed online in the HealthVault
Developer Center’s service definition section (http://developer.healthvault.com/pages/methods/methods.aspx).
Example 4-14. List of file extensions supported by HealthVault
PS C:Windowssystem32> $a = Get-ServiceDefinition PS C:Windowssystem32> $a.ConfigurationValues Key Value --- ----- allowedDocumentExtensions .avi,.bluebutton,.bmp,.ccd,.ccr,.cda,.doc,.docm,... autoReconcilableTypes 1e1ccbfc-a55d-4d91-8940-fa2fbf73c195,9c48a2b8-... blobHashBlockSizeBytes 2097152 blobHashDefaultAlgorithm SHA256Block blobStreamWriteTokenTtlMs 172800000 defaultCulture en defaultPersonInfosPerRetrieval 200 emailValidationExp ^([w-+.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]... liveIdAuthPolicy HBI liveIdEnvironment PROD <... clipped for brevity..>
The Medical Image study type used by the HealthVault Connection Center uploads DICOM medical images in this type. The CCD/CCR types are industry-standard ways by which various hospital information systems send care records to HealthVault. Google Health users, for instance, migrated to HealthVault using the CCR type. The Message file type is the backbone of HealthVault’s Direct integration. Any email message received by the user is stored in the Message type.
The Application Specific type, already covered in the section Creating Custom Types with regard to adding a repository in which to store self-experiments, is the most important custom data type. This type is used by various applications to store information in HealthVault for which no other type or extension to a type is appropriate. For instance, the Vivacity’s Spending Scout application (http://www.spendingscout.com/) stored explanation of benefit information in this type until the HealthVault team created an Explanation of Benefits (EOB) type to support it more directly.
In next chapter we will see how we can augment the self-experimentation web application by creating mobile applications. The source for the application is available at http://enablingprogrammableself.com, and we are inviting you, dear reader, to extend this application and make it your own. Perhaps fork the Git repository and contribute your code back, or create Java, Ruby, or Python versions of it!
3.133.126.239