fhir.resources icon indicating copy to clipboard operation
fhir.resources copied to clipboard

How to discover the element type?

Open Healthedata1 opened this issue 3 years ago • 7 comments

  • fhir.resources version: current
  • Python version: 3.7
  • Operating System: Mac

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?

Healthedata1 avatar Jul 01 '21 20:07 Healthedata1

We should have a class method available.

      >>> from fhir.resources.observation import Observation
 
      >>> Observation.get_resource_type()

nazrulworld avatar Jul 01 '21 20:07 nazrulworld

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'

Healthedata1 avatar Jul 01 '21 21:07 Healthedata1

@Healthedata1 that is something not possible, unfortunately.

nazrulworld avatar Jul 02 '21 06:07 nazrulworld

here is what I did:

element_type = next(i.type_.__resource_type__ for i in resource.element_properties() if i.name == element)

Healthedata1 avatar Jul 06 '21 16:07 Healthedata1

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.

theGOTOguy avatar Oct 13 '21 06:10 theGOTOguy

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.

ArdonToonstra avatar Jul 15 '22 09:07 ArdonToonstra

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.

vadi2 avatar Mar 10 '24 13:03 vadi2