Page tree

2286 View 5 Comment In discussion Comments enabled In the category: Undefined

About how to specify the extent of the scope when instantiating slot variables

Contributors (4)

5 Comments

  1. First, I think that most authoring use cases will be pretty simple compared to the FHIR transformation use case we've been discussing earlier. In the observables work, since observables are not relationship grouped, the scope is always the attribute-value pair. For "relationship grouped" hierarchies like Findings and Procedures there will also be relationship group scope, meaning that multiple values might imply multiple relationship groups, not only multiple attribute-value pairs.

    There are 3 400 active concepts with more than one occurrence of multiple stated relationships of the same type in the same relationship group (or 25 000 when counting inferred relationships). 187081003 | Subcutaneous pheohyphomycotic abscess and cyst (disorder) | holds the record with 8 stated 246075003 | Causative agent (attribute) | relationships. The vast majority of concepts have one occurrence stated per type per relationship group.

    Taking two simple examples of fractures and vaccines:

    FSNFinding_siteAssoc_morphology
    Fracture of ulna23416004 | Bone structure of ulna (body structure) |72704001 | Fracture (morphologic abnormality) |
    Closed fracture of ulna and radius23416004 | Bone structure of ulna (body structure) |, 62413002 | Bone structure of radius (body structure) |20946005 | Fracture, closed (morphologic abnormality) |
    ...  

    and the template (in two version, with scope types and with scope markers:

    64572001 | Disease (disorder) | :
    {
    363698007 | Finding site (attribute) | = [[ scope:RG [1..*] @Finding_site <<272673000 | Bone structure (body structure) | ]],
    116676008 | Associated morphology (attribute) | = [[ scope:RG [1..*] @Assoc_morphology <<72704001 | Fracture (morphologic abnormality) | ]]
    }

    64572001 | Disease (disorder) | :
    #< #<{
    363698007 | Finding site (attribute) | = [[ [1..*] @Finding_site <<272673000 | Bone structure (body structure) | ]],
    116676008 | Associated morphology (attribute) | = [[ [1..*] @Assoc_morphology <<72704001 | Fracture (morphologic abnormality) | ]]
    } #> #>

    scope:RG here means that the extent of instantiation is the immediately surrounding role group.

    The result is:

    Result
    64572001 | Disease (disorder) | :
    {
    363698007 | Finding site (attribute) | = 23416004 | Bone structure of ulna (body structure) |,
    116676008 | Associated morphology (attribute) | = 72704001 | Fracture (morphologic abnormality) |
    }
    64572001 | Disease (disorder) | :
    {
    363698007 | Finding site (attribute) | = 23416004 | Bone structure of ulna (body structure) |,
    116676008 | Associated morphology (attribute) | = 20946005 | Fracture, closed (morphologic abnormality) |
    } ,
    {
    363698007 | Finding site (attribute) | = 62413002 | Bone structure of radius (body structure) |,
    116676008 | Associated morphology (attribute) | = 20946005 | Fracture, closed (morphologic abnormality) |
    }

    Note that the cartesian product of the values are used to instatiate the relationship groups. Had there been two kinds of fracture in row 2 the result would have been 4 relationship groups. If there is a need to pair values, a template containing two relationship groups would have to be created.


    And for vaccines:

    FSNdose_formactive_ingredient
    Live measles + rubella vaccine injection dose form385218009 | Injection (qualifier value) |396427003 | Measles vaccine (substance) |, 396438003 | Rubella vaccine (substance) |
    Measles + mumps + rubella + varicella vaccine null396427003 | Measles vaccine (substance) |, 396438003 | Rubella vaccine (substance) |, 396431009 | Mumps vaccine (substance) |, 396442000 | Varicella virus vaccine (substance) |
    ...  

    and the templates:

    71181003 | Vaccine (product) | :
    {
    127489000 | Has active ingredient (attribute) | = [[ scope:AVP [1..*] @active_ingredient <<398827000 | Vaccine (substance) | ]],
    411116001 | Has dose form (attribute) | = [[ scope:AVP [0..1] @dose_form <<105904009 | Type of drug preparation (qualifier value) | ]]
    }

    71181003 | Vaccine (product) | :
    {
    #< 127489000 | Has active ingredient (attribute) | = [[ [1..*] @active_ingredient <<398827000 | Vaccine (substance) | ]] #>,
    #< 411116001 | Has dose form (attribute) | = [[ [0..1] @dose_form <<105904009 | Type of drug preparation (qualifier value) | ]] #>
    }

    scope:AVP means that the extent of instantiation is the attribute-value pair containing the slot.

    Result

    71181003 | Vaccine (product) | :
    {
    127489000 | Has active ingredient (attribute) | = 396427003 | Measles vaccine (substance) |,
    127489000 | Has active ingredient (attribute) | = 396438003 | Rubella vaccine (substance) |,

    411116001 | Has dose form (attribute) | = 385218009 | Injection (qualifier value) |
    }

    71181003 | Vaccine (product) | :
    {
    127489000 | Has active ingredient (attribute) | = 396427003 | Measles vaccine (substance) |,
    127489000 | Has active ingredient (attribute) | = 396438003 | Rubella vaccine (substance) |,
    127489000 | Has active ingredient (attribute) | = 396431009 | Mumps vaccine (substance) |,
    127489000 | Has active ingredient (attribute) | = 396442000 | Varicella virus vaccine (substance) |

    }

    Relationship group scope and attribute-value pair scope may also be combined, and then all AVP scoped slots are instatiated in each relationship group.

  2. Some additional comments:

    I assume that not meeting the cardinality constraints would throw an error, e.g. not having an active ingredient in the vaccines template would be an error.

    I have not seen, and cannot think of, a case where cardinality constraints are made cross relationship groups.

    Slots with non-grouped attributes cannot have a relationship group scope.

    When authoring, a template should be able to have slot for equivalentClass/subClassOf. Also, how is the definiendum specified?

    ( [[ scope:CONCEPT [1..1] @definiendum ]] )
    === /* should this be "templatable" */
    ( 71181003 | Vaccine (product) | :
    {
    127489000 | Has active ingredient (attribute) | = [[ scope:AVP [1..*] @active_ingredient <<398827000 | Vaccine (substance) | ]],
    411116001 | Has dose form (attribute) | = [[ scope:AVP [0..1] @dose_form <<105904009 | Type of drug preparation (qualifier value) | ]]
    } )

  3. Thanks for the great examples Daniel! These are really helpful.

    I think it's really useful to explore the requirement for defining the scope of a slot, and what this means for authoring. However, let's first explore cardinality and how far we can get with this ... and then identify if/where the gaps in expressivity are that need to be filled with a new feature.

    For example, what if we defined your first example template (note the new syntax) as:

    64572001 |Disease (disorder)|  : [[~1..*]] { 
       [[~1..1]] 
    363698007 |Finding site (attribute)|  = 
             [[+id(<<
    272673000 |Bone structure (body structure)| ) @Finding_site]],
       [[~1..1]] 
    116676008 |Associated morphology (attribute)|  = 
             [[+id(<<
    72704001 |Fracture (morphologic abnormality)| ) @Assoc_morphology]] }
    This allows only exactly 1 finding site and exactly 1 associated morphology per group, but allows there to be more than 1 relationship group. In the 53627009 |Closed fracture of ulna and radius|  example, repeating the @Finding_site and @Assoc_morphology slots in the same relationship group would not be valid according to the template's cardinality constraints - so once these slots get filled up, a second relationship group must be created to ensure the expression conforms to the template.

    If we were to define your second example template as:

    71181003 |Vaccine (product)|  : [[~1..1]] {
       [[~1..*]] 
    127489000 |Has active ingredient (attribute)|  = 
             [[+id(<<
    398827000 |Vaccine (substance)| ) @active_ingredient]],
       [[~1..1]] 
    411116001 |Has dose form (attribute)|  = 
             [[+id(<<
    105904009 |Type of drug preparation (qualifier value)| ) @dose_form]]}
    This could be used to represent a single-or-multi-ingredient, single-component (i.e. one dose form) medication concept. The cardinality shows that if you want to add multiple ingredients, they need to go inside the same relationship group.

    If, however, we want to represent a multi-component medication concept (e.g. a solution with active ingredient W + X and powder with active ingredient Y + Z), then we would need to allow the relationship group to be repeated like:

    71181003 |Vaccine (product)|  : [[~1..*]] {
       [[~1..*]] 
    127489000 |Has active ingredient (attribute)|  = 
             [[+id(<<
    398827000 |Vaccine (substance)| ) @active_ingredient]],
       [[~1..1]] 
    411116001 |Has dose form (attribute)|  = 
             [[+id(<<
    105904009 |Type of drug preparation (qualifier value)| ) @dose_form]]}
    There is still only 1 dose form allowed per relationship group, but you can have more than one relationship group, each with a different dose form. This example shows that there is no clear 'scope' for the @active_ingredient slot. If we populate it with substances W, X, Y, and Z, we can't avoid specifying (in the input), which active ingredients get put in the first relationship group (with the 'Solution' dose form) and which active ingredients get put in the second relationship group (with the 'Powder' dose form). If we name the relationship group (e.g. @component), then the input can define the active_ingredient and dose_form values to use for @component[1] (i.e. W, X, 'Solution') and @component[2] (i.e. Y, Z, 'Powder'). But I'm not sure how you would do this inside the template. Thoughts?

    With respect to your other questions:

    • Not meeting a cardinality constraint would definitely be 'invalid' (ie the expresion would not be a valid instantiation of the template). How this was handled, however, (in terms of throwing errors) would probably be an implementation decision.
    • We could potentially support a slot for the definitionStatus (i.e. '===' or '<<<') if needed. At the moment, in a 'replace slot' we are using the syntax "[[+id]]" for a slot that is replaced by a single SNOMED CT identifier, "[[+scg]]" for a slot that can be replaced by any SNOMED CT CG expression, and "[[+ecl]]" for a slot that can be replaced by an expression constraint. We could, for example, use "[[+def]]" for definition status. This also relates to another comment made regarding concrete values. Concrete values may become even more important when we define templates for the full Query Language - however they are still important for extentions that use concrete values to define (for example) their drug models. We may therefore want to consider "[[+int]]", "[[+dec]]" and "[[+str]]" (for slots that can be replaced with an integer, decimal and string concrete values respectively). Any thoughts on this? 
    • The "definiendum" (admittedly a word for which I needed to consult the dictionary) can be defined on the left side of the definition status (as suggested in Appendix A of the Compositional Grammar specification), and a slot may be used if required.

    By the way, I have developed a first-cut of a draft ABNF syntax for the Expression Template Language (which combines Compositional Grammar, the Expression Constraint Language and the current-proposal for the Template Syntax). If you would like to take a look, please let me know.

    Thanks again!

    Kind regards,
    Linda. 

     

    1. Firstly, definiendum, a word that I have now added to my lexicon and will undoubtedly make use of - in fact I don't know how I have gotten this far without it.

      Example 3 here is the general case I've been concerned about.  Linda Bird, when you say "the input can define the active_ingredient and dose_form values to use for @component", can you explain how this would happen in more detail?  For example, how does a template engine know how to interpret a tuple like <W, X, 'Solution'>? That is, how does it know that X and X map to @active_ingredient and 'Solution' maps to @dose_form?

      Michael

      1. Definiendum is the definiendum of the definition of definiendum.