GSoC'20: Add support for FHIR Narratives

Tags: #<Tag:0x00007f0a2a1f1d60> #<Tag:0x00007f0a2a1f1c70> #<Tag:0x00007f0a2a1f1b58>

heilo @ibacher could you be having any additional resource

That list looks to be comprehensive of the list of resources we support.

2 Likes

Should the Default Narratives be generated by the DefaultThymeleafNarrativeGenerator itself or should they rather be rendered in a custom template?

cc: @ibacher @herbert24 @suthagar23

My vote would be “yes”. To phrase things a little more helpfully: ideally, for those resources fully specified by the HAPI FHIR default templates and where an implementation hasn’t specified their own custom template for a given type, it should be rendered as it would be by the default narrative generator. Where we need resources not fully specified by the HAPI FHIR default templates, we should have custom (OpenMRS) templates that mirror the default templates as closely as possible (with the idea that these could be contributed back to HAPI FHIR). That said, an implementation should be able to specify a custom template for any of either the HAPI FHIR defaults, the OpenMRS defaults or other types that we haven’t covered.

1 Like

Okay. So apart from the resources which have default templates provided by HAPI FHIR here, we’ll be adding default templates defined by us, for rest of the resources.

Yes. Ideally, we want them to be similar to the examples provided with the specification. E.g., for Observation. Also note that there are more up-to-date narratives in the main HAPI FHIR distribution here.

2 Likes

Okay. Thanks!

1 Like

Hi there. This post basically enlists the objectives for Coding Phase-1 of the GSoC period. Kindly go through it and provide feedback/suggestions on the same.
cc @herbert24 @ibacher @suthagar23

Objectives for Coding Phase-1

OVERVIEW

  • Creation of Default Narratives for the resources:
    • AllergyIntolerance
    • Condition
    • DiagnosticReport
    • Encounter
    • Location
    • MedicationRequest
    • Medication
    • Observation
    • Patient
    • Person
    • Practitioner
    • RelatedPerson
    • ServiceRequest
    • Task
  • Inclusion of the Narrative as the text element of the Resource.

DETAILS

  • Create a method generateDefaultNarrative, which takes in an IBaseResource object as parameter, and returns an object of Narrative class.

  • It will check if the resource has a default narrative provided by HAPI FHIR. If yes, then it will call the DefaultThymeleafNarrativeGenerator. Else, it will call CustomThymeleafNarrativeGenerator, which will generate the default narrative using a template defined by us.

  • Then, we will extract the text element from the generated narrative, create a Narrative object and return the same, so that it could be assigned to the resource from the place it was called.

The method generateDefaultNarrative would be called in the translator before returning the translated resource. The generated narrative will be assigned to text element of the resource using Resouce.setText(narrative).

For checking if HAPI FHIR provides a default narrative for the resource, we will create an ArrayList of all such resources for which it does. The method will check if the passed resource is present in the array, and then take the above steps accordingly.

Please find the JIRA ticket for this here.
(I have currently added sub-tasks for Coding Phase-1)

Hi @ibacher! I tried to use the dependency you suggested (quoted above for reference) but I still get these errors:

java.lang.NoClassDefFoundError: org/thymeleaf/templateresolver/ITemplateResolver

java.lang.NoSuchMethodError: org.apache.commons.io.IOUtils.toString(Ljava/io/InputStream;Ljava/nio/charset/Charset;)Ljava/lang/String;

java.lang.NoClassDefFoundError: com/github/benmanes/caffeine/cache/Caffeine

unless I add these dependencies to the dependencies section of <root>/pom.xml:

<dependency>
	<groupId>org.thymeleaf</groupId>
	<artifactId>thymeleaf</artifactId>
	<version>3.0.11.RELEASE</version>
</dependency>
<dependency>
	<groupId>commons-io</groupId>
	<artifactId>commons-io</artifactId>
	<version>2.6</version>
</dependency>
<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
	<artifactId>caffeine</artifactId>
	<version>2.8.2</version>
</dependency>

So is it fine if these dependencies are added?

If they’re necessary, then, yes, we need them!

1 Like

Please review the PR for FM2-193 at https://github.com/openmrs/openmrs-module-fhir2/pull/190

cc: @ibacher @herbert24 @suthagar23

@iamsr looked at it thanks , dropped a comment there.

2 Likes

In the resources which have some references to other resources, how are we supposed to display them in the narratives?
For example, the AllergyIntolerance class has patient (of Patient type) and asserter (of Practitioner type). The example here gives a link to that reference’s details, but here we can’t do that, since active elements are not allowed in a narrative.

[BLOCKER] I was thinking of mentioning details like Name, Address of the reference in the narrative, but then I was facing issues in figuring out a way to do so.

cc @ibacher @herbert24 @suthagar23

Quoting from the spec:

The contents of the div element are an XHTML fragment that SHALL contain only the basic HTML formatting elements described in chapters 7-11 (except section 4 of chapter 9) and 15 of the HTML 4.0 standard, <a> elements (either name or href), images and internally contained style attributes.

Note that this explicitly allows anchor tags (<a>), which are how those Patient links are generated). So, the correct thing to do is to display just that kind of link. We may need to do some work to generated the correct link, however; e.g., I would expect the results to be something like:

<strong>subject</strong>: <a href="http://localhost:8080/openmrs/ws/fhir2/R4/Patient/00000000">Patient/00000000</a>

At no point in generating the narrative should we need to fetch more data from the database than is already in the resource. So, for instance, there is this example which renders Patient and Performer name but note that those are included in the JSON as the display property for the reference. Where the display property is present, we should get something like:

<strong>subject</strong>: <a href="http://localhost:8080/openmrs/ws/fhir2/R4/Patient/00000000">John Smith</a>

And where it isn’t we should something like what I showed above.

1 Like

Hi, I created a Thymeleaf template for AllergyIntolerance resource, and generated a narrative by creating an object of AllergyIntolerance basing it upon this example. I tried to resemble the narrative format as closely as I could.

This is how it looks when rendered:

This is the Narrative Div which gets generated:

<div xmlns="http://www.w3.org/1999/xhtml">
    <table class="hapiPropertyTable">
        <tbody>
            <tr>
                <td style="font-weight: bold">Id:</td>
                <td>example</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Identifier:</td>
                <td>12345678</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Clinical Status:</td>
                <td> Active </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Verification Status:</td>
                <td> Confirmed </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Type:</td>
                <td>Allergy</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Category:</td>
                <td>food</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Criticality:</td>
                <td>High Risk</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Code:</td>
                <td> Cashew Nuts </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Patient:</td>
                <td>
                    <a href="http://localhost:8080/openmrs/ws/fhir2/R4/Patient/10010">PatientNAME</a>
                </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Onset:</td>
                <td>01/01/2004</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Recorded Date:</td>
                <td>02/06/2020 10:26:07 PM</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Recorder:</td>
                <td>
                    <a href="http://localhost:8080/openmrs/ws/fhir2/R4/Practitioner/10011">Practitioner/10011</a>
                </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Asserter:</td>
                <td>
                    <a href="http://localhost:8080/openmrs/ws/fhir2/R4/Patient/10211">AsserterNAME</a>
                </td>
            </tr>
            <tr>
                <td style="font-weight: bold">Last Occurrence:</td>
                <td>02/06/2020</td>
            </tr>
            <tr>
                <td style="font-weight: bold">Note:</td>
                <td>The criticality is high becasue of the observed anaphylactic reaction when challenged with cashew extract.</td>
            </tr>
        </tbody>
    </table>
    <blockquote>
        <table class="hapiPropertyTable">
            <tbody>
                <tr>
                    <td style="font-weight: bold; text-decoration: underline;">Reaction:</td>
                    <td/>
                </tr>
                <tr>
                    <td style="font-weight: bold">Substance:</td>
                    <td> cashew nut allergenic extract Injectale Product </td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Manifestation:</td>
                    <td> Anaphylactic reaction </td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Description:</td>
                    <td>Challenge Protocol. Severe reaction to subcutaneous cashew extract. Epinephrine administered</td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Onset:</td>
                    <td>02/06/2020</td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Severity:</td>
                    <td>SEVERE</td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Exposure Route:</td>
                    <td> Subcutaneous route </td>
                </tr>
            </tbody>
        </table>
    </blockquote>
    <blockquote>
        <table class="hapiPropertyTable">
            <tbody>
                <tr>
                    <td style="font-weight: bold; text-decoration: underline;">Reaction:</td>
                    <td/>
                </tr>
                <tr>
                    <td style="font-weight: bold">Manifestation:</td>
                    <td> Anaphylactic reaction </td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Onset:</td>
                    <td>02/06/2020</td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Severity:</td>
                    <td>MODERATE</td>
                </tr>
                <tr>
                    <td style="font-weight: bold">Note:</td>
                    <td>The patient reports that the onset of urticaria was within 15 minutes of eating cashews.</td>
                </tr>
            </tbody>
        </table>
    </blockquote>
</div>

Please provide feedback/suggestions.

Also, is there a simpler way of populating resources other than setting all the values one-by-one (which I did :sweat_smile:)?

cc @ibacher @herbert24 @suthagar23

I might take a look at this configuration file for how HAPI breaks down narratives into component parts. Also, I realise you were just following the example, but I hate the idea of using a <blockquote> around the reaction types.

I’d also prefer wrapping the the headers in <td><strong>Id:</strong></td> rather than <td style="font-weight: bold">Id:</td>. Even better might be to just have <td>Id:</td> and CSS with a rule like:

table.hapiPropertyTable tr > td:first-of-type {
    font-weight: bold;
}

(In other words, leave the styling decisions as much out of the template as possible).

@ibacher Yes I’ve tried to do it in the same way. Actually, for the datatypes (eg CodeableConcept, etc), I’ve used the Narratives provided by HAPI itself, to keep it the way it is.

Okay, so I’ll remove the blockquote then?

Okay. The reason for putting bold text inline was to kind of essentially make it look that way. But yeah it makes it a bit messier. I will use a stylesheet instead.

I’ll be proceeding with creating narrative templates for other resources in a similar way (after correcting these issues). So other than the issues you’ve mentioned, its fine right?

Yes, I think it’s fine. The other thing to think about is how we might go about localising the narratives, but that’s a secondary concern right now.

1 Like

@ibacher Also, where should these Default Narrative templates reside? A sub-directory under Resources?