Conversation
Widen the whitespace check to rdfs:label and rid:UMLS_Term. Add checks for empty annotation values, rid:RadLexID matching the IRI, class IRIs in RID<digits> form (WARN), and rid:Replaced_by being an IRI, aimed at a live class, and carried only by retired classes. Fix the violations on main: 7 labels, 2 rid:RadLexID typos, 4 rid:Replaced_by literals, 2 chained retirements. Remove a stray conflict marker from .gitignore. Part of #5. Related to #8.
| # | ||
| # The constrained properties are checked directly and through any declared sub-property. Matching only through | ||
| # rdfs:subPropertyOf would skip rdfs:label and rid:UMLS_Term, which have no sub-properties (rid:Synonym is caught | ||
| # that way only because it is declared as a sub-property of itself). |
There was a problem hiding this comment.
Good catch. rdfs:subPropertyOf is reflexive, so with RDFS entailments, the '*' would not be necessary - but ROBOT does not compute those entailments when it runs these testing queries.
|
In general, I would like the ROBOT testing queries to be named consistently for what they bind, rather than how they happen to be used. The queries themselves bind violations, so (IMO) should be named for the thing we expect them to return - e.g. Please make that change for the new queries? |
There was a problem hiding this comment.
This one seems like a new policy that we should discuss before adding the test. Even the warning is noise until we make that decision. I'd prefer to remove this, and add the recommendation as an Issue so we can discuss it there.
| # VIOLATIONS will be bindings that have, on ?entity, ?property, and ?value respectively: | ||
| # - The entity carrying the empty assertion. | ||
| # - The annotation property. | ||
| # - The empty value. |
There was a problem hiding this comment.
nit:
| # - The empty value. | |
| # - The empty or whitespace value. |
| WHERE { | ||
| BIND(rid:Replaced_by AS ?property) | ||
| ?entity ?property ?value . | ||
| FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_name } |
There was a problem hiding this comment.
I recommend removing this line for clarity; we should separately require that it is only present on subclasses of rid:RID15849.
There was a problem hiding this comment.
Done. Every check now treats a class as obsolete only when it is under RID15849. The separate check is live_class_with_preferred_name_for_obsolete. It reported two misfiled obsolete classes, and I moved them.
There was a problem hiding this comment.
I'm ambivalent about this one. It implies that chains will always be resolvable to a live class. But what if we retire class A as a duplicate of class B, and then retire class B for a different reason (so it has no "replacement")? Do we need to drop the pointer from A to B? It's not hurting anything AFAICT.
Even if we do have a chain that ends in a "live" class, resolving that chain when/as needed seems totally doable by consumers, and I'm not sure that we should take on the maintenance burden (and loss of historical record) implied by needing to repoint.
Counterpoint might be that this rule catches mistakes where a replacement is already retired when it is asserted.
There was a problem hiding this comment.
Agreed. The check now reports only a replacement that doesn't exist, and I restored the two chains.
|
Reviewing the actual ontology changes, I see several cases where values were changed in nontrivial ways (from what I've seen so far, in ". I think those changes deserve close review or at least reporting - not saying they are wrong, but given how difficult it can be to review OWL changes, listing those changes in an easy-to-digest format seems important. So far I see such changes in RadLexID assertions, and in Replaced_By assertions. The whitespace fixes are more trivial and easy to assess here in github; the others aren't, IMO. |
| ?entity ?property ?value . | ||
| FILTER(isIRI(?value)) | ||
| FILTER(?value != rid:RID15849) | ||
| { ?value rid:Preferred_Name_for_Obsolete ?_pname } UNION { ?value rdfs:subClassOf rid:RID15849 } |
There was a problem hiding this comment.
Use rdfs:subClassOf+: without RDFS inference this only matches direct children of RID15849, so a retired class nested deeper (and lacking Preferred_Name_for_Obsolete) would be missed. + rather than * so RID15849 itself isn't treated as retired.
There was a problem hiding this comment.
Done for the parent. With + on the child, the check never returns a result, because any child of an obsolete class is itself under RID15849. I confirmed this with a test case. The check now reports a child of an obsolete class that has no obsolete name of its own.
| FILTER(?value != rid:RID15849) | ||
| { ?value rid:Preferred_Name_for_Obsolete ?_pname } UNION { ?value rdfs:subClassOf rid:RID15849 } | ||
| FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_cname } | ||
| FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } |
There was a problem hiding this comment.
Same here: rdfs:subClassOf+.
| BIND(rid:Replaced_by AS ?property) | ||
| ?entity ?property ?value . | ||
| FILTER NOT EXISTS { ?entity rid:Preferred_Name_for_Obsolete ?_name } | ||
| FILTER NOT EXISTS { ?entity rdfs:subClassOf rid:RID15849 } |
There was a problem hiding this comment.
Use rdfs:subClassOf+: without RDFS inference this only matches direct children of RID15849, so a retired class nested deeper (and lacking Preferred_Name_for_Obsolete) would be missed. + rather than * so RID15849 itself isn't treated as retired.
| } | ||
| UNION | ||
| { | ||
| { ?value rid:Preferred_Name_for_Obsolete ?_name } UNION { ?value rdfs:subClassOf rid:RID15849 } |
There was a problem hiding this comment.
Use rdfs:subClassOf+: without RDFS inference this only matches direct children of RID15849, so a retired class nested deeper (and lacking Preferred_Name_for_Obsolete) would be missed. + rather than * so RID15849 itself isn't treated as retired.
There was a problem hiding this comment.
Removed with the change above.
…D15849 alone Rename the queries for the violations they return. Drop the RID<digits> IRI check pending its own issue. Use rdfs:subClassOf+ to find obsolete classes at any depth. Add a check that Preferred_Name_for_Obsolete sits only on obsolete classes, and file its two hits (RID27787, RID49508) under RID15849. Narrow the Replaced_by target check to undeclared targets and restore the two chained pointers.
|
Thanks, Jeff. I made all the changes in 7d7f44e. I renamed each check for what it reports, such as
I also put back the two replacement chains I had changed. |
Part of #5.
I added seven checks and widened the whitespace check. A class is obsolete when it is filed anywhere under RID15849, as we agreed in #13.
RadLexIDReplaced_byReplaced_byReplaced_byPreferred_Name_for_ObsoletesubClassOfI fixed what the checks found on
main. That was 7 labels, 2 ID typos, 4 replacements stored as text, 2 obsolete classes filed in the wrong place, and a stray line in.gitignore. All tests pass.