Page tree

Date & Time

20:00 UTC Wednesday 13th March 2019

Teleconference Details

To join the meeting please go to

Further information can be found at SLPG meeting information


  • Review actions from last meeting
  • Proposed enhancements to template language
  • Proposed new language features for mapping



Agenda and Meeting Notes


Welcome and apologies

Actions from last week
  • Actions from last week:
    • Consider new syntax to support proposed expression template use case
    • Consider new syntax to support proposed map use case
Template SyntaxLinda Bird

Use cases: New concept development, querying based on template matching, and template-based modeling transformation

New requirements

  1. Constrain values across 2 or more replacement slots
    • 2 replacement slots must have the same value, different values, subsumed values, or not subsumed values.
    • Example A - A clinical finding, with 2 role groups with the same morphology, and finding sites that not subsume each other
      • Template

        • [[ +id ]]:
          { 116676008 |Associated morphology| = [[ +id @morphology ]],
          363698007 |finding site| = [[ +id (<< |Body structurel MINUS << $findingSite2 ) @findingSite1 ]] },
                  { 116676008 |Associated morphology| = [[ +id @morphology ]],
          363698007 |finding site| = [[ +id (* MINUS << $findingSite1) @findingSite2 ]] }

      • Valid Expression (Definition of 16027391000119109 |Bone cyst of bilateral tibias (disorder)|)
        • 64572001 |Disease| :
                      { 116676008 |Associated morphology| = 66954000 |Bone cyst|,
                        363698007 |Finding site| = 719491009 |Bone structure of right tibia| }
                      { 116676008 |Associated morphology| = 66954000 |Bone cyst|,
                        363698007 |Finding site| = 719492002 |Bone structure of left tibia| }
    • Example B - A clinical finding, with one or more role groups in which the morphology is always the same, and no 2 finding sites subsume each other.
      • Template - 3 role groups with 3 sites: site[1], site[2], site [3] /// site [1,2]
        •  [[+id]]:
          [[1..*] @group1] { |Finding site| = [[ +id (* MINUS $site[! SELF ] ) @site constraint ( [n] != << $site [!n] ]] ,
          |Associated morphology| = [[ +id ($morphology [! SELF] ) @morphology constraint ( [n] = $morphology [!n] ]] }
      • Valid Expression (Definition of 208510002 |Multiple fracture of clavicle, scapula and humerus (disorder)| )
          • 64572001 |Disease| :
                        { 363698007 |Finding site| = 85050009 |Bone structure of humerus|,
                          116676008 |Associated morphology| = 5468008 |Fracture of multiple sites of bone| }
                        { 363698007 |Finding site| = 51299004 |Bone structure of clavicle|,
                          116676008 |Associated morphology| = 5468008 |Fracture of multiple sites of bone| }
                        { 363698007 |Finding site| = 79601000 |Bone structure of scapula|,
                          116676008 |Associated morphology| = 5468008 |Fracture of multiple sites of bone| }
                        { 363698007 |Finding site| = 773134001 |Bone structure of multiple body regions|,
                          116676008 |Associated morphology| = 771485007 |Fracture of multiple bones| }
  2. Default value for replacement slot
    • Default value for authoring and template-driven modelling transformations
    • Example A - Default finding site of 72673000 |Bone structure|
      • Template
        • [[ + id ]] :
          { |Finding site| = [[ +id (<< 72673000|Bone structure|) @site default (72673000 |Bone structure (body structure)|) ]]
  3. Definition status of a replacement slot
    • Specifying whether the value used in a replacement slot must be primitive or defined
    • Example A - When proximal primitive modelling, the focus concept must be a primitive concept
      • Template - Requires use of more expressive query language with filters
        • [[ + id (<< 64572001 |Disease| {{ c.definitionStatus = primitive }}) ]]
      • Valid Expression
        • 195967001 |Asthma (disorder)|
  4. Definition status of a templated expression
    • Specifying the definition status of a templated expression
    • Template
      • [[ +tok ("===" "<<<") ]] [[ +id ]] : { |Finding site| = [[+id]] }
      • Valid Expression
        • === 128272009 |Disorder of lower respiratory system| : 363698007 |Finding site| = 39607008 |Lung structure|
        • <<< 128272009 |Disorder of lower respiratory system| : 363698007 |Finding site| = 39607008 |Lung structure|
  5. Attributes used in repeating role groups
    • Constraining the set of attributes that appear in a repeating role group
    • Example A - The same set of attributes must appear in each instance of a repeating role group (with optional attributes)
      • Template - using allOrNone
        • [[+id]]: [[1..* @group1 allOrNone ($site, $occurrence)]]
          { [[1..1]] |Associated morphology| = [[ +id @morphology ]],
          [[0..1 ]] |Finding site| = [[ +id @site]],
          [[0..1 ]] |Occurrence| = [[ +id @occurrence ]] }
        • Valid Expression - Injury of head, neck and chest
          • [[ |Disease| ]]: 
            { |Associated morphology| = |Injury|, |Finding site| = |Head structure| } 
            { |Associated morphology| = |Injury|,  |Finding site| = |Neck structure| }
            { |Associated morphology| = |Injury|,  |Finding site| = |Chest structure| }
        • Valid Expression - Congenital malformation of head and neck 
          • [[ |Disease| ]]: 
            { |Associated morphology| = |malformation|, |Finding site| = |Head structure|, |Occurrence| = |Gongenital| } 
            { |Associated morphology| = |malformation|,  |Finding site| = |Neck structure|, |Occurrence| = |Gongenital| }
    • Example B - Some of the optional attributes must either always or never appear in each instance of a repeating role groupTemplate - using "allOrNone"
        • [[+id]]: [[1..* @group1 allOrNone($morph) ]]
          { [[ 1..1 ]] |Method| = [[+id]],
          [[ 0..1 ]] |Direct morphology| = [[+id @morph]],
          [[ 0..1 ]] |Procedure site - Direct| = [[+id]],
          [[ 0..1]] |Using device| = [[+id]] ,
          [[ 0..1]] |Has intent| = [[+id]] ,
        • Valid Expression - Closure of skin by suture
          • |Procedure|: 
            { |Method| = |Closure - action|, |Procedure site - Direct| = |Skin structure| , |Using device| = |Surgical suture, device|} 
        • Valid Expression - Core needle biopsy of skin using ultasonographic guidance
          • |Procedure|: 
            { |Method| = |Ultrasound imaging - action|, |Procedure site - Direct| = |Skin structure| , |Has intent| = |Guidance intent|} 
            { |Method| = |Biopsy - action|, |Procedure site - Direct| = |Skin structure| , |Using device| = |Core biopsy needle, device|} 
        • Valid Expression - Toilet and suture of wound
          • |Procedure|: 
            { |Method| = |Surgical toilet - action|, |Direct morphology| = |Wound| } 
            { |Method| = |Closure - action|,  |Direct morphology| = |Wound|,
            |Procedure site - Direct| = |Skin structure|, |Using device| = |Surgical suture, device| }
Executing maps

Proposed extension to ECL to support the execution of maps

  • Example use cases
    • Mapping from international substance concepts to AMT substance concepts
    • Anatomy structure and part association reference set - e.g. find the anatomical parts of a given structure
  • Potential syntax to consider
    • Functional
      • mapTarget (|Anatomy structure and part association refset|, << |Upper abdomen structure|)
      • mapSource (|Anatomy structure and part association refset|, << |Liver part|)
    • Dot notation
      • ( |Anatomy structure and part association refset|: |ReferencedComponent| = << |Upper abdomen structure ) . |mapTarget|
      • ( |Anatomy structure and part association refset|: |mapTarget| = << |Upper abdomen structure ) . |referencedComponent|
    • Filters
      • ( |Anatomy structure and part association refset| {{ |referencedComponent| = << |Upper abdomen structure| }} ). |mapTarget|
      • ( |Anatomy structure and part association refset| {{ mapTarget = << |Upper abdomen structure| }} ) . |referencedComponent|
        • ^ ( |Anatomy structure and part association refset| {{ mapTarget = << |Upper abdomen structure| }} )
Returning attributesMichael Lawley

Proposal from Michael:

  • Currently ECL expressions can match (return) concepts that are either the source or the target of a relationship triple (target is accessed via the 'reverse' notation or 'dot notation', but not the relationship type (ie attribute name) itself. 

For example, I can write: 

<< 404684003|Clinical finding| : 363698007|Finding site| = <<66019005|Limb structure| 

<< 404684003|Clinical finding| . 363698007|Finding site| 

But I can't get all the attribute names that are used by << 404684003|Clinical finding| 

    • Perhaps something like:
      • ?? R.type ?? (<< 404684003 |Clinical finding|)
    • This could be extended to, for example, return different values - e.g.
      • ?? |Simple map refset|.|maptarget| ?? (^|Simple map refset| AND < |Fracture|)
URI Standard
  • Finalize and publish language and language instance URIs
Query Language
- Summary from previous meetings

Examples: version and language


    • Allow nested where, version, language
    • Scope of variables is inner query

Examples: where


      • Allow nested variable definitions, but recommend that people don't due to readability
      • Scope of variables is the inner query
      • No recursion e.g X WHERE X = 1234 MINUS X
        • ie can't use a variable in its own definition
        • ie X is only known on the left of the corresponding WHERE, and not on the right of the WHERE

Keywords for Term-based searching:

  • D.term
    • D.term = "*heart*"
    • D.term = wild:"*heart*"
    • D.term = regex:".*heart.*"
    • D.term = match:"hear att"
    • D.term = (sv) wild: "*heart*"
  • D.languageCode
    • D.languageCode = "en"
    • D.languageCode = "es"
  • D.caseSignificanceId
    • D.caseSignificanceId = 900000000000448009 |entire term case insensitive|
    • D.caseSignificanceId = 900000000000017005 |entire term case sensitive|
    • D.caseSignificanceId = 900000000000020002 |only initial character case insensitive|
  • D.caseSignificance
    • D.caseSignificance = "insensitive"
    • D.caseSignificance = "sensitive"
    • D.caseSignificance = "initialCharInsensitive"
  • D.typeId
    • D.typeId = 900000000000003001 |fully specified name|
    • D.typeId = 900000000000013009 |synonym|
    • D.typeId = 900000000000550004 |definition|
  • D.type
    • D.type = "FSN"
    • D.type = "fullySpecifiedName"
    • D.type = "synonym"
    • D.type = "textDefinition"
  • D.acceptabilityId
    • D.acceptabilityId = 900000000000549004 |acceptable|
    • D.acceptabilityId = 900000000000548007 |preferred|
  • D.acceptability
    • D.acceptability = "acceptable"
    • D.acceptability = "preferred"

Additional Syntactic Sugar

  • FSN
    • FSN = "*heart"
      • D.term = "*heart", D.type = "FSN"
      • D.term = "*heart", D.typeId = 900000000000003001 |fully specified name|
    • FSN = "*heart" LANGUAGE X
      • D.term = "*heart", D.type = "FSN", D.acceptability = * LANGUAGE X
      • D.term = "*heart", D.typeId = 900000000000003001 |fully specified name|, acceptabilityId = * LANGUAGE X
  • synonym
    • synonym = "*heart"
      • D.term = "*heart", D.type = "synonym"
      • D.term = "*heart", D.typeId = 900000000000013009 |synonym|
    • synonym = "*heart" LANGUAGE X
      • D.term = "*heart", D.type = "synonym", D.acceptability = * LANGUAGE X
      • D.term = "*heart", D.typeId = 900000000000013009 |synonym|, (D.acceptabilityId = 900000000000549004 |acceptable| OR D.acceptabilityId = 900000000000548007 |preferred|) LANGUAGE X
  • synonymOrFSN
    • synonymOrFSN = "*heart"
      • synonym = "*heart" OR FSN = "*heart"
      • D.term = "*heart", (D.type = "synonym" OR D.type = "fullySpecifiedName")
    • synonymOrFSN = "*heart" LANGUAGE X
      • synonym = "*heart" OR FSN = "*heart" LANGUAGE X
      • D.term = "*heart", (D.type = "synonym" OR D.type = "fullySpecifiedName"), D.acceptability = * LANGUAGE X
  • textDefinition
    • textDefinition = "*heart"
      • D.term = "*heart", D.type = "definition"
      • D.term = "*heart", D.typeId = 900000000000550004 |definition|
    • textDefinition = "*heart" LANGUAGE X
      • D.term = "*heart", D.type = "definition", D.acceptability = * LANGUAGE X
      • D.term = "*heart", D.typeId = 900000000000550004 |definition|, D.acceptabilityId = * LANGUAGE X
  • Unacceptable Terms
    • (D.term = "*heart") MINUS (D.term = "*heart", D.acceptability = * LANGUAGE X)

Language preferences using multiple language reference sets

  • LRSs that use the same Language tend to use 'Addition' - i.e. child LRS only includes additional acceptable terms, but can override the preferred term

    • E.g. Regional LRS that adds local dialect to a National LRS

    • E.g. Specialty-specific LRS

    • E.g. Irish LRS that adds local preferences to the en-GB LRS

      • 99999900 |Irish language reference set| PLUS |GB English reference set|

  • LRSs that define a translation to a different language tend to use 'Replacement' - i.e. child LRS replaces set of acceptable and preferred terms for any associated concept

    • E.g. Danish LRS that does a partial translation of the International Release

      • 999999 |Danish language reference set| ELSE |GB English reference set|

Other topics
  • Any other topics?
Confirm next meeting date/time

The next SLPG meeting will be held in 2 weeks at 20:00 UTC on Wednesday 27th March.

  File Modified
Microsoft Word 97 Document 1997 Rogers - (MIE) Rubrics to Dissections.doc 2019-Mar-26 by Ed Cheetham
Microsoft Powerpoint 97 Slideshow 2000 Rogers (AMIA) - Intermediate Representation.ppt 2019-Mar-26 by Ed Cheetham

  • No labels


  1. Following on from the call discussion regarding the ambitions and use cases of the template language..

    I confess that I had missed the refocusing in emphasis of the template syntax. Looking back over the minutes of 2016 calls considerable effort was expended trying to meet the FHIR extraction/population use cases. What happened to this work? Is the 2017 STS material capable of meeting the original FHIR requirements, or (as seemed to be said on the call) was this deemed too hard?

    Returning then to the 'authoring of pre-coordinated content' use case, I again want to ask what is the expectation regarding the capabilities of the template syntax? I'm strongly in favour of automating as many rules as possible, but am not convinced that the declarative 'paradigm' of the template syntax is the right place to do anything more than - well - 'template' stuff (useful, but basically rigid guides that say 'put this sort of thing here, and get it from over there'). If the desire is to do more sophisticated things than this (notably condition testing and flow control) then I'd prefer it if there was a really clear debate now as to how this will be achieved before the STS is extended.

    Looking within the current 'specific disorder modelling' guidance, and picking out a few clauses that reference 'occurrence' (because that's close to an example already under discussion) we have:

    • "...Disorders with the word congenital in their FSNs should be classified under 66091009 |Congenital disease (disorder)|.
    • Do not make a direct stated assertion that the parent is 66091009 |Congenital disease (disorder)|; instead allow the classifier to infer this relationship.
    • Occurrence should be in the same relationship group as Associated morphology and Finding site because the morphology is located at the site and the occurrence applies to the combined morphology-site pair.
    • ...
    • Congenital disorders are modeled using Occurrence = 255399007 | Congenital (qualifier value) |. If the FSN does not include congenital, it should not be modeled as congenital. The precise meaning of the FSN should be followed (e.g. many hereditary disorders have congenital appearances).
    • ...
    • All concepts that explicitly state acquired in their FSNs or in a synonym should be modeled with Occurrence = 767023003 | Period of life beginning after birth and ending before death (qualifier value) |; that is if an Occurrence relationship does not already exist, i.e. there is not already another period of life that is a value for Occurrence, which would infer the parent..."

    At the moment the discussion has focused on the third one (plus its unstated allOrNone enhancement), but it seems to me that there are many more aspects of these 'rules' which could be automated. If there is wider appetite to do so, then simply folding more and more if the condition testing into each template slot doesn't feel like the right way to go.


    1. I am struggling with similar concerns Ed.

      Originally I had understood the templating language as a way to construct expressions (eventually any of PCG, ECL, SQG) from some kind of input data model, although it was never quite clear whether the output was a single thing or multiple things, and we've never really documented an input model (AFAICR).

      In this scenario, you have some input and you apply a template and you get (or not) an output.

      However, we seem to be straying into a lot of other territory.  For example, validating that the input / output matches a whole lot of other constraints, that really appear more like MRCM issues.  i.e., having generated an expression from a template, does it satisfy some other constraints.

      I'm also wondering about the use-case of an interactive author filling out a template. That is, where the template (and constraints) are somehow used to provide an intelligent UI for authoring.

      All of these uses have an impact on the kinds of design tradeoffs we need to make.  Furthermore, unlike with the others languages where I'm implementing them, we don't have anyone consistently on the call who is implementing the templating language and is thus able to provide input on what is / is not possible / better from that perspective.

      1. Thanks Michael

        It's reassuring to hear that I'm not completely alone with these (and similar) concerns.

        Whilst addressing them now may slow down pragmatic/tactical efforts to meet immediate requirements, I'd hope that in the long term it would result in a more tractable approach.

        Just a thought (which probably others have had): perhaps there is mileage in looking again at the Galen work. The GRAIL language [1] supported the distinction between 'grammatical' sanctioning (personal opinion - more like much of the MRCM) and 'sensible' sanctioning (presumably including intelligent UI features and related rules), and the Galen development workflow included an 'intermediate representation' [2] to hide some of the internal complexity of the required description logic (personal opinion - not unlike the 'grouped/ungrouped' feature of the MRCM as well as the 'allOrNone' idea from the meeting). If these are valid distinctions then there is a risk that they are being mixed up in SNOMED CT's approach.

        Clearly Jeremy has lots of first-hand experience of this work; maybe if we asked nicely he could be persuaded to give us a primer?


        [1] non-searchable document here, summary in Ian's thesis here.

        [2] "Having our cake..."

        1. Hi Ed,

          If Jeremy is able to give us a digestible primer to the Galen work and/or GRAIL language, that would be great.

          Happy to include this in a future languages meeting, if you think this might be directly relevant to this work.

          Thank you!
          Kind regards,

          1. Thanks Linda

            I've raised the question with Jeremy - I'll see what he says.


            1. Doesn't look as though Jeremy will have the time to do a personal presentation on this work in the near future, but in the meantime he shared a few documents...

              "...For digestible primers, there’s the original 1997 paper to MIE (1997 Rogers - (MIE) Rubrics to Dissections.doc) and then a slightly different perspective on the same work that was presented at AMIA in 2000 (conference slides here 2000 Rogers (AMIA) - Intermediate Representation.ppt, original paper at".

              Kind regards


              1. Thanks Ed! Would you be able to give us a summary at this week's meeting (or a future one)?

                Kind regards,

      2. Hi Michael,

        Just to refresh your memory ... we did document an input model, as suggested and reviewed by you previously. See 7.1. Preparing Input Data and 7. Processing Expression Templates.

        Also, while I agree that we don't have anyone regularly on the call who is implementing these templates, Yong and I are working closely with Peter Williams, who is implementing these templates internally within SNOMED International. This implementation work is driving these requirements - so any new features that are added to the syntax will be implemented and testing through Peter's work. 

        Kind regards,

        1. Now I'm glad I included that AFAICR - I clearly didn't recall (smile)


    2. Hi Ed,

      Thank you for sharing your concerns.

      With respect to the FHIR use case, I believe the 2017 STS material is capable of meeting the original FHIR requirements - however the SNOMED on FHIR group hasn't been focusing on using templates recently. I'm not sure if they are still planning to define templates for each clinical resource. Daniel may be able to add a comment here (as a co-chair of the clinical binding stream).

      With respect to the authoring of precoordinated content use case, I completely agree that we should not be attempting to add full condition testing and flow control to the syntax language. I think we're all in agreement there. So then, the question is where is the boundary between what is in scope, and what is out of scope. We had previously agreed that conditional statements such as IF ... THEN .. ELSE were out of scope, as we do not want to introduce a conditional sublanguage into the syntax. Some of the examples that you've included refer to checking if a specific word is in the FSN (e.g. "congenital", "acquired"), which includes both lexical string comparison and conditionality - I would strongly suggest that these are out of scope (for multiple reasons).

      However, (referring to your third example) defining which attributes should be used in each role group is clearly in scope, and as per the current syntax (as long as conditional constraints are not required). Similarly, specifying the cardinality of each attribute in a role group is also in scope (as per the current syntax). Specifying that an attribute must either be used in all instances of a repeated role group or none of them (ie allOrNone), is an extension to these requirements that I agree could be seen as a "conditional cardinality" (i.e. If the attribute is in one instance of the role group, then it's in all instances of the role group). However, this is a very specific use case that is very commonly used in SNOMED CT by our authors, and which does not require any generalised support of full conditionality. Given its frequent usage, and the benefits of being able to share this information in templates published by SNOMED International, I personally think the benefits of including an allOrNone function in the syntax outweigh the disadvantages.

      Happy to continue this discussion, as I agree that the scope of the syntax is an important topic. Thanks for raising this Ed! 

      Kind regards,

      1. Thanks Linda

        You may well be right about the allOrNone use case (a sort of 'inline if' ternary function). I deliberately included the surface property/term clauses as being 'in scope' for formalising authoring business rules; I agree that they would not be sensibly handled in templates, but their consideration highlights the need for a rule language that is able to pull together fragments of ECL, query and template language.


        1. Interesting idea Ed! (i.e. the rule language that pulls together the other syntaxes)
          ... but not for 2019. (smile)

          Kind regards,

  2. A couple of cautious corrections or queries on the 'minutes' above (template syntax section):

    In part 1, example B, in order to satisfy "...and no 2 finding sites subsume each other...", I think the value constraint should read  [[ +id (* MINUS << $site[! SELF ] ) @site]], not  [[ +id (* MINUS $site[! SELF ] ) @site]].

    Also, the supposed valid example of the definition for 208510002 |Multiple fracture of clavicle, scapula and humerus (disorder)| isn't actually valid against the intent of the [[ +id ($morphology [! SELF] ) @morphology ]] constraint ("... in which the morphology is always the same..."). The fourth group has a different morphology value (771485007 |Fracture of multiple bones|) to the preceding three groups (5468008 |Fracture of multiple sites of bone|).


    1. Hi Ed,

      You are absolutely correct on both of these issues. Thank you for spotting these. I believe I have corrected both issues in the 2019-03-27 meeting agenda.

      Kind regards,