nazrulworld / fhir.resources

FHIR Resources https://www.hl7.org/fhir/resourcelist.html
https://pypi.org/project/fhir.resources/
Other
372 stars 104 forks source link

How to discover the element type? #77

Open Healthedata1 opened 3 years ago

Healthedata1 commented 3 years ago

Description

Describe what you were trying to get done.

I am trying to discover the simplest and most direct way to discover the type for an element:

ideally this :

      1 from fhir.resources.observation import Observation
      2 
----> 3 Observation.resource_type

AttributeError: type object 'Observation' has no attribute 'resource_type'

obviously this isn't going to work on this instance but don't know the best way to do this on the class

What I Did


obs_obj = Observation.parse_file("Observation_wt.yml")
for i in obs_obj.element_properties():
    try:
        print(f'i.name={i.name}, itype = {i.type_.__resource_type__}')
    except:
        print(f'i.name={i.name}')

i.name=id
i.name=implicitRules
i.name=language
i.name=meta, itype = Meta
i.name=contained, itype = Resource
i.name=extension, itype = Extension
i.name=modifierExtension, itype = Extension
i.name=text, itype = Narrative
i.name=basedOn, itype = Reference
i.name=bodySite, itype = CodeableConcept
i.name=category, itype = CodeableConcept
i.name=code, itype = CodeableConcept
i.name=component, itype = ObservationComponent
i.name=dataAbsentReason, itype = CodeableConcept
i.name=derivedFrom, itype = Reference
i.name=device, itype = Reference
i.name=effectiveDateTime
i.name=effectiveInstant
i.name=effectivePeriod, itype = Period
i.name=effectiveTiming, itype = Timing
i.name=encounter, itype = Reference
i.name=focus, itype = Reference
i.name=hasMember, itype = Reference
i.name=identifier, itype = Identifier
i.name=interpretation, itype = CodeableConcept
i.name=issued
i.name=method, itype = CodeableConcept
i.name=note, itype = Annotation
i.name=partOf, itype = Reference
i.name=performer, itype = Reference
i.name=referenceRange, itype = ObservationReferenceRange
i.name=specimen, itype = Reference
i.name=status
i.name=subject, itype = Reference
i.name=valueBoolean
i.name=valueCodeableConcept, itype = CodeableConcept
i.name=valueDateTime
i.name=valueInteger
i.name=valuePeriod, itype = Period
i.name=valueQuantity, itype = Quantity
i.name=valueRange, itype = Range
i.name=valueRatio, itype = Ratio
i.name=valueSampledData, itype = SampledData
i.name=valueString
i.name=valueTime
```

Is there an easier way?
nazrulworld commented 3 years ago

We should have a class method available.

      >>> from fhir.resources.observation import Observation

      >>> Observation.get_resource_type()
Healthedata1 commented 3 years ago

Thanks but it does not work for the elements...

      1 from fhir.resources.observation import Observation
----> 2 Observation.code.get_resource_type

AttributeError: type object 'Observation' has no attribute 'code'
nazrulworld commented 3 years ago

@Healthedata1 that is something not possible, unfortunately.

Healthedata1 commented 3 years ago

here is what I did:

element_type = next(i.type_.__resource_type__ for i in resource.element_properties() if i.name == element)
theGOTOguy commented 2 years ago

For my application, I wished to search a FHIR resource for objects of type Coding, and return the list of all Coding relevant to the resource.

For any who follow, I used a different approach:

from fhir.resources.coding import Coding

def reflect_get_coding(fhir):
  response_objects = []

  if not isinstance(fhir, str):
    if isinstance(fhir, Coding):
      response_objects.append(fhir)
    elif isinstance(fhir, Iterable):
      for item in fhir:
        response_objects.extend(reflect_get_coding(item))
    elif hasattr(fhir, '__dict__'):
      for prop, value in vars(fhir).items():
        if not prop.startswith("_"):
          response_objects.extend(reflect_get_coding(value))

  return response_objects

It would be awesome if there were a clearer story for using reflection in nested fhir.resources objects.

ArdonToonstra commented 2 years ago

Hi @theGOTOguy , thanks! That helped me a lot. I use it to translate Coding.displays in all my resources examples. :) And +1 for having something that is clearer to filter on element types.

vadi2 commented 6 months ago

I had a hard time finding if an element is a List - in case anyone else runs into it, this works:

from typing import get_origin

get_origin(parent.__fields__[element_name].annotation) is list

Suggestions for improvement welcome.