onaio / rdt-standard

RDT Open Guidelines Application
Apache License 2.0
1 stars 5 forks source link

Update RDT templates dynamically #283

Closed pld closed 3 years ago

pld commented 4 years ago

As a healthcare project manager I'd like to add new RDTs to the app without needing my users to upgrade the app.

Currently the UW RDT reader reads templates from a JSON file and an image file, which requires a new deploy add a new RDT.

UW can modify this to read from a database or over the API, including the image as a blob. We'd like to extend the reader to support dynamically configurable RDT reading like this.

These are the parameters in the UW reader we would need to set

https://github.com/cjpark87/rdt-scan/blob/master/readme_assets/rdt_configuration.md#3-modifying-the-configuration-file

pld commented 4 years ago

Template images for FHIR are here, https://github.com/cjpark87/rdt-scan/tree/master/app/src/main/res/drawable-nodpi

there are the configs that we will be ignoring in the future, https://github.com/cjpark87/rdt-scan/blob/master/app/src/main/assets/config.json

RDTScan chooses the name here from an intent, https://github.com/cjpark87/rdt-scan/blob/3bb41cf0ddff8381c1f4d5d860809758de39b575/app/src/main/java/edu/washington/cs/ubicomplab/rdt_reader/activities/ImageQualityActivity.java#L41

we'll probably want to set a rdt_config intent w/all the data and modify further code to handle this, eg image loading to convert a b64 to the image needed

this is where we set the intent in this code, https://github.com/onaio/rdt-standard/blob/f658d53f6f88398dccf3b2741963f6f086d986b6/rdt-open-reader/src/main/java/io/ona/rdt/widget/UWRDTCaptureFactory.java#L74

CC @shivenbhatt1 @vincent-karuri

vincent-karuri commented 3 years ago

https://github.com/onaio/Covid19/blob/master/scripts/device-definition/device_definitions-rdt-og-2020-09-18.json#L166 fhir resource definition.

vincent-karuri commented 3 years ago
InputStream resourceMessage = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
InputStream stream = new ByteArrayInputStream(resourceMessage.getResource().getBytes(StandardCharsets.UTF_8));
DeviceDefinition domainResource = FHIRParser.parser(Format.JSON).parse(stream);

Instantiate a device definition.

vincent-karuri commented 3 years ago

@pld, @githengi says there's an issue with the fhir resource https://github.com/onaio/rdt-standard/issues/283#issuecomment-700694772, maybe he can explain better.

githengi commented 3 years ago

@pld Json Array is not valid FHIR resource and will cause problems in evaluation. I suggest to use a fhir bundle of type collection

githengi commented 3 years ago

Also the contents seems not be valid, I was not able to parse as bundle or the individual device definitions. I will correct and share a valid JSON

pld commented 3 years ago

Yes that's correct it's not valid fhir, we added the parameters for rdtscan verbatim from their config

Vinny, I believe this is what you suggested

On Sep 30, 2020, at 04:04, Samuel Githengi notifications@github.com wrote:

 Also the contents seems not be valid, I was not able to parse as bundle or the individual device definitions. I will correct and share a valid JSON

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub, or unsubscribe.

vincent-karuri commented 3 years ago

yea that was the idea but I don't know how to encode that as fhir and still maintain its structure. I assumed it'd be valid.

pld commented 3 years ago

K, Sam G if you have a reasonable way to encode this as FHIR let us know, we can incorporate it into the code that’s generate the resources

On Sep 30, 2020, at 8:29 AM, vincent-karuri notifications@github.com wrote:

yea that was the idea but I don't know how to encode that as fhir and still maintain its structure. I assumed it'd be valid.

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/onaio/rdt-standard/issues/283#issuecomment-701358381, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAAMMEUCH6ZGLOVNY7UZU53SIMQBLANCNFSM4M7AWHYQ.

vincent-karuri commented 3 years ago

I see this as having three components:

  1. Format Device Definitions into a valid FHIR resource (requires FHIR domain knowledge)
  2. Write FHIR Path queries to extract information from the resource in 1 (requires FHIR domain knowledge) and possibly convert this information into Java POJOs
  3. Modify RDTScan to accept RDT configurations and template images as Java POJOs for better configurability (requires some knowledge on how RDTScan handles configurations)

I'll refine this as I go but the point here is I don't see how to split this up to greatly speed up delivery of this feature. 3 is closest to what could be done separately from FHIR stuff but a developer would still require some context to make things easier when navigating the RDTScan library.

pld commented 3 years ago

I agree w/your assessment, (3) can be done independently, let's gather context for that in a separate issue.

(2) is dependent on (1), IMO having access to a validator and being able to understand the FHIR resources is enough domain knowledge, at least Craig and I can do the later

vincent-karuri commented 3 years ago
{
  "resourceType": "Bundle",
  "identifier": {
    "value": "rdtdevice-defintions"
  },
  "type": "collection",
  "entry": [
    {
      "resource": {
        "resourceType": "DeviceDefinition",
        "identifier": [
          {
            "value": "d3fdac0e-061e-b068-2bed-5a95e803636f"
          }
        ],
        "udiDeviceIdentifier": [
          {
            "deviceIdentifier": "row['Product Code']",
            "issuer": "urn:manufacturer",
            "jurisdiction": "urn:global"
          }
        ],
        "manufacturerString": "Guangzhou Wondfo Biotech",
        "deviceName": [
          {
            "name": "Wondfo SARS-CoV-2 Antibody Test",
            "type": "user-friendly-name"
          }
        ],
        "type": {
          "coding": [
            {
              "system": "http://hl7.org/fhir/ValueSet/device-kind",
              "code": "87717000",
              "display": "Tester"
            }
          ],
          "text": "Diagnostic Test Device"
        },
        "version": [
          "0.1"
        ],
        "capability": [
          {
            "type": {
              "text": "instructions"
            },
            "description": [
              {
                "text": "Collect blood sample"
              }
            ]
          },
          {
            "type": {
              "text": "lines"
            },
            "description": [
              {
                "coding": [
                  {
                    "code": "C"
                  }
                ],
                "text": "Control"
              },
              {
                "coding": [
                  {
                    "code": "T"
                  }
                ],
                "text": "Test"
              },
              {
                "coding": [
                  {
                    "code": "G+M"
                  }
                ],
                "text": "IgG / IgM"
              }
            ]
          },
          {
            "type": {
              "text": "sample types"
            },
            "description": [
              {
                "text": "Whole Blood"
              },
              {
                "text": "Serum"
              },
              {
                "text": "Plasma"
              }
            ]
          }
        ],
        "property": [
          {
            "type": {
              "text": "Time For Result"
            },
            "valueQuantity": [
              {
                "value": 15,
                "comparator": ">=",
                "unit": "minutes"
              },
              {
                "value": 20,
                "comparator": "<=",
                "unit": "minutes"
              }
            ]
          },
          {
            "type": {
              "text": "Temperature"
            },
            "valueQuantity": [
              {
                "value": 2,
                "comparator": ">=",
                "unit": "degrees celsius"
              },
              {
                "value": 30,
                "comparator": "<=",
                "unit": "degrees celsius"
              }
            ]
          },
          {
            "type": {
              "text": "Sample Quantity"
            },
            "valueQuantity": [
              {
                "value": 1,
                "unit": "drop"
              },
              {
                "value": 10,
                "unit": "microliter"
              }
            ]
          },
          {
            "type": {
              "text": "Buffer Quantity"
            },
            "valueQuantity": [
              {
                "value": 2,
                "comparator": ">=",
                "unit": "drop"
              },
              {
                "value": 3,
                "comparator": "<=",
                "unit": "drop"
              },
              {
                "value": 80,
                "unit": "microliter"
              }
            ]
          },
          {
            "type": {
              "text": "RDTScan Configuration"
            },
            "valueCode": [
              {
                "coding": [
                  {
                    "code": "REF_IMG"
                  }
                ],
                "text": "/9j/4AAQSkZJRgABAQAASABIAAD/4QE0RXhpZgAATU0AKgAAAAgABgESAAMAAAABAAEAAAEaAAUAAAABAAAAVgEbAAUAAAABAAAAXgEoAAMAAAABAAIAAAEyAAIAAAAUAAAAZodpAAQAAAABAAAAegAAAAAAAABIAAAAAQAAAEgAAAABMjAyMDowMzozMSAxNzo0ODowNAAAC5AAAAcAAAAEMDIyMZADAAIAAAAUAAABBJAEAAIAAAAUAAABGJEBAAcAAAAEAQIDAJKRAAIAAAAEMTQzAJKSAAIAAAAEMTQzAKAAAAcAAAAEMDEwMKABAAMAAAABAAEAAKACAAQAAAABAAADAqADAAQAAAABAAAAlqQGAAMAAAABAAAAAAAAAAAyMDIwOjAzOjMxIDE3OjQ4OjA0ADIwMjA6MDM6MzEgMTc6NDg6MDQA/+EJ/Wh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNS40LjAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnBob3Rvc2hvcD0iaHR0cDovL25zLmFkb2JlLmNvbS9waG90b3Nob3AvMS4wLyIgeG1wOkNyZWF0ZURhdGU9IjIwMjAtMDMtMzFUMTc6NDg6MDQuMTQzIiB4bXA6TW9kaWZ5RGF0ZT0iMjAyMC0wMy0zMVQxNzo0ODowNCIgcGhvdG9zaG9wOkRhdGVDcmVhdGVkPSIyMDIwLTAzLTMxVDE3OjQ4OjA0LjE0MyIvPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAg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"
              },
              {
                "coding": [
                  {
                    "code": "VIEW_FINDER_SCALE"
                  }
                ],
                "text": "0.6"
              },
              {
                "coding": [
                  {
                    "code": "RESULT_WINDOW_TOP_LEFT"
                  }
                ],
                "text": "[350,67]"
              },
              {
                "coding": [
                  {
                    "code": "RESULT_WINDOW_BOTTOM_RIGHT"
                  }
                ],
                "text": "[420,77]"
              },
              {
                "coding": [
                  {
                    "code": "TOP_LINE_POSITION"
                  }
                ],
                "text": "[ 370, 75]"
              },
              {
                "coding": [
                  {
                    "code": "MIDDLE_LINE_POSITION"
                  }
                ],
                "text": "[ 405, 75]"
              },
              {
                "coding": [
                  {
                    "code": "TOP_LINE_NAME"
                  }
                ],
                "text": "Control"
              },
              {
                "coding": [
                  {
                    "code": "MIDDLE_LINE_NAME"
                  }
                ],
                "text": "Test"
              },
              {
                "coding": [
                  {
                    "code": "LINE_INTENSITY"
                  }
                ],
                "text": "85"
              }
            ]
          }
        ]
      }
    }
  ]
}

valid bundle for the 1st device from @githengi.

vincent-karuri commented 3 years ago

From slack on changes made:

The changes are adding a bundle wrapper object
changing identifier of DD(device definition) to list of identifiers. Should have a value
For quantities they should be int, remove the quotes
For the concepts convert all to String i.e wrapped in ""
For valueCode convert all to valid codable concepts, havent used any code system
I have changed evaluateElementExpression in my local to accept Resource, you can make a PR to amend it
vincent-karuri commented 3 years ago
InputStream stream = new ByteArrayInputStream(json.getBytes(StandardCharsets.UTF_8));
        Bundle domainResource = FHIRParser.parser(Format.JSON).parse(stream);
        assertEquals("Collect blood sample",
            pathEvaluatorLibrary
                    .evaluateElementExpression(domainResource,
                        "$this.where(entry.resource.capability.type.where(text='instructions')).entry.resource.capability.description.text")
                    .getValue().asStringValue().string());

validation in a unit test.

vincent-karuri commented 3 years ago

https://www.hl7.org/fhir/binary.html binary resource, might be useful for the images?

pld commented 3 years ago

@vincent-karuri we have a new JSON generated and validated with a python FHIR library, https://github.com/onaio/Covid19/blob/master/scripts/device-definition/device_definitions-rdt-og-2020-10-07.json

added the bundle as well, code for this should be readable, each DeviceDefinition resource is created as JSON then encoded as FHIR and validated, then converted back to JSON and added to a Bundle resource and encoded as FHIR and validated again, then converted as JSON a final time and written to file, https://github.com/onaio/Covid19/blob/master/scripts/device-definition/device-definition.ipynb

Let me know if you have any problems parsing the JSON

vincent-karuri commented 3 years ago

Nice! Thanks!

vincent-karuri commented 3 years ago

Is Alltest 2019-nCoV IgG/IgM a duplicate RDT definition?

pld commented 3 years ago

not sure the 2 have different sample quantities so I don't think so, but the JSON will definitely change there are others in the source sheet that don't have RDT params yet that we'll need to add, so doesn't seem particularly important the content is accurate right now as long as the format is