Debugging help: Python FHIR client resource resolution

504 views
Skip to first unread message

A :-)

unread,
Apr 12, 2016, 9:42:40 PM4/12/16
to SMART on FHIR
Hi!  I'm part of a student team at Georgia Tech, and we're working on a prototype that uses FHIR.  This prototype is a webapp based on the Django framework, so we're using the Python FHIR client from https://github.com/smart-on-fhir/client-py.  (The FHIR client made it really convenient to get started, by the way - so thank you to anyone who has contributed to that!)

I'm really, really sorry for the length of this e-mail - I tried to sand it down but found that it didn't make a lot of sense without concrete examples.

Some of the records we're saving and retrieving use references.  For instance, here's an example of a Communication we're pulling from the FHIR server:

{
"resourceType":"Communication",
"meta":{
"versionId":"1",
"lastUpdated":"2016-03-28T21:17:04.651-04:00"
},
"text":{
"status":"generated",
"div":"<div>Healthy Weight message</div>"
},
"category":{
"coding":[
{
"system":"http://acme.org/messagetypes",
"code":"general"
}
],
"text":"general"
},
"sender":{
"reference":"Practitioner/Practitioner-2189",
"display":"Your Care Coordinator"
},
"recipient":[
{
"reference":"Patient/18791962",
"display":"Diana's parent or guardian"
}
],
"payload":[
{
"contentString":"The YMCA near your home just started a new dance club for girls age 8-10!"
}
],
"status":"completed",
"sent":"2016-03-29T01:17:04-0700",
"reason":[
{
"text":"Resource referral"
}
]
}

We retrieve Communications using a search like this:

try:
search = communication.Communication.where(struct={"recipient":"Patient/"+patientId})
messages = search.perform(smart.server)
if messages.total > 0:
messages = map(lambda(entry): entry.resource, messages.entry)
...
except Exception:
    ...

The resources are coming back just fine, and the body contents are as we would expect, but when we try to retrieve referenced entities (in this case, the sender), it always fails with "WARNING:root:No `reference` set, cannot resolve."  For instance,

>>> messages[0]
<fhirclient.models.communication.Communication object at 0x10d5eeb90>
>>> messages[0].sender
<fhirclient.models.fhirreference.FHIRReference object at 0x10d60ffd0>
>>> messages[0].sender.resolved(practitioner.Practitioner)
WARNING:root:No `reference` set, cannot resolve
None 
>>> messages[0].sender.resolvedReference(messages[0].sender.reference)
None

Looking at the source, I see:

refid = self.processedReferenceIdentifier()
if not refid:
logging.warning("No `reference` set, cannot resolve")
return None
And:
def processedReferenceIdentifier(self):
""" Normalizes the reference-id.
"""
if not self.reference:
return None
if '#' == self.reference[0]:
return self.reference[1:]
# TODO: distinguish absolute (has "://") and relative URLs
return None

But the reference we're getting back is in the format:
>>> messages[0].sender.reference
u'Practitioner/Practitioner-2189'

No leading #, obviously, so it makes sense that processedReferenceIdentifier() is always None.

I'm very new to FHIR, so I have absolutely no idea what to conclude from this. :-)

Is it:

1) The Reference we add when creating the resource is in the wrong format, and is supposed to be prefixed with #?  (If so, is it expected behavior that the server allows us to create the resource anyway?)
2) This is the wrong method for us to use to resolve references?  (If so, what's the right one to call?)
3) We're supposed to call / set up something else on the resource before resolving references?  (If so, what?)
4) Resource resolution isn't implemented yet?  (In which case, are there any "gotchas" I should know about before I add it?)

Or something totally different?

Right now we're manually pulling messages[0].sender.reference in our code, stripping it and stuffing it into a .read() call, but that gives me a sinking feeling I'm reinventing the wheel.

--Angela Smiley

P.S.: we're testing against the MiHIN FHIR server, if that makes a difference (e.g. in expected reference format).

P.P.S.: any errors or bad practices you spot in my JSON or code, please mention even if they're not relevant to this specific problem.  I'm a shameless FHIR newbie.

Nikolai Schwertner

unread,
Apr 12, 2016, 10:25:49 PM4/12/16
to smart-...@googlegroups.com
Hi Angela,

Welcome! There is nothing wrong with being new to FHIR and asking. At a quick glance, I don't see anything particularly wrong with your resource example. The snippet from the Python client does indeed feel incomplete (the TO DO part is likely a placeholder for code yet to be implemented). Pascal can tell you more about it and how to go about getting the client to resolve references.

-Nikolai
--
You received this message because you are subscribed to the Google Groups "SMART on FHIR" group.
To unsubscribe from this group and stop receiving emails from it, send an email to smart-on-fhi...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Pascal Pfiffner

unread,
Apr 13, 2016, 3:11:52 AM4/13/16
to SMART on FHIR
No need to apologize indeed!

First: which version of the client is this? Reference resolving has received a bit of work but not with the love it deserves. But the snippet you show is outdated, the current client should be able to resolve your references or give better feedback: https://github.com/smart-on-fhir/client-py/blob/master/fhirclient/models/fhirreference.py#L51

Second, just to clear up your questions: there basically are 3 types of references:

- contained references, referenced with the hash part of a URL. So the reference to a contained sender with id "sender" would be "#sender", and the resource would live in the containing resource's "contained" array.
- relative references, like the ones you have. The reference "Practitioner/sender" means the Practitioner resource with id "sender" on the same server
- absolute references. The reference is a full URL and hence it could live on a different server. Resolving these is not implemented and you'll get a warning about that fact.

Hope this helps!
Pascal

A :-)

unread,
Apr 13, 2016, 3:36:28 AM4/13/16
to Pascal Pfiffner, SMART on FHIR
Hmm!  Very strange.  I must be misunderstanding what's going on here.  I do see the same code on the current master - specifically, the check for "refid=self.processedReferenceIdentifier(); if not refid..." is on lines 28-29, and the definition of processedReferenceIdentifier is on lines 65-75.  It never seems to reach the line which you've highlighted (line 51).

Thank you for the clarification on the references - I had no idea about the contained format so that clears up a number of things.  It does sound like the Practitioner/some-id format should be supported, so I'll dig a little deeper.  Is there an example anywhere of using resolved() for the relative reference type, so I can compare my code to it?  Unfortunately fhirreference_tests.py only seems to test contained resources, and flask_app.py doesn't make use of references at all.

--a :-)

--

Pascal Pfiffner

unread,
Apr 13, 2016, 7:23:54 AM4/13/16
to SMART on FHIR, phase.o...@gmail.com
Ha, wait, whoa, you're right, that's an oversight and a bug! I'll push a fix to master. Maybe I can also add a test case so the usage is clearer.

Pascal

Pascal Pfiffner

unread,
Apr 13, 2016, 8:15:15 AM4/13/16
to SMART on FHIR, phase.o...@gmail.com
Alright, I have pushed an update to master with added unit tests. This should now work, let me know how it goes! Resolving references that are contained vs. relative ones (and absolute ones in the future) works the same way for you, so you should not have to worry.

Thanks for testing!
Pascal

Josh Mandel

unread,
Apr 13, 2016, 9:31:51 AM4/13/16
to Pascal Pfiffner, SMART on FHIR
Thanks Angela for reaching out, and Nikolai + Pascal for a rapid response!

While we're talking about references, it's probably worth pointing out (for completeness!) that there's one more kind of resource reference in FHIR: bundle-relative. That is, if you get a bundle of resources (e.g. a set of search results), one of them can refer to another with a reference whose "value" matches a Bundle.entry.fullUrl. This is more relevant for clients who want to create data on a server by constructing a bundle of resources to post all at once, so it's not really critical here. (Details at http://hl7-fhir.github.io/bundle.html#references)

A :-)

unread,
Apr 14, 2016, 2:50:55 AM4/14/16
to Josh Mandel, Pascal Pfiffner, SMART on FHIR
Hey, thanks!  I feel a little guilty - I didn't mean to put more work in your lap.  But I'm very grateful for the quick fix!

Thanks also, Josh, for the additional details - every piece of the puzzle adds a little bit more to my picture of the overall standard.  We don't have a place where we need it just yet, but we're always looking for new capabilities we can add, so knowing about it may inspire other feature ideas (or just smoother workflows) later.

Cheers!
--a :-)

Pascal Pfiffner

unread,
Apr 14, 2016, 3:28:25 AM4/14/16
to SMART on FHIR, jma...@gmail.com, phase.o...@gmail.com
Don't feel guilty! The framework is far from perfect, mostly because we don't use all the capabilities that it should have in our own project, hence some things simply don't work. Reference resolving is an important aspect, so it's good you need this and we finally need to build solid support for it. I hope to do some more work on it in the next weeks. If you have suggestions or pull requests send them along!

Pascal

Pascal Pfiffner

unread,
Apr 15, 2016, 7:36:49 AM4/15/16
to SMART on FHIR, jma...@gmail.com, phase.o...@gmail.com
Support for resolving references has been pushed to both `develop` and `master`, but is not on pip yet.

Pascal
Reply all
Reply to author
Forward
0 new messages