Gravitate Health FHIR Implementation Guide
0.1.0 - CI Build

Gravitate Health FHIR Implementation Guide, published by Gravitate Health Project. This guide is not an authorized publication; it is the continuous build for version 0.1.0 built by the FHIR (HL7® FHIR® Standard) CI Build. This version is based on the current content of https://github.com/hl7-eu/gravitate-health/ and changes regularly. See the Directory of published versions

: pregnancy-lens - JSON Representation

Draft as of 2024-06-12

Raw json | Download


{
  "resourceType" : "Library",
  "id" : "588",
  "meta" : {
    "versionId" : "1",
    "lastUpdated" : "2024-06-12T12:30:09.424+00:00",
    "source" : "#8e0ccded-206a-96",
    "profile" : [
      🔗 "http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/lens"
    ]
  },
  "text" : {
    "status" : "generated",
    "div" : "<div xmlns=\"http://www.w3.org/1999/xhtml\"><h2>Parameters</h2><table class=\"grid\"><tr><td/><td>in</td><td/><td/><td>CodeableConcept</td><td>parameter if it exists</td></tr></table><h2>Contents</h2><p><code>application/javascript</code></p><pre><code>let pvData = pv;\nlet htmlData = html;\n\nlet epiData = epi;\nlet ipsData = ips;\n\nlet getSpecification = () =&gt; {\n    return &quot;1.0.0&quot;;\n};\n\nlet annotationProcess = (listOfCategories, enhanceTag, document, response) =&gt; {\n    listOfCategories.forEach((check) =&gt; {\n        if (response.includes(check)) {\n            let elements = document.getElementsByClassName(check);\n            for (let i = 0; i &lt; elements.length; i++) {\n                elements[i].classList.add(enhanceTag);\n            }\n            if (document.getElementsByTagName(&quot;head&quot;).length &gt; 0) {\n                document.getElementsByTagName(&quot;head&quot;)[0].remove();\n            }\n            if (document.getElementsByTagName(&quot;body&quot;).length &gt; 0) {\n                response = document.getElementsByTagName(&quot;body&quot;)[0].innerHTML;\n                console.log(&quot;Response: &quot; + response);\n            } else {\n                console.log(&quot;Response: &quot; + document.documentElement.innerHTML);\n                response = document.documentElement.innerHTML;\n            }\n        }\n    });\n\n    if (response == null || response == &quot;&quot;) {\n        throw new Error(\n            &quot;Annotation proccess failed: Returned empty or null response&quot;\n        );\n        //return htmlData\n    } else {\n        console.log(&quot;Response: &quot; + response);\n        return response;\n    }\n}\n\nlet annotateHTMLsection = async (listOfCategories, enhanceTag) =&gt; {\n    let response = htmlData;\n    let document;\n\n    if (typeof window === &quot;undefined&quot;) {\n        let jsdom = await import(&quot;jsdom&quot;);\n        let { JSDOM } = jsdom;\n        let dom = new JSDOM(htmlData);\n        document = dom.window.document;\n        return annotationProcess(listOfCategories, enhanceTag, document, response);\n    } else {\n        document = window.document;\n        return annotationProcess(listOfCategories, enhanceTag, document, response);\n    }\n};\n\nlet getIPSAge = (birthDate) =&gt; {\n    let today = new Date();\n    let birthDateParsed = new Date(birthDate);\n\n    let ageMiliseconds = today - birthDateParsed;\n    let age = Math.floor(ageMiliseconds / 31536000000);\n\n    return age;\n}\n\nlet enhance = async () =&gt; {\n    //                  pregnancyCategory    breastfeedingCategory\n    //                             SNOMED    SNOMED\n    let listOfCategoriesToSearch = [&quot;W78&quot;, &quot;77386006&quot;, &quot;69840006&quot;]; //&quot;contra-indication-pregancy&quot;]\n\n    // Get IPS gender and check if is female\n    let gender;\n\n    let enhanceTag;\n\n    if (ips == &quot;&quot; || ips == null) {\n        throw new Error(&quot;Failed to load IPS: the LEE is getting a empty IPS&quot;);\n    }\n    ips.entry.forEach((element) =&gt; {\n        if (element.resource.resourceType == &quot;Patient&quot;) {\n            gender = element.resource.gender;\n            if (gender != &quot;female&quot; || getIPSAge(element.resource.birthDate) &gt;= 75) {\n                enhanceTag = &quot;collapsed&quot;;\n            } else {\n                enhanceTag = &quot;highlight&quot;;\n            }\n        }\n    });\n\n    // ePI traslation from terminology codes to their human redable translations in the sections\n    let compositions = 0;\n    let categories = [];\n    epi.entry.forEach((entry) =&gt; {\n        if (entry.resource.resourceType == &quot;Composition&quot;) {\n            compositions++;\n            //Iterated through the Condition element searching for conditions\n            entry.resource.extension.forEach((element) =&gt; {\n                \n                // Check if the position of the extension[1] is correct\n                if (element.extension[1].url == &quot;concept&quot;) {\n                    // Search through the different terminologies that may be avaible to check in the condition\n                    if (element.extension[1].valueCodeableReference.concept != undefined) {\n                        element.extension[1].valueCodeableReference.concept.coding.forEach(\n                            (coding) =&gt; {\n                                console.log(&quot;Extension: &quot; + element.extension[0].valueString + &quot;:&quot; + coding.code)\n                                // Check if the code is in the list of categories to search\n                                if (listOfCategoriesToSearch.includes(coding.code)) {\n                                    // Check if the category is already in the list of categories\n                                    categories.push(element.extension[0].valueString);\n                                }\n                            }\n                        );\n                    }\n                }\n            });\n        }\n    });\n\n    if (compositions == 0) {\n        throw new Error('Bad ePI: no category &quot;Composition&quot; found');\n    }\n\n    if (categories.length == 0) {\n        // throw new Error(&quot;No categories found&quot;, categories);\n        return htmlData;\n    }\n    //Focus (adds highlight class) the html applying every category found\n    return await annotateHTMLsection(categories, enhanceTag);\n};\n\nreturn {\n    enhance: enhance,\n    getSpecification: getSpecification,\n};\n</code></pre></div>"
  },
  "extension" : [
    {
      "url" : "http://hl7.eu/fhir/ig/gravitate-health/StructureDefinition/lee-version",
      "valueString" : "dev"
    }
  ],
  "url" : "http://hl7.eu/fhir/ig/gravitate-health/Library/mock-lib",
  "identifier" : [
    {
      "system" : "http://gravitate-health.lst.tfo.upm.es",
      "value" : "pregnancy-lens"
    }
  ],
  "version" : "0.1.0",
  "name" : "pregnancy-lens",
  "title" : "pregnancy-lens",
  "status" : "draft",
  "experimental" : true,
  "type" : {
    "coding" : [
      {
        "code" : "logical-library"
      }
    ]
  },
  "date" : "2024-06-12T12:23:10.005Z",
  "publisher" : "Gravitate Health Project",
  "contact" : [
    {
      "name" : "Gravitate Health Project",
      "telecom" : [
        {
          "system" : "url",
          "value" : "https://www.gravitatehealth.eu/"
        }
      ]
    },
    {
      "name" : "Gravitate Health Project",
      "telecom" : [
        {
          "system" : "url",
          "value" : "https://www.gravitatehealth.eu/"
        }
      ]
    }
  ],
  "description" : "Lens that highlight or collapses pregnancy related information",
  "jurisdiction" : [
    {
      "coding" : [
        {
          "system" : "urn:iso:std:iso:3166",
          "code" : "US"
        }
      ]
    }
  ],
  "purpose" : "Collapse or highlight pregnancy related information on a preprocessed ePI.",
  "usage" : "You can import this lens directly to your FHIR Server which suports Library Resource type.",
  "copyright" : "© 2024 Gravitate Health",
  "parameter" : [
    {
      "use" : "in",
      "documentation" : "parameter if it exists",
      "type" : "CodeableConcept"
    }
  ],
  "content" : [
    {
      "contentType" : "application/javascript",
      "data" : "bGV0IHB2RGF0YSA9IHB2OwpsZXQgaHRtbERhdGEgPSBodG1sOwoKbGV0IGVwaURhdGEgPSBlcGk7CmxldCBpcHNEYXRhID0gaXBzOwoKbGV0IGdldFNwZWNpZmljYXRpb24gPSAoKSA9PiB7CiAgICByZXR1cm4gIjEuMC4wIjsKfTsKCmxldCBhbm5vdGF0aW9uUHJvY2VzcyA9IChsaXN0T2ZDYXRlZ29yaWVzLCBlbmhhbmNlVGFnLCBkb2N1bWVudCwgcmVzcG9uc2UpID0+IHsKICAgIGxpc3RPZkNhdGVnb3JpZXMuZm9yRWFjaCgoY2hlY2spID0+IHsKICAgICAgICBpZiAocmVzcG9uc2UuaW5jbHVkZXMoY2hlY2spKSB7CiAgICAgICAgICAgIGxldCBlbGVtZW50cyA9IGRvY3VtZW50LmdldEVsZW1lbnRzQnlDbGFzc05hbWUoY2hlY2spOwogICAgICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IGVsZW1lbnRzLmxlbmd0aDsgaSsrKSB7CiAgICAgICAgICAgICAgICBlbGVtZW50c1tpXS5jbGFzc0xpc3QuYWRkKGVuaGFuY2VUYWcpOwogICAgICAgICAgICB9CiAgICAgICAgICAgIGlmIChkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiaGVhZCIpLmxlbmd0aCA+IDApIHsKICAgICAgICAgICAgICAgIGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJoZWFkIilbMF0ucmVtb3ZlKCk7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgaWYgKGRvY3VtZW50LmdldEVsZW1lbnRzQnlUYWdOYW1lKCJib2R5IikubGVuZ3RoID4gMCkgewogICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5VGFnTmFtZSgiYm9keSIpWzBdLmlubmVySFRNTDsKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJSZXNwb25zZTogIiArIHJlc3BvbnNlKTsKICAgICAgICAgICAgfSBlbHNlIHsKICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJSZXNwb25zZTogIiArIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5pbm5lckhUTUwpOwogICAgICAgICAgICAgICAgcmVzcG9uc2UgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuaW5uZXJIVE1MOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSk7CgogICAgaWYgKHJlc3BvbnNlID09IG51bGwgfHwgcmVzcG9uc2UgPT0gIiIpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoCiAgICAgICAgICAgICJBbm5vdGF0aW9uIHByb2NjZXNzIGZhaWxlZDogUmV0dXJuZWQgZW1wdHkgb3IgbnVsbCByZXNwb25zZSIKICAgICAgICApOwogICAgICAgIC8vcmV0dXJuIGh0bWxEYXRhCiAgICB9IGVsc2UgewogICAgICAgIGNvbnNvbGUubG9nKCJSZXNwb25zZTogIiArIHJlc3BvbnNlKTsKICAgICAgICByZXR1cm4gcmVzcG9uc2U7CiAgICB9Cn0KCmxldCBhbm5vdGF0ZUhUTUxzZWN0aW9uID0gYXN5bmMgKGxpc3RPZkNhdGVnb3JpZXMsIGVuaGFuY2VUYWcpID0+IHsKICAgIGxldCByZXNwb25zZSA9IGh0bWxEYXRhOwogICAgbGV0IGRvY3VtZW50OwoKICAgIGlmICh0eXBlb2Ygd2luZG93ID09PSAidW5kZWZpbmVkIikgewogICAgICAgIGxldCBqc2RvbSA9IGF3YWl0IGltcG9ydCgianNkb20iKTsKICAgICAgICBsZXQgeyBKU0RPTSB9ID0ganNkb207CiAgICAgICAgbGV0IGRvbSA9IG5ldyBKU0RPTShodG1sRGF0YSk7CiAgICAgICAgZG9jdW1lbnQgPSBkb20ud2luZG93LmRvY3VtZW50OwogICAgICAgIHJldHVybiBhbm5vdGF0aW9uUHJvY2VzcyhsaXN0T2ZDYXRlZ29yaWVzLCBlbmhhbmNlVGFnLCBkb2N1bWVudCwgcmVzcG9uc2UpOwogICAgfSBlbHNlIHsKICAgICAgICBkb2N1bWVudCA9IHdpbmRvdy5kb2N1bWVudDsKICAgICAgICByZXR1cm4gYW5ub3RhdGlvblByb2Nlc3MobGlzdE9mQ2F0ZWdvcmllcywgZW5oYW5jZVRhZywgZG9jdW1lbnQsIHJlc3BvbnNlKTsKICAgIH0KfTsKCmxldCBnZXRJUFNBZ2UgPSAoYmlydGhEYXRlKSA9PiB7CiAgICBsZXQgdG9kYXkgPSBuZXcgRGF0ZSgpOwogICAgbGV0IGJpcnRoRGF0ZVBhcnNlZCA9IG5ldyBEYXRlKGJpcnRoRGF0ZSk7CgogICAgbGV0IGFnZU1pbGlzZWNvbmRzID0gdG9kYXkgLSBiaXJ0aERhdGVQYXJzZWQ7CiAgICBsZXQgYWdlID0gTWF0aC5mbG9vcihhZ2VNaWxpc2Vjb25kcyAvIDMxNTM2MDAwMDAwKTsKCiAgICByZXR1cm4gYWdlOwp9CgpsZXQgZW5oYW5jZSA9IGFzeW5jICgpID0+IHsKICAgIC8vICAgICAgICAgICAgICAgICAgcHJlZ25hbmN5Q2F0ZWdvcnkgICAgYnJlYXN0ZmVlZGluZ0NhdGVnb3J5CiAgICAvLyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgU05PTUVEICAgIFNOT01FRAogICAgbGV0IGxpc3RPZkNhdGVnb3JpZXNUb1NlYXJjaCA9IFsiVzc4IiwgIjc3Mzg2MDA2IiwgIjY5ODQwMDA2Il07IC8vImNvbnRyYS1pbmRpY2F0aW9uLXByZWdhbmN5Il0KCiAgICAvLyBHZXQgSVBTIGdlbmRlciBhbmQgY2hlY2sgaWYgaXMgZmVtYWxlCiAgICBsZXQgZ2VuZGVyOwoKICAgIGxldCBlbmhhbmNlVGFnOwoKICAgIGlmIChpcHMgPT0gIiIgfHwgaXBzID09IG51bGwpIHsKICAgICAgICB0aHJvdyBuZXcgRXJyb3IoIkZhaWxlZCB0byBsb2FkIElQUzogdGhlIExFRSBpcyBnZXR0aW5nIGEgZW1wdHkgSVBTIik7CiAgICB9CiAgICBpcHMuZW50cnkuZm9yRWFjaCgoZWxlbWVudCkgPT4gewogICAgICAgIGlmIChlbGVtZW50LnJlc291cmNlLnJlc291cmNlVHlwZSA9PSAiUGF0aWVudCIpIHsKICAgICAgICAgICAgZ2VuZGVyID0gZWxlbWVudC5yZXNvdXJjZS5nZW5kZXI7CiAgICAgICAgICAgIGlmIChnZW5kZXIgIT0gImZlbWFsZSIgfHwgZ2V0SVBTQWdlKGVsZW1lbnQucmVzb3VyY2UuYmlydGhEYXRlKSA+PSA3NSkgewogICAgICAgICAgICAgICAgZW5oYW5jZVRhZyA9ICJjb2xsYXBzZWQiOwogICAgICAgICAgICB9IGVsc2UgewogICAgICAgICAgICAgICAgZW5oYW5jZVRhZyA9ICJoaWdobGlnaHQiOwogICAgICAgICAgICB9CiAgICAgICAgfQogICAgfSk7CgogICAgLy8gZVBJIHRyYXNsYXRpb24gZnJvbSB0ZXJtaW5vbG9neSBjb2RlcyB0byB0aGVpciBodW1hbiByZWRhYmxlIHRyYW5zbGF0aW9ucyBpbiB0aGUgc2VjdGlvbnMKICAgIGxldCBjb21wb3NpdGlvbnMgPSAwOwogICAgbGV0IGNhdGVnb3JpZXMgPSBbXTsKICAgIGVwaS5lbnRyeS5mb3JFYWNoKChlbnRyeSkgPT4gewogICAgICAgIGlmIChlbnRyeS5yZXNvdXJjZS5yZXNvdXJjZVR5cGUgPT0gIkNvbXBvc2l0aW9uIikgewogICAgICAgICAgICBjb21wb3NpdGlvbnMrKzsKICAgICAgICAgICAgLy9JdGVyYXRlZCB0aHJvdWdoIHRoZSBDb25kaXRpb24gZWxlbWVudCBzZWFyY2hpbmcgZm9yIGNvbmRpdGlvbnMKICAgICAgICAgICAgZW50cnkucmVzb3VyY2UuZXh0ZW5zaW9uLmZvckVhY2goKGVsZW1lbnQpID0+IHsKICAgICAgICAgICAgICAgIAogICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIHBvc2l0aW9uIG9mIHRoZSBleHRlbnNpb25bMV0gaXMgY29ycmVjdAogICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuZXh0ZW5zaW9uWzFdLnVybCA9PSAiY29uY2VwdCIpIHsKICAgICAgICAgICAgICAgICAgICAvLyBTZWFyY2ggdGhyb3VnaCB0aGUgZGlmZmVyZW50IHRlcm1pbm9sb2dpZXMgdGhhdCBtYXkgYmUgYXZhaWJsZSB0byBjaGVjayBpbiB0aGUgY29uZGl0aW9uCiAgICAgICAgICAgICAgICAgICAgaWYgKGVsZW1lbnQuZXh0ZW5zaW9uWzFdLnZhbHVlQ29kZWFibGVSZWZlcmVuY2UuY29uY2VwdCAhPSB1bmRlZmluZWQpIHsKICAgICAgICAgICAgICAgICAgICAgICAgZWxlbWVudC5leHRlbnNpb25bMV0udmFsdWVDb2RlYWJsZVJlZmVyZW5jZS5jb25jZXB0LmNvZGluZy5mb3JFYWNoKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgKGNvZGluZykgPT4gewogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKCJFeHRlbnNpb246ICIgKyBlbGVtZW50LmV4dGVuc2lvblswXS52YWx1ZVN0cmluZyArICI6IiArIGNvZGluZy5jb2RlKQogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIENoZWNrIGlmIHRoZSBjb2RlIGlzIGluIHRoZSBsaXN0IG9mIGNhdGVnb3JpZXMgdG8gc2VhcmNoCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGxpc3RPZkNhdGVnb3JpZXNUb1NlYXJjaC5pbmNsdWRlcyhjb2RpbmcuY29kZSkpIHsKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGhlIGNhdGVnb3J5IGlzIGFscmVhZHkgaW4gdGhlIGxpc3Qgb2YgY2F0ZWdvcmllcwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBjYXRlZ29yaWVzLnB1c2goZWxlbWVudC5leHRlbnNpb25bMF0udmFsdWVTdHJpbmcpOwogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgICAgICAgICAgICAgKTsKICAgICAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgICAgICB9CiAgICAgICAgICAgIH0pOwogICAgICAgIH0KICAgIH0pOwoKICAgIGlmIChjb21wb3NpdGlvbnMgPT0gMCkgewogICAgICAgIHRocm93IG5ldyBFcnJvcignQmFkIGVQSTogbm8gY2F0ZWdvcnkgIkNvbXBvc2l0aW9uIiBmb3VuZCcpOwogICAgfQoKICAgIGlmIChjYXRlZ29yaWVzLmxlbmd0aCA9PSAwKSB7CiAgICAgICAgLy8gdGhyb3cgbmV3IEVycm9yKCJObyBjYXRlZ29yaWVzIGZvdW5kIiwgY2F0ZWdvcmllcyk7CiAgICAgICAgcmV0dXJuIGh0bWxEYXRhOwogICAgfQogICAgLy9Gb2N1cyAoYWRkcyBoaWdobGlnaHQgY2xhc3MpIHRoZSBodG1sIGFwcGx5aW5nIGV2ZXJ5IGNhdGVnb3J5IGZvdW5kCiAgICByZXR1cm4gYXdhaXQgYW5ub3RhdGVIVE1Mc2VjdGlvbihjYXRlZ29yaWVzLCBlbmhhbmNlVGFnKTsKfTsKCnJldHVybiB7CiAgICBlbmhhbmNlOiBlbmhhbmNlLAogICAgZ2V0U3BlY2lmaWNhdGlvbjogZ2V0U3BlY2lmaWNhdGlvbiwKfTsK"
    }
  ]
}