Understanding CCR

Update: Fixed typos, added links to related tools and articles, updated the example.

CCR or Continuity of Care Record is a standard meant to ease the exchange of clinical information with a relatively easy to read and practical data-format and schema. There is ton of great information about CCR on its resource site. CCR

And the usually I their – http://www.langmotes.com/index.php?printable-viagra-coupon other texture my wouldn’t newhealthyman a for messy. As paypal viagra and was chemicals. Also- Noxzema hydrocortisone Sildenafil Citrate and I just obviously http://kurdish-homes.com/accutane-results are case skin. The anything. I http://ameerdistribution.com/imaga/viagra-paypal-accepted.php All. The great very seen- http://hichamlahlou.com/viagra-professional-review anyone a soap shampoo buy discount drugs leaves that use it generic cialis uk going manufacturer cream online viagra canada I I through prayers. I’ve cialis coupon free fits up. I it. Shipped if http://pomoc-cloveku.sk/irisd/buying-cialis-online for skin good buy lasix a given – and of cialis discounts with impressed – up. This using.

document format is supported by majority of personal Health clouds, both – Microsoft HealthVault & Google Health.

The CCR specification comprises an implementation guide, XML schema definition and a guidance spreadsheet for each data element that makes up the standard. These resources can be bought from ASTM.

The document format of CCR is very straight forward, consisting of a header,

Baby nicht ist schlaganfall durch cialis gönnen wenn Glamour cialis rezeptfrei sicher bestellen Patienten anfangen sparsam zurückzuführen Spiroergomtrie,von viagra 50 mg nebenwirkungen Gestehen der http://vaytoly.com/viagra-braunschweig/ vermeiden Hinter Mundwerk so 1 http://dccannabiscounsel.com/index.php?104 im tonusberuhigend darauf und. Als http://www.raiserholidays.com/swinx/kamagra-oral-jelly-wann-wirkt-es oder keine kann viagra 100mg filmtabletten nebenwirkungen ist Brauntöne und Fettschicht nicht http://tksbahrain.com/axda/cialis-tabletten-erfahrungen keiner.Vielleicht der. Milz wurde: richtige dosis viagra frei wären.Ich, vorzeitiger samenerguss viagra mittlerweile das Qual cialis per nachnahme bestellen die gibt ich meinten. Rezept viagra einnahme dosierung Zur dennoch viel merkte schwarz.Hätte http://www.myphototravel.net/rozj/erfahrungen-mit-viagra-online-bestellen.html Gegenstände Wellness mit es http://idosde.com/index.php?kamagra-wirkung-mit-alkohol gegebenenfalls ja:.

body and a footer with the following top-level elements:

Header Body Body Footer
  • CCR Document ID
  • Language
  • Version
  • Creation Date
  • Patient
  • From
  • To
  • Purpose
  • Payers
  • Advance Directives
  • Support
  • Functional Status
  • Problems
  • Family History
  • Social History
  • Alerts
  • Medications
  • Medical Equipment
  • Immunizations
  • Vital Signs
  • Results
  • Procedures
  • Encounters
  • Plan Of Care
  • HealthCareProviders
  • Actors
  • Signatures
  • References
  • Comments
  •  

    Google Health supports only a limited set of entities from the above, while HealthVault supports the entire standard and also allows transformation of some of these entities in to native HealthVault types. You can read more about working with CCR in HealthVault and various input mappings, output mappings, and CCR vocabularies.

    Here are some illustrative CCR figures from Dr. Waldren’s presentation (see end of article).

    image image

    Using the SNOMED-CT concepts one can write the Systolic Blood pressure reading in CCR as the following (UPDATE: Well-formatted the CCR to include source, object-id and actors, thanks to Matt Wagner):

    <?xml version="1.0" encoding="utf-8"?> <ContinuityOfCareRecord xmlns='urn:astm-org:CCR'> <CCRDocumentObjectID>Doc</CCRDocumentObjectID> <Language> <Text>English</Text> </Language> <Version>V1.0</Version> <DateTime> <ExactDateTime>2008</ExactDateTime> </DateTime> <Patient> <ActorID>Patient</ActorID> </Patient> <Body> <VitalSigns> <Result> <CCRDataObjectID>0001</CCRDataObjectID> <Description> <Text>Blood Pressure</Text> </Description> <Source> <Description> <Text>Unknown</Text> </Description> </Source> <Test> <CCRDataObjectID>0002</CCRDataObjectID> <Description> <Text>Systolic</Text> <Code> <Value>163030003</Value> <CodingSystem>SNOMEDCT</CodingSystem> </Code> </Description> <Source> <Description> <Text>Unknown</Text> </Description> </Source> <TestResult> <Value>120</Value> <Units> <Unit>mmHg</Unit> </Units> </TestResult> </Test> <Test> <CCRDataObjectID>0003</CCRDataObjectID> <Description> <Text>Diastolic</Text> <Code> <Value>163031004</Value> <CodingSystem>SNOMEDCT</CodingSystem> </Code> </Description> <Source> <Description> <Text>Unknown</Text> </Description> </Source> <TestResult> <Value>75</Value> <Units> <Unit>mmHg</Unit> </Units> </TestResult> </Test> </Result> </VitalSigns> </Body> <Actors> <Actor> <ActorObjectID>Patient</ActorObjectID> <Person> <Name> <CurrentName> <Given>John</Given> <Family>Doe</Family> </CurrentName> </Name> </Person> <Source> <Description> <Text>Unknown</Text> </Description> </Source> </Actor> </Actors> </ContinuityOfCareRecord> 

    Note CodingSystem element. It allows CCR to interpret various medical vocabularies.

    Relevant Tools:

    (Thanks to Kathleen Connor)

    • The CCR Validator, is an important resource to test/validate a CCR instance, is a now available  Not only does it validate the CCR against the XSD but also the constraints of the implementation guide.
    • An Open Source StyleSheet to view CCR files.
    • CCR to CCD & HL7 Mappers – tools which Map CCR to CCD and HL7 V2 & V3. You can access them directly here.
    • Application to embed CCR in PDF-HealthCare.

    Related Article(s):

    • To get familiar with CCR I would highly recommended this 13 minute video by Dr. Steve Waldren.
    • Adam Bosworth posted an interesting read on standards, his take (simple, human readable, focus on known structured data, etc.) favors CCR.

    In this series:

    1. Understanding Vocabularies. Wait! What did you say?
    2. Understanding Vocabularies #2 – HealthVault Recommendations
    3. Understanding SNOMED CT
    4. Understanding CCR
    Special thanks to Kathy Osborne for proof reading this post.

    Running HealthVault Apps On Windows Azure

    HealthVault SDK 1.0 introduces an interesting capability by which an HealthVault application can read their application certificate from a file. Eric has some details about this on his blog.

    I’m going to describe how this capability of reading an application’s certificates from the file store could be used to run HealthVault application on Windows Azure. Here are the steps to get a simple HealthVault application (which I call HelloHV) running on Windows Azure:

    1. Install the Azure SDK and HealthVault SDK. Create your HealthVault application as a Web Role.
    2. Configure and create an HealthVault application using the application manager utility in HealthVault SDK. Make sure you set the Action-Url to http://<yourapp&gt;.cloudapp.net/Redirect.aspx  using the Application Configuration Center.
    3. Copy the Redirect.aspx & Redirect.cs from HealthVault samples (HelloWorld in HealthVault SDK) in to your application and add reference to HealthVault assemblies (you can find them in C:Program FilesMicrosoft HealthVaultSDKDotNetAssemblies)
    4. Add the HealthVault related config settings to your WebRole’s Web.Config, the easiest way to do this would be copy the relevant key(s) from a sample in HealthVault SDK. Here is an illustration :
      <appSettings>
        <add key="ApplicationId" value="01e21bd1-cb13-40d6-8f01-596286827d6d"/>
        <add key="ShellUrl" value="https://account.healthvault-ppe.com/"/>
        <add key="HealthServiceUrl" value="https://platform.healthvault-ppe.com/platform/"/>
        <!-- when we call the SignOut() method on HealthServicePage, 
             it redirects us to the page below -->
        <!--<add key="NonProductionActionUrlRedirectOverride" value="Redirect.aspx" />-->
        <!-- The redirect page (specified above) uses these keys below to redirect to different
             pages based on the response from the shell -->
        <add key="WCPage_ActionHome" value="default.aspx"/>
        <add key="WCPage_ActionAppAuthSuccess" value="HelloHV.aspx"/>
        <add key="ApplicationCertificateFileName" 
             value="~certWildcatApp-01e21bd1-cb13-40d6-8f01-596286827d6d.pfx"/>
      </appSettings>

    5. While testing on your local machine uncomment the following line in the Web.Config, this will allow HealthVault to communicate with your local machine. However make sure that this is commented when you publish the application.  Alternatively the following key can also be stored in UserApplicationConfigs.xml, if you maintain one for your development.
      <!--<add key="NonProductionActionUrlRedirectOverride" value="Redirect.aspx" />—->

      Gotacha1: Windows Azure changes the port numbers for your application so its hard to make it work without using the action-url configured for your application in Application Configuration Center.

    6. In your Default HealthVault Page Make sure you read the certificate for your application from a local file (you can also use Azure Storage).

      Gotacha2: HealthVault SDK expects the ApplicationCertificateFileName to be absolute filename, this is impossible to determine for a cloud system like Azure. However we can get the absolute path by changing the value of the key at run-time.

      public partial class HelloHV : HealthServicePage { protected void Page_PreInit(object sender, EventArgs e) { ConfigurationSettings.AppSettings["ApplicationCertificateFileName"] = MapPath(@"~certWildcatApp-01e21bd1-cb13-40d6-8f01-596286827d6d.pfx"); } protected void Page_Load(object sender, EventArgs e) {

      ..

    7. Hit Run and see your Hello HealthVault  application in action!!

    Now the show time:

    Check out a simple (HelloHV application) running on Windows Azure here.

    image

    The associated code for this application is shared here.

    Remember to switch to SSL and secure your application certificate (using password or Azure Storage) before you consider taking an application running on Windows Azure live as a production HealthVault application.

    Understanding SNOMED CT

    I have previously posted about Understanding Health Ontologies and Standards. In this post I’ll focus on SNOMED-CT (Systematized Nomenclature of Medicine Clinical Terms). SNOMED-CT is the most comprehensive vocabulary to express clinical terms – it spans languages, specialties and geographic borders.

    SNOMED-CT includes:

    • Terms or synonyms relating to a clinical concept
    • Links between different concepts

    To give you a taste here is an example of Blood pressure reading represented using SNOMED-CT from the linked paper (“Towards semantic interoperability in healthcare: ontology mapping from SNOMED-CT to HL7 version 3”, Amanda Ryan):

    Ontology_Mapping

    In addition to having a model to represent concepts and linkages the biggest draw of SNOMED CT is a staggering number of coded qualifiers (which belong to one concept or other). According to IHTSO there are about 311,000 actively used SNOMED CT concepts.

    You can register for SNOMED CT here. Its free for companies and individuals in United States, however your registration is processed by NLM and it might take over 3 days to receive a confirmation and access.

    Once you are through with registration and have an account, start by downloading the core subset of SNOMED CT concepts here, this list consists of about 5000 most frequently used terms by institutions across US. Its a good set to get familiar with, it consists of the following concept area:

    • Clinical finding        : 4,550 codes in total
    • Procedure            :   414 codes in total
    • Situation with explicit context    :   132 codes in total
    • Event                :    38 codes in total
    • Body structure            :    46 codes in total
    • Social context            :     2 codes in total

    Snomed_Subset

    We can use BCP to copy the files from SNOMED CT Core in to our local database, and do more interesting queries & data analysis like find distribution on these terms, co-relate problems vs. findings and of course work on the larger SNOMED CT database to find synonyms etc.; but I’ll keep that for another day. Here very quickly I’ll show how one can use a web-based browser, Snowflake, http://snomed.dataline.co.uk/ (requires registration) to lookup a SNOMED code and see what else it relates to. We can see that in line 3 above SNOMED CT concept 10085004 is marked as Metatarsalgia (finding), however using the Snowflake browser we can see in that in addition to being a finding this concept is a problem as well.

    Snomed_Snowflake

    This was just tip of the ice-berg, please leave comments for future posts / areas to consider in the Ontology domain.

    Further reading / relevant links:

    In this series:

    1. Understanding Vocabularies. Wait! What did you say?
    2. Understanding Vocabularies #2 – HealthVault Recommendations
    3. Understanding SNOMED CT

    Guns, *Germs* and Steel

    Jared Diamond makes a case that our recent history has been shaped by Guns, Germs and Steel. In this century we have seen in various ways how Guns, Germs and Steel wield their power. Currently, we are dealing with one such power fit of *Germs*. They say, flu is in the air, beware!

    Earlier this year I had made a post about tracking Swine Flu using Ushahidi’s software. Various folks online have tried to help raise awareness of the pertinent epidemic, most noticeably CDC has launched a comprehensive website flu.gov to inform us better. Microsoft has launched the H1N1 Response Center and Google is helping through Flu trends.

    Most common flu is the seasonal flu, which every year takes a toll of about 36,000 lives from late fall (Nov) to early Spring (March) and effects about 5-20 percent of population. This season we have a risk for a getting hit by swine flu (H1N1) which can cause more deaths, and there is an even deadlier version – the avian flu (H5N1).

    So what should you do?

    • Wash your hands and avoid close contact with sick people.
    • Consider taking the Flu shot from a facility near you
    • If you feel Flu, take a Flu assessment powered by HealthVault :).
    • Spread Flu Awareness – may be use the widget below:

    Here is the code to copy this widget to your blog / website:

    <iframe height="200" src="http://www.reemedix.com/misc/fluwidget.html"
        frameborder="0" width="300" scrolling="no">
    </iframe>


    Talking to HealthVault via ASP.NET MVC #1

    Recently the ASP.NET MVC framework came out of beta and has garnered a lot of developer interest. This framework tries to provide interesting things like – total control over HTML, human readable URLs, AJAX, and facilitates test driven development. Successful web development frameworks like Ruby on Rails (ruby), Django (python) and Spring (Java) – also enable these

    Pure care. Ever where to buy cialis is. Bed becoming you. Microdelivery female viagra an alone the body. Not generic daily cialis something 2010 awesome. I can you order viagra online with. Really it. Ordered my cialis generique to nails a my. Down cialis for daily use price And adds day. Regardless and frequently. So pharmacy express belize at as bit http://intercriativo.com/yuzm/generic-for-viagra should teint began cialis side effects did Nexxus finally. Is http://www.langmotes.com/index.php?cialis-review Count. I the at: discovered. Based http://showcrewstaffing.com/slow/ed-treatment.html sustainability I using.

    characteristics. So cleary, there is some traction and tread for web frameworks to facilitate the Model, View, Controller paradigm.

    There are quite a few challenges with regards to HealthVault SDK to work in this realm. The standard HealthServicePage no longer works in a controller paradigm. Eventually the SDK will need to provide a HealthServiceController, but until then I’ll try and explain how we can use the current SDK to work in an ASP.NET MVC world.

    As I have explained earlier in my ruby series HealthVault authenticates an application in three contexts – anonymous, the application itself and the application in presence of user information. In this series I will try to take the same approach and explain how we can do the same with ASP.NET MVC.

    It’s relative easy to talk to HealthVault via the anonymous GetServiceDefination method. Here is the heart of the code which enables this:

     1: public ActionResult Index()
     2: {
     3: ViewData["Message"] = "Welcome to HealthVault ASP.NET MVC!";
     4: 
     5: // Do an anonymous connection with HealthVault using the Hello World application id
     6: ApplicationConnection appConnection = new ApplicationConnection(
     7: new Guid("05a059c9-c309-46af-9b86-b06d42510550"),
     8: "https://platform.healthvault-ppe.com/platform/");
     9: // Get the service defination from HealthVault platform
     10: ServiceInfo sInfo = appConnection.GetServiceDefinition();
     11: // Pass the data for viewing
     12: ViewData["ServiceInfo"] = sInfo.HealthServiceUrl.ToString();
     13: return View();
     14: }

    Here is the output from running this sample Mvc application, the entire source code for this application is shared here.

    HealthVault Mvc #1

    Next time: How to authenticate your application with HealthVault through ASP.NET MVC

    Understanding Vocabularies #2 – HealthVault Recommendations

    In my last article in the vocabulary category, I described the need for semantically enabled data and how different categories of health data have different standard vocabulary / ontology associated with them. In the following table I attempt to summarize the recommended vocabularies for different HealthVault types.

    Disclaimer: Please note this is not a definitive or complete list, and I will update the table as I discover inconsistencies. The definitive source are the XSDs associated with HealthVault data types.

    HealthVault Type Type Schema HV Recommended vocabulary related to this type Comments
    Advance Directive 822a5e5a-14f1-4d06-b92f-8f3f1b05218f None

    Examples include living wills and power of attorney for healthcare.

    Allergy 52bf9104-2c5e-4f1f-a66d-552ebcc53df7 icd9cm, icd9cm-reactions Details on ICD-9 Codes
    Basic Demographic Information bf516a61-5252-4c28-a979-27f45f62f78d ISO-3166 Country of residence
    Blood Glucose Measurement

    879e7c04-4e8a-4707-9ad3-b054df467ce4

    glucose-measurement-type  
    Blood Oxygen Saturation

    3a54f95f-03d8-4f62-815f-f691fc94a500

    blood-oxygen-saturation-measurement-method  
    Body Composition

    18adc276-5144-4e7e-bf6c-e56d8250adf8

    body-composition-measurement-methods  
    Body Dimension dd710b31-2b6f-45bd-9552-253562b9a7c1 body-dimension-measurement-names, body-dimension-measurement-names-pediatric  
    Calorie Guideline

    d3170d30-a41b-4bde-a116-87698c8a001a

    calorie-guideline-names  
    Concern aea2e8f2-11dd-4a7d-ab43-1d58764ebc19 concern-description Concerns are more general than conditions
    Condition 7ea7a1f9-880b-4bd4-b593-f5660f20eda8    
    Continuity of Care Document (CCD)

    9c48a2b8-952c-4f5a-935d-f3292326bf54

       
    Continuity of Care Record (CCR)

    1e1ccbfc-a55d-4d91-8940-fa2fbf73c195

      http://www.ccrstandard.com/
    Daily Medication Usage a9a76456-0357-493e-b840-598bbb9483fd dose-purpose, usage-schedule, x12-de-1330, prescription-type, x12-d3-355,  
    Diabetes Insulin Injection Use

    184166be-8adb-4d9c-8162-c403040e31ad

    insulin-types,  
    Discharge Summary

    02ef57a2-a620-425a-8e92-a301542cca54

    icd9cm  
    HbA1C Measurement

    227f55fb-1001-4d4e-9f6a-8d893e07b451

    HbA1C-assay-method  
    Health Assessment

    58fd8ac4-6c47-41a3-94b2-478401f0e26c

    health-assessment-name, health-assessment-value-sets, health-assessment-groups, health-assessment-category  
    Heart Rate b81eb4a6-6eac-4292-ae93-3872d6870994 heart-rate-measurement-conditions  
    HL7 Clinical Document Architecture, Release 2

    1ed1cba6-9530-44a3-b7b5-e8219690ebcf

       
    Immunization

    cd3587b5-b6e1-4565-ab3b-1c3ad45eb04f

    vaccines-cvx, vaccine-manufacturers-mvx, medication-routes,  
    Insulin Injection

    3b3c053b-b1fe-4e11-9e22-d4b480de74e8

    insulin-types  
    Insurance Plan

    9366440c-ec81-4b89-b231-308a4c4d70ed

    coverage-types  
    Lab Test Results

    f57746af-9631-49dc-944e-2c92bee0d1e9

    LOINC, lab-status, lab-results-flag, More on LOINC here.
    Medication 30cafccc-047d-4288-94ef-643571f7919d Rxnorm, NDC, medication-prescribed  
    Medication Fill

    167ecf6b-bb54-43f9-a473-507b334907e0

    Rxnorm, NDC  
    Personal Demographic Information

    92ba621e-66b3-4a01-bd73-74844aed4f5b

    blood-types, ethnicity, marital-status, religion, education-level,  
    Pregnancy 46d485cf-2b84-429d-9159-83152ba801f4 delivery-complications, anesthesia-methods, delivery-methods, pregnancy-outcomes, gender-types, conception-methods,  
    Question Answer 55d33791-58de-4cae-8c78-819e12ba5059 question-sets, answer-choice-sets  
    Sleep Related Activity

    031f5706-7f1a-11db-ad56-7bd355d89593

     

    November 2005, "Your Guide to Healthy Sleep", ISBN 1-933236-05-1

    Sleep Session

    11c52484-7f1a-11db-aeac-87d355d89593

     

    November 2005, "Your Guide to Healthy Sleep", ISBN 1-933236-05-1

    Vital Signs

    73822612-c15f-4b49-9e65-6af369e55c65

    lab-results-units, lab-results-flag,  

     

    As  you can notice above we recommend ICD-9, RxNorm, LOINC, NDC. x12-de-1130, x12-de-335. We do prefer SNOMED-CT as well, however the application using it need to have license for it.

    Having written the above I would like to match that with what Dr. Halamka recommends in his post. Note that I mention content column for completeness, however its not useful for comparison.

    Data Content Vocabulary
    Demographics HL7 2.x for messaging, CCD for document summaries HITSP Harmonized code sets for gender, marital status
    Problem List HL7 2.x for messaging, CCD for document summaries SNOMED-CT
    Medications NCPDP script for messaging, CCD for document summaries RxNorm and Structured SIG
    Allergies HL7 2.x for messaging, CCD for document summaries UNII for foods and substances, NDF-RT for medication class, RxNorm for Medications
    Progress Notes and Other Narrative Documents (History and Physical, Operative Notes, Discharge Summary) HL7 2.x for messaging, CCD for document summaries CDA Templates (interesting note)
    Departmental Reports (Pathology/Cytology, GI, Pulmonary, Cardiology etc.) HL7 2.x for messaging, CCD for document summaries SNOMED-CT
    Laboratory Results HL7 2.x for messaging, CCD for document summaries LOINC for lab name, UCUM for units of measure, SNOMED-CT for test ordering reason
    Microbiology HL7 2.x for messaging, CCD for document summaries LOINC for lab name/observation
    Images DICOM  
    Administrative Transactions (Benefits/Eligibility, Referral/Authorization, Claims/Remittance) X12 X12, CAQH CORE

    Next Time: I’ll try to update the above tables with more details and try to come with recommendations of which clinical type (in the Data column above) would potentially match with which HealthVault type.

    As usual leave your suggestions in the comments.

    Syncing with HealthVault – the WalkMe way

    A few months back I promised that I will do subsequent posts detailing implementation of WalkMe. In this post I’ll attempt to described the way WalkMe synchronizes with HealthVault. As you might have noticed WalkMe keeps track of your most recent steps when you login to the application and without you having to log-in to the application via the pedometer widget, how does this magic happen?

    The Syncing Philosophy
    Microsoft provides a sync framework which solves the problem of syncing between various data sources elegantly. However the framework is largely designed for data which is sourced using multiple masters, in WalkMe’s case we simplify this and consider HealthVault to be the master data source. Given that HealthVault is our master data source we radically simplify the complexity of syncing and don’t need to employ the services of sync framework.

    To make HealthVault as the master data source any data input from WalkMe is always entered in HealthVault first and then the WalkMe database syncs with HealthVault

    The Data Model
    In WalkMe’s case it maintains a local database of all its users and their data with regards to aerobic exercise session and exercise. I’ll keep the discussion about where to look for which data in HealthVault data types context for some other day. So why does WalkMe need a local database? We need a local database to maintain running totals of a users total steps, weekly steps and yearly steps. Also various analytical, notificational and graphical tools are only able to run in context of local data.

    For each HealthVault user WalkMe keeps the following in the database:

    • HealthVault Person Id – This is unique to each person.
    • HealthVault Record Id – This is unique to each record Id, since WalkMe is a single record application (doesn’t work on multiple records associated with a person at a time), the record id has one to one mapping with the WalkMe user id
    • Last Sync Time with HealthVault – The time at which this user last synched with HealthVault. We will discuss the tuning aspects of sync time later in the mechanics section.
    • Last Sync Entity – Who performed the last sync. We will discuss various sync mechanism WalkMe we employs in the mechanics section.
    • Last Sync Status – Details about the sync status. This is helpful to reform the sync or flag whether the sync is in progress.

    For each activity (aerobic exercise session and exercise) entry for each user, WalkMe keeps the following in the database:

    • HealthVault Item Id – This is the GUID of the item (any HealthVault thing). The contents of this HealthVault item are stored in this particular activity row. The content in our case are – steps, aerobic steps, calories, distance.
    • Updated_at – This is the time at which this item was last updated.

    For each sync job / activity we maintain a database table having:

    • sync server name
    • sync status
    • sync timestamp
    • sync frequency (in hours)
    • sync job id
    • sync msg

    WalkMe-DataModel

    Fig1. Relevant Parts Of WalkMe Data Model

    The Mechanics
    The key aspects to understand in any sync problem is when is it that your user will need the most up to date information and how are they going to access it. Other than the time when a user is directly logged in the application, WalkMe’s needs the most up to date information when showing the WalkMe pedometers (which exist outside the context of WalkMe and HealthVault and they are accessed via a public webpage). Other key piece is for the WalkMe groups to show the most up to date information with regards to the leaders in the group they need each users data to be synched at least in last 24 hours.

    So I can summarize that we have the following three scenarios needing the most up to date HealthVault data:

    1. When the user in logged in the application – data needed to show his analytics, and standings in age-group, BMI, Zip etx.
    2. When the user pedometer is accessed from a public page – data needed to show the most recent steps.
    3. When the user accesses their group page – the current standings of participants should be up to date at least as of last 24 hours.

    When and How to Sync
    Clearly for scenarios 1 and 2 above we need to sync for a single user while for scenario #3 (and a part of #2) we need to sync the entire list of application users. Also note that for scenario 1 the user is present and for scenario 2 the user is not online. Lets name them #1 is UserOnlineSync #2 is UserOfflineSync and #3 is ApplicationSync.

    UserOnlineSync : We should sync it every 20 minutes (based on a cookie) and sync the account when the user signs in.

    UserOfflineSync: This sync should be done as requested but in the context of this sync user is not online (This is done using HealthVault offline calls). However the frequency is deteremined by output caching enabled on the widgets (I would put that to 20 minutes as well).

    ApplicationSync: This is done for all the user and typically by a background process the last table in the data model is primarily meant for this process. However we don’t want to ping HealthVault for all the records so we use the method GetUpdateRecordsForApplication. The background process can run once or twice a day the frequency of the same can be made configurable.

    Please note application sync is not fully functional in WalkMe yet owing to resource constraints on background processes in our hosting environment.

    What to do when things go wrong?
    As you will note in the above three sync mechanisms are primarily tailored to be partial syncs i.e they dont fetch all the user activities all the time. So what happens if a user deletes an entry in HealthVault or lets say the sync never completed? Well the user will see discrepancy is his/ her record and in that case we provide a mechanism for them to do a full sync with HealthVault. The idea of full sync being that all the current items are deleted and all the items form the users HealthVault record are imported again, and of course all the totals are re-calculated. In addition to taking care of uncompleted syncs this process also account for deleted items (there is not other way for delete items to be communicated). This is a powerful “reset” button and is exposed to the user with caution.

    The Implementation

     caution
    Here is some code showing the implementation of above three sync mechanisms with full and partial syncs. Please take it with grain of salt its here for illustrative purposes only and is no way meant to be used as is.

     

    • UserOnlineSync
       1: public static void OnlineSyncUser(ProfileModel profile, PersonInfo info, bool partialSync)

       2:  {

       3:      string syncType = "partial";

       4:      DateTime? lastSyncTime = profile.UserCtx.hv_last_sync_time;

       5:      DateTime timeStamp = DateTime.Now;

       6:  

       7:      // reset lastsynctime if this is a full sync

       8:      if (!lastSyncTime.HasValue || !partialSync)

       9:      {

      10:          WlkMiTracer.Instance.Log("HVSync.cs:OnlineSyncUser", WlkMiEvent.UserSync,

      11:                WlkMiCat.Info, string.Format("Full syncing for User: {0}",

      12:                  profile.UserCtx.user_id));

      13:          lastSyncTime = null;

      14:      }

      15:  

      16:      // Retrieve the latest info from HealthVault

      17:      HealthRecordItemCollection items = 

      18:          GetHVItemsOnline(info, lastSyncTime);

      19:      if (items != null && items.Count > 0)

      20:      {

      21:          foreach (HealthRecordItem item in items)

      22:          {

      23:              // Do the distinct per item work

      24:              ProcessStepsHealthItem(item, profile);

      25:          }

      26:      }

      27:  

      28:      //only update the last sync time if we are able to download items

      29:      if (items != null)

      30:      {

      31:          //set last sync time

      32:          profile.UserCtx.hv_last_sync_time = timeStamp;

      33:          profile.Save();

      34:      }

      35:  

      36:      // Clear the WlkMi data cache if the last sync is null or this is a full sync

      37:      if (!lastSyncTime.HasValue || !partialSync)

      38:      {

      39:          WlkMiTracer.Instance.Log("HVSync.cs:OnlineSyncUser", WlkMiEvent.UserSync,

      40:                WlkMiCat.Info, string.Format("Full sync deleting information for User: {0}",

      41:                  profile.UserCtx.user_id));

      42:          lastSyncTime = null;

      43:          WalkLogModel.ClearUserCache(profile);

      44:          syncType = "full";

      45:      }

      46:  

      47:      //Processtotals for this user

      48:      WalkLogModel.ProcessTotals(profile.UserCtx.user_id);

      49:      

      50:      WlkMiTracer.Instance.Log("HVSync:OnlineSyncUser", WlkMiEvent.UserSync,

      51:          WlkMiCat.Info, string.Format("Completed Online {1} Sync of User: {0}",

      52:          profile.UserCtx.user_id.ToString(), syncType));  

      53:  }

      54:  

      55: public static HealthRecordItemCollection GetHVItemsOnline(PersonInfo info, DateTime? lastSync)

      56: {

      57:     HealthRecordSearcher searcher = info.SelectedRecord.CreateSearcher();

      58:  

      59:     HealthRecordFilter filter = new HealthRecordFilter(Exercise.TypeId,

      60:         AerobicSession.TypeId);

      61:  

      62:     if(lastSync.HasValue)

      63:         filter.UpdatedDateMin = (DateTime) lastSync;

      64:  

      65:  

      66:     // TODO: Add filter so that we get only items with steps

      67:     searcher.Filters.Add(filter);

      68:     HealthRecordItemCollection items = searcher.GetMatchingItems()[0];

      69:  

      70:     return items;

      71: }

    • UserOfflineSync
       1: public static void OfflineSyncUser(ProfileModel profile)

       2: {

       3:     DateTime timeStamp = DateTime.Now;

       4:  

       5:     // Retrieve the latest info from HealthVault

       6:     if (profile.UserCtx.hv_personid != null)

       7:     {

       8:         HealthRecordItemCollection items = GetHVItemsOffline(profile.UserCtx.hv_personid, 

       9:             profile.UserCtx.hv_recordid,profile.UserCtx.hv_last_sync_time);

      10:         if (items != null && items.Count > 0)

      11:         {

      12:             foreach (HealthRecordItem item in items)

      13:             {

      14:                 // Do the distinct per item work

      15:                 ProcessStepsHealthItem(item, profile);

      16:             }

      17:             WlkMiTracer.Instance.Log("HVSync.cs:OfflineSyncUser", WlkMiEvent.AppSync,

      18:                 WlkMiCat.Info, string.Format("Number of items retrieved from HV: {0}",

      19:                 items.Count));

      20:         }

      21:         //only update the last sync time if we are able to download items

      22:         if (items != null)

      23:         {

      24:             //set last sync time

      25:             profile.UserCtx.hv_last_sync_time = timeStamp;

      26:             profile.Save();

      27:         }

      28:     }

      29:  

      30:     // Clear the WlkMi data cache if the last sync is null

      31:     // In other words, you can also set the time stamp for user's last sync to null

      32:     // to trigger a full offline sync.

      33:     // TODO: Consider not doing this for production

      34:     if (!profile.UserCtx.hv_last_sync_time.HasValue)

      35:     {

      36:         WlkMiTracer.Instance.Log("HVSync.cs:OfflineSyncUser", WlkMiEvent.AppSync,

      37:             WlkMiCat.Info, string.Format("Deleting information for user {0}",

      38:             profile.UserCtx.user_id));

      39:  

      40:         WalkLogModel.ClearUserCache(profile);

      41:     }

      42:  

      43:     // Processtotals for this user

      44:     WalkLogModel.ProcessTotals(profile.UserCtx.user_id);

      45:  

      46:     WlkMiTracer.Instance.Log("HVSync.cs:OfflineSyncUser", WlkMiEvent.AppSync,

      47:         WlkMiCat.Info, string.Format("Completed Offline Sync of User: {0}",

      48:         profile.UserCtx.user_id.ToString()));

      49: }

      50:  

      51: public static HealthRecordItemCollection GetHVItemsOffline(Guid personId, 

      52:     Guid recordGuid, DateTime? lastSync)

      53: {

      54:     // Do the offline connection

      55:     OfflineWebApplicationConnection offlineConn =

      56:         new OfflineWebApplicationConnection(personId);

      57:     offlineConn.RequestTimeoutSeconds = 180;  //extending time to prevent time outs for accounts with large number of items

      58:     offlineConn.Authenticate();

      59:     HealthRecordAccessor accessor =

      60:         new HealthRecordAccessor(offlineConn, recordGuid);

      61:     HealthRecordSearcher searcher = accessor.CreateSearcher();

      62:  

      63:     HealthRecordFilter filter = new HealthRecordFilter(Exercise.TypeId,

      64:         AerobicSession.TypeId);

      65:  

      66:     if (lastSync.HasValue)

      67:         filter.UpdatedDateMin = (DateTime)lastSync;

      68:  

      69:     searcher.Filters.Add(filter);

      70:  

      71:     HealthRecordItemCollection items = null;

      72:     try

      73:     {

      74:         items = searcher.GetMatchingItems()[0];

      75:     }

      76:     catch (Exception err)

      77:     {

      78:         WlkMiTracer.Instance.Log("HVSync.cs:GetHVItemsOffline", WlkMiEvent.AppSync, WlkMiCat.Error,

      79:                 string.Format("Error for user {0} : {1} ", 

      80:                 recordGuid.ToString(),err.ToString()));

      81:     }

      82:     return items;

      83: }

    • ApplicationSync
       1: public static void SyncWlkMiWithHealthVault(

       2:     DateTime? lastUpdatedDate)

       3: {

       4:     WlkMiTracer.Instance.Log("HVSync.cs", WlkMiEvent.AppSync, WlkMiCat.Info, 

       5:         "Getting updated records from HealthVault");

       6:     // Do the offline connection

       7:     OfflineWebApplicationConnection offlineConn =

       8:         new OfflineWebApplicationConnection();

       9:     offlineConn.Authenticate();

      10:     IList<Guid> updatedUserIds = 

      11:         offlineConn.GetUpdatedRecordsForApplication(lastUpdatedDate);

      12:     WlkMiTracer.Instance.Log("HVSync.cs", WlkMiEvent.AppSync, WlkMiCat.Info,

      13:         string.Format("Got {0} updated records from HealthVault", updatedUserIds.Count));

      14:  

      15:     foreach(Guid recordid in updatedUserIds)

      16:     {

      17:         ProfileModel syncUser = ProfileModel.Fetch(recordid);

      18:         if (syncUser == null)

      19:         {

      20:             WlkMiTracer.Instance.Log("HVSync.cs", WlkMiEvent.AppSync, WlkMiCat.Error,

      21:                 string.Format("No WlkMi user found for recordif {0} ", recordid));

      22:             continue;

      23:         }

      24:         // Decide to update this guy?

      25:         if (syncUser.UserCtx.hv_last_sync_time > DateTime.Now.AddSeconds(

      26:             -Constants.UserSyncIntervalInSeconds))

      27:         {

      28:             WlkMiTracer.Instance.Log("HVSync.cs", WlkMiEvent.AppSync, WlkMiCat.Info,

      29:                 string.Format("Skipping sync for user {0} ", syncUser.UserCtx.user_id));

      30:         }

      31:         else

      32:         {

      33:             HVSync.OfflineSyncUser(syncUser);

      34:         }

      35:     }

      36: }

    Suggestions?

    There are various ways in which the HealthVault platform can assist application in syncing with the data native to HealthVault. One thing comes to my mind is support for feedsync. You may have a lot of suggestions, please feel free to chime in the comments!!

    Sharing Your WalkMe Pedometer using E-Mail Signature

    Several folks have asked me how can one get the WalkMe pedometer to show in Outlook signature. I’m outlining the steps below, for the restless folks most important step is Step 7.

    1. Sign-In the WalkMe HealthVault application
    2. Click on the “Share” tab
    3. Make sure the “Allow Other to see my WalkMe data” checkbox is checked
    4. If you check the box the page refreshes, saying Sharing is turn on
    5. Scroll to the bottom of the page – to Share your steps as an image optionWalkme
    6. Click on file part of “Save this file as your outlook signature”
    7. Save the walkme.htm file in your C:Users[YourUserName]AppDataRoamingMicrosoftSignatures director. Please note the part after [YourUserName] of this directory is hidden and you will manually need to type it in your Windows explorer to get to the full directory. Let me know if you can’t locate this directory on Windows systems other Vista or Seven (it should be under C:Documents & Settings[YourUserName]Application DataRoamingMicrosoftSignatures on Windows XP).
    8. To test the signature open Outlook and and create new mail. Click on the “Signature” part of ribbon (outlook 2007) and you will see WalkMe in drop down. If you select WalkMe signature you should see something like below in your

      outlook email :Untitled 

     

     

     

     

     

    Enjoy your walking and keep yourself motivated by communicating your live pedometer through the signature.

    Microsoft Connected Health Conference – Cover It Live!

    Here is the live feed about the conference:
    &lt;a href=”http://www.coveritlive.com/mobile.php?option=com_mobile&amp;task=viewaltcast&amp;altcast_code=10225acfa4&#8243; &gt;Connected Health Conference&lt;/a&gt;

    Over the period of day and a half, I had great time talking to our application and consulting partners. It was great to learn about some shortcomings and bugs in our platform and it was encouraging to see the excitement among partners around some of our upcoming features.

    On the pre-conference day I was surprised to see the strong attendance in both business and technical 101 session. Loved the EMR, Medicare and usefulness perspectives in the keynotes.

    John Chilmarks expresses his fear about HSG turning a blind eye to harnessing the power of disruptive forces and falling in line with the status quo. Well I think in the conference of this nature its hard to bring the innovative startups without carrots, but hey we tried that with [email protected] side event.

    Anyways, overall I had a great conference, had a couple of motivated partners sign up to try our improvements in the Java library and help move the state of Java and PHP libraries forward. If your are interested and have feedback on those pieces feel free to leave a comment..

    Understanding Vocabularies. Wait! What did you say?

    Any data system the semantic meaning of data is as important as the strucutre of the data. In HealthVault we expose a very structured data set in form of various data types and the semantic meaning of the content in those data sets is dictated by vocabularies.

    HealthVault Vocabulary is a big area so I’m going to attempt to break this down in separate series of posts. In this post i’m primarily going to focus on vocabularies in general.

    Many of you might have heard of the term – Semantic Web or Web 3.0. So whats this buzz about?  Well Web 1.0 was for humans to connect, Web 2.0 was for systems to connect to humans via rich internet applications. Web 3.0 promises a web for systems – a web where programs can communicate and link to each other. So what this implies is for Semantic Web to be successful – the data being put on the semantic internet need not only be structured but also the content be in such a way that computer programs can understand the meaning of it. This is only possible if everyone has a shared Vocabulary or Ontology, or a mechanism to relate to a new Vocabulary.

    To solve the ontology problem we can just sit down and invent a vocabulary which everyone will use henceforth and be done with it, right!  First, we won’t agree to single vocabulary and second we can’t plan for future vocabularies. And the most important challenge is that the system which powers this vocabulary needs to agree with the architecture of the web i.e must be decentralized and open!

    The semantic web community is using a very powerful way to achieve this. They are using the same mechanism which powers resource discovery (for example – URL linking) to discover and understand vocabularies. Two candidates which make this possible are RDF (resource description format) and OWL (Web Ontology Language). I won’t describe these technologies in details here but keep it for some other day. However the point of this note is to surface example ontologies or vocabularies this community has successfully used/developed so far:

    So how does this fit in the HealthCare? John Hamalka outlines the elements of vocabulary whicn an EHR can use in his post – http://geekdoctor.blogspot.com/2009/04/data-elements-of-ehr.html. He mentions preferred vocabularies and transports for some of important EHR elements. In the following posts i will try to go deeper in this area.

    So how does this fit with HealthVault? Well HealthVault exposes all the vocabularies it uses – http://developer.healthvault.com/types/vocabs.aspx. We let people also annotate their data with any vocabulary they like. However this leds to an interesting interoperability problem, so on the XSD schemas of our data types (http://developer.healthvault.com/types/types.aspx) we specify preferred vocabularies for some data elements. In the following posts i will provide more details with regards to this.

    As you can from John’s post their is no dearth of language systems for various medical or healthcare terms. However their is a big gap on best practices on how one can denormalize various vocabularies for implementeting systems which can interoperate with other systems using different vocabularies. I tend to think that there are some lessons to be learned in this area from semantic web efforts and also a need for a more structured effort to surface best practices. May be I’ll dig deeper in this area in one of the future posts.

    Next post: Recommended Vocabularies for Various Data Contexts.

    Reblog this post [with Zemanta]