diff --git a/language-extensions/owl-extension/src/main/java/dev/ikm/tinkar/ext/lang/owl/SctOwlUtilities.java b/language-extensions/owl-extension/src/main/java/dev/ikm/tinkar/ext/lang/owl/SctOwlUtilities.java
index 26dff1e2..78777800 100644
--- a/language-extensions/owl-extension/src/main/java/dev/ikm/tinkar/ext/lang/owl/SctOwlUtilities.java
+++ b/language-extensions/owl-extension/src/main/java/dev/ikm/tinkar/ext/lang/owl/SctOwlUtilities.java
@@ -45,7 +45,9 @@
import static java.io.StreamTokenizer.*;
public class SctOwlUtilities {
+
private static final Logger LOG = LoggerFactory.getLogger(SctOwlUtilities.class);
+
public static final String TRANSITIVEOBJECTPROPERTY = "transitiveobjectproperty";
public static final String PREFIX = "prefix";
public static final String ONTOLOGY = "ontology";
@@ -84,7 +86,7 @@ public static LogicalExpression sctToLogicalExpression(String owlClassExpression
String originalExpression = owlClassExpressionsToProcess + " " + owlPropertyExpressionsToProcess;
-
+
final LogicalExpressionBuilder leb = new LogicalExpressionBuilder();
diff --git a/reasoner/reasoner-elk-snomed/pom.xml b/reasoner/reasoner-elk-snomed/pom.xml
index bd40faa4..639240c6 100644
--- a/reasoner/reasoner-elk-snomed/pom.xml
+++ b/reasoner/reasoner-elk-snomed/pom.xml
@@ -69,6 +69,13 @@
${snomed-test-data.version}
zip
+
+ ${snomed-test-data.groupid}
+
+ snomed-test-data-intl-20241001
+ ${snomed-test-data.version}
+ zip
+
${project.build.directory}/data
@@ -92,6 +99,13 @@
zip
+
+ ${reasoner-test-data.groupid}
+
+ tinkar-test-data-snomed-intl-20241001
+ 2024.10.18
+ zip
+
${project.build.directory}/db
diff --git a/reasoner/reasoner-elk-snomed/src/main/java/dev/ikm/tinkar/reasoner/elksnomed/ElkSnomedDataBuilder.java b/reasoner/reasoner-elk-snomed/src/main/java/dev/ikm/tinkar/reasoner/elksnomed/ElkSnomedDataBuilder.java
index 700b1f5b..f2aceb0f 100644
--- a/reasoner/reasoner-elk-snomed/src/main/java/dev/ikm/tinkar/reasoner/elksnomed/ElkSnomedDataBuilder.java
+++ b/reasoner/reasoner-elk-snomed/src/main/java/dev/ikm/tinkar/reasoner/elksnomed/ElkSnomedDataBuilder.java
@@ -22,6 +22,7 @@
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import dev.ikm.elk.snomed.SnomedIds;
import dev.ikm.elk.snomed.model.Concept;
import dev.ikm.elk.snomed.model.ConcreteRole;
import dev.ikm.elk.snomed.model.ConcreteRole.ValueType;
@@ -35,6 +36,7 @@
import dev.ikm.tinkar.common.id.PublicId;
import dev.ikm.tinkar.common.service.PrimitiveData;
import dev.ikm.tinkar.common.service.TrackingCallable;
+import dev.ikm.tinkar.common.util.uuid.UuidUtil;
import dev.ikm.tinkar.coordinate.logic.LogicCoordinateRecord;
import dev.ikm.tinkar.coordinate.view.calculator.ViewCalculator;
import dev.ikm.tinkar.entity.graph.DiTreeEntity;
@@ -204,18 +206,27 @@ private void processPropertySet(EntityVertex propertySetNode, int conceptNid, Di
for (EntityVertex node : definition.successors(child)) {
switch (getMeaning(node)) {
case CONCEPT -> {
- RoleType roleType = data.getOrCreateRoleType(conceptNid);
ConceptFacade nodeConcept = node.propertyFast(TinkarTerm.CONCEPT_REFERENCE);
- if (nodeConcept.nid() == TinkarTerm.TRANSITIVE_PROPERTY.nid()) {
- roleType.setTransitive(true);
- } else if (nodeConcept.nid() == TinkarTerm.REFLEXIVE_PROPERTY.nid()) {
- roleType.setReflexive(true);
+ // This won't work if SNOMED introduces data property hierarchy
+// LOG.info("UUID for " + SnomedIds.concept_model_data_attribute + " "
+// + UuidUtil.fromSNOMED("" + SnomedIds.concept_model_data_attribute));
+// if (nodeConcept.nid() == ElkSnomedData.getNid(SnomedIds.concept_model_data_attribute)) {
+ if (nodeConcept.nid() == TinkarTerm.CONCEPT_MODEL_DATA_ATTRIBUTE.nid()) {
+ ConcreteRoleType roleType = data.getOrCreateConcreteRoleType(conceptNid);
+ roleType.addSuperConcreteRoleType(data.getOrCreateConcreteRoleType(nodeConcept.nid()));
} else {
- roleType.addSuperRoleType(data.getOrCreateRoleType(nodeConcept.nid()));
+ RoleType roleType = data.getOrCreateRoleType(conceptNid);
+ if (nodeConcept.nid() == TinkarTerm.TRANSITIVE_PROPERTY.nid()) {
+ roleType.setTransitive(true);
+ } else if (nodeConcept.nid() == TinkarTerm.REFLEXIVE_PROPERTY.nid()) {
+ roleType.setReflexive(true);
+ } else {
+ roleType.addSuperRoleType(data.getOrCreateRoleType(nodeConcept.nid()));
+ }
}
}
case PROPERTY_PATTERN_IMPLICATION -> {
- LOG.info("PropertySet: " + PrimitiveData.text(conceptNid) + " " + propertySetNode + "\n" + definition);
+// LOG.info("PropertySet: " + PrimitiveData.text(conceptNid) + " " + propertySetNode + "\n" + definition);
RoleType roleType = data.getOrCreateRoleType(conceptNid);
// TODO: update to new concept binding: Property sequence implication...
ConceptFacade ppi = node.propertyFast(TinkarTerm.PROPERTY_PATTERN_IMPLICATION);
@@ -223,6 +234,10 @@ private void processPropertySet(EntityVertex propertySetNode, int conceptNid, Di
throw new IllegalStateException(
"Property chain malformed. Concept: " + conceptNid + " definition: " + definition);
IntIdList ps = node.propertyFast(TinkarTerm.PROPERTY_SEQUENCE);
+ if (ps == null)
+ throw new IllegalStateException(
+ "Property chain malformed. Expected " + TinkarTerm.PROPERTY_SEQUENCE.description()
+ + " Concept: " + conceptNid + " definition: " + definition);
if (ps.size() != 2)
throw new IllegalStateException("Property chain " + ps.size() + " != 2. Concept: " + conceptNid
+ " definition: " + definition);
@@ -234,8 +249,8 @@ private void processPropertySet(EntityVertex propertySetNode, int conceptNid, Di
if (!roleType.equals(prop1))
throw new IllegalStateException("This is a bug.");
roleType.setChained(prop2);
- LOG.info("PPI: " + PrimitiveData.text((int) prop1.getId()) + " "
- + PrimitiveData.text((int) prop1.getChained().getId()));
+// LOG.info("PPI: " + PrimitiveData.text((int) prop1.getId()) + " -> "
+// + PrimitiveData.text((int) prop1.getChained().getId()));
}
default -> throw new UnsupportedOperationException("Can't handle: " + node + " in: " + definition);
}
diff --git a/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedClassifierTestIT.java b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedClassifierTestIT.java
new file mode 100644
index 00000000..7c3aa80f
--- /dev/null
+++ b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedClassifierTestIT.java
@@ -0,0 +1,149 @@
+/*
+ * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.ikm.tinkar.reasoner.elksnomed;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.UUID;
+import java.util.stream.Collectors;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import dev.ikm.elk.snomed.SnomedIds;
+import dev.ikm.elk.snomed.SnomedIsa;
+import dev.ikm.elk.snomed.SnomedOntology;
+import dev.ikm.elk.snomed.SnomedOntologyReasoner;
+import dev.ikm.elk.snomed.model.Concept;
+import dev.ikm.tinkar.common.service.PrimitiveData;
+import dev.ikm.tinkar.common.util.uuid.UuidUtil;
+
+public class SnomedINTL20241001ElkSnomedClassifierTestIT extends SnomedINTL20241001ElkSnomedTestBase {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SnomedINTL20241001ElkSnomedClassifierTestIT.class);
+
+ @Test
+ public void supercs() throws Exception {
+ ArrayList lines = runSnomedReasoner();
+ assertEquals(634059, lines.size());
+ }
+
+ @Test
+ public void supercsService() throws Exception {
+ ArrayList lines = runSnomedReasonerService();
+ assertEquals(634059, lines.size());
+ }
+
+ private HashMap nid_sctid_map;
+
+ private Set toSctids(Set nids) {
+ return nids.stream().map(x -> nid_sctid_map.get(x.intValue())).collect(Collectors.toSet());
+ }
+
+ @Test
+ public void isas() throws Exception {
+ LOG.info("runSnomedReasoner");
+ ElkSnomedData data = buildSnomedData();
+ LOG.info("Create ontology");
+ SnomedOntology ontology = new SnomedOntology(data.getConcepts(), data.getRoleTypes(), List.of());
+ LOG.info("Create reasoner");
+ SnomedOntologyReasoner reasoner = SnomedOntologyReasoner.create(ontology);
+ TreeSet misses = new TreeSet<>();
+ TreeSet other_misses = new TreeSet<>();
+ int non_snomed_cnt = 0;
+ int miss_cnt = 0;
+ int pharma_miss_cnt = 0;
+ int other_miss_cnt = 0;
+ SnomedIsa isas = SnomedIsa.init(rels_file);
+ nid_sctid_map = new HashMap<>();
+ for (long sctid : isas.getOrderedConcepts()) {
+ int nid = ElkSnomedData.getNid(sctid);
+ nid_sctid_map.put(nid, sctid);
+ }
+ for (Concept con : ontology.getConcepts()) {
+ long nid = con.getId();
+ Set sups = toSctids(reasoner.getSuperConcepts(nid));
+ Long sctid = nid_sctid_map.get((int) nid);
+ if (sctid == null) {
+ non_snomed_cnt++;
+ continue;
+ }
+ Set parents = isas.getParents(sctid);
+ if (sctid == SnomedIds.root) {
+ assertTrue(parents.isEmpty());
+ } else {
+ assertNotNull(parents);
+ }
+ if (!parents.equals(sups)) {
+ misses.add(sctid);
+ miss_cnt++;
+ if (isas.hasAncestor(sctid, 373873005)) {
+ // 373873005 |Pharmaceutical / biologic product (product)|
+ pharma_miss_cnt++;
+ } else if (isas.hasAncestor(sctid, 127785005)) {
+ // 127785005 |Administration of substance to produce immunity, either active or
+ // passive (procedure)|
+ } else if (isas.hasAncestor(sctid, 713404003)) {
+ // 713404003 |Vaccination given (situation)|
+ } else if (isas.hasAncestor(sctid, 591000119102l)) {
+ // 591000119102 |Vaccine declined by patient (situation)|
+ } else if (isas.hasAncestor(sctid, 90351000119108l)) {
+ // 90351000119108 |Vaccination not done (situation)|
+ } else if (isas.hasAncestor(sctid, 293104008)) {
+ // 293104008 |Adverse reaction to component of vaccine product (disorder)|
+ } else if (isas.hasAncestor(sctid, 266758009)) {
+ // 266758009 |Immunization contraindicated (situation)|
+ } else {
+ other_misses.add(sctid);
+ other_miss_cnt++;
+ }
+ }
+ }
+ isas.getOrderedConcepts().stream().filter(other_misses::contains) //
+ .limit(10) //
+ .forEach((sctid) -> {
+ UUID uuid = UuidUtil.fromSNOMED("" + sctid);
+ int nid = PrimitiveData.nid(uuid);
+ LOG.error("Miss: " + sctid + " " + PrimitiveData.text(nid));
+ Set sups = toSctids(reasoner.getSuperConcepts(nid));
+ Set parents = isas.getParents(sctid);
+ HashSet par = new HashSet<>(parents);
+ par.removeAll(sups);
+ HashSet sup = new HashSet<>(sups);
+ sup.removeAll(parents);
+ LOG.error("Sno: " + par);
+ LOG.error("Elk: " + sup);
+ });
+ LOG.error("Miss cnt: " + miss_cnt);
+ LOG.error("Pharma cnt: " + pharma_miss_cnt);
+ LOG.error("Other cnt: " + other_miss_cnt);
+ assertEquals(282, non_snomed_cnt);
+ // TODO this should be 0 after all the data issues are fixed
+ assertEquals(21065, miss_cnt);
+ assertEquals(20815, pharma_miss_cnt);
+ assertEquals(194, other_miss_cnt);
+ }
+
+}
diff --git a/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedCompareTestIT.java b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedCompareTestIT.java
new file mode 100644
index 00000000..83563a86
--- /dev/null
+++ b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedCompareTestIT.java
@@ -0,0 +1,155 @@
+/*
+ * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.ikm.tinkar.reasoner.elksnomed;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
+
+import java.nio.file.Files;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import dev.ikm.elk.snomed.SnomedDescriptions;
+import dev.ikm.elk.snomed.SnomedIds;
+import dev.ikm.elk.snomed.SnomedOntology;
+import dev.ikm.elk.snomed.model.Concept;
+import dev.ikm.elk.snomed.model.Definition;
+import dev.ikm.elk.snomed.model.RoleType;
+import dev.ikm.elk.snomed.owl.OwlTransformer;
+import dev.ikm.elk.snomed.owl.SnomedOwlOntology;
+import dev.ikm.tinkar.common.util.uuid.UuidUtil;
+
+public class SnomedINTL20241001ElkSnomedCompareTestIT extends SnomedINTL20241001ElkSnomedTestBase {
+
+ private static final Logger LOG = LoggerFactory.getLogger(SnomedINTL20241001ElkSnomedCompareTestIT.class);
+
+ @Test
+ public void compare() throws Exception {
+ assumeTrue(Files.exists(axioms_file), "No file: " + axioms_file);
+ assumeTrue(Files.exists(rels_file), "No file: " + rels_file);
+ LOG.info("Files exist");
+ LOG.info("\t" + axioms_file);
+ LOG.info("\t" + rels_file);
+ ElkSnomedData data = buildSnomedData();
+ {
+ Concept us_con = data.getConcept(ElkSnomedData.getNid(SnomedIds.us_nlm_module));
+ assertNull(us_con);
+ }
+ SnomedOwlOntology ontology = SnomedOwlOntology.createOntology();
+ ontology.loadOntology(axioms_file);
+ SnomedOntology snomedOntology = new OwlTransformer().transform(ontology);
+ snomedOntology.setDescriptions(SnomedDescriptions.init(descriptions_file));
+ {
+ Concept us_con = snomedOntology.getConcept(SnomedIds.us_nlm_module);
+ assertNull(us_con);
+ }
+ for (RoleType role : snomedOntology.getRoleTypes()) {
+ int nid = ElkSnomedData.getNid(role.getId());
+ RoleType data_role = data.getRoleType(nid);
+ if (data_role == null)
+ continue;
+ data_role.setId(role.getId());
+ }
+ for (Concept con : snomedOntology.getConcepts()) {
+ int nid = ElkSnomedData.getNid(con.getId());
+ Concept data_con = data.getConcept(nid);
+ if (data_con == null)
+ continue;
+ data_con.setId(con.getId());
+ }
+ int missing_role_cnt = 0;
+ int missing_concept_cnt = 0;
+ int compare_role_cnt = 0;
+ int compare_concept_cnt = 0;
+ for (RoleType role : snomedOntology.getRoleTypes()) {
+ int nid = ElkSnomedData.getNid(role.getId());
+ RoleType data_role = data.getRoleType(nid);
+ if (data_role == null) {
+ LOG.error("No role: " + role);
+ missing_role_cnt++;
+ continue;
+ }
+ if (!compare(role, data_role, snomedOntology))
+ compare_role_cnt++;
+ }
+ for (Concept con : snomedOntology.getConcepts()) {
+ int nid = ElkSnomedData.getNid(con.getId());
+ Concept data_con = data.getConcept(nid);
+ if (data_con == null) {
+ LOG.error("No concept: " + con);
+ missing_concept_cnt++;
+ continue;
+ }
+// LOG.info(con.getId() + " " + snomedOntology.getFsn(con.getId()));
+ if (!compare(con, data_con, snomedOntology))
+ compare_concept_cnt++;
+ }
+ assertEquals(0, missing_role_cnt);
+ assertEquals(0, missing_concept_cnt);
+ // TODO should be 0 when data issues are fixed
+ assertEquals(5, compare_role_cnt);
+ assertEquals(7, compare_concept_cnt);
+ }
+
+ public boolean compareEquals(Object expect, Object actual, String msg) {
+ if (Objects.equals(expect, actual))
+ return true;
+ LOG.error(msg);
+ LOG.error("Expect: " + expect + " Actual: " + actual);
+ return false;
+ }
+
+ public boolean compare(RoleType expect, RoleType actual, SnomedOntology snomedOntology) {
+ String con_msg = expect.getId() + " " + snomedOntology.getFsn(expect.getId());
+ return compareEquals(new HashSet<>(expect.getSuperRoleTypes()), new HashSet<>(actual.getSuperRoleTypes()),
+ "Super Role Types " + con_msg)
+ & compareEquals(expect.isTransitive(), actual.isTransitive(), "Transitive " + con_msg)
+ & compareEquals(expect.getChained(), actual.getChained(), "Chained " + con_msg)
+ & compareEquals(expect.isReflexive(), actual.isReflexive(), "Reflexive " + con_msg);
+ }
+
+ public boolean compare(Concept expect, Concept actual, SnomedOntology snomedOntology) {
+ compareDefinitions(expect.getDefinitions(), actual.getDefinitions(), "Definitions ", expect, snomedOntology);
+ compareDefinitions(expect.getGciDefinitions(), actual.getGciDefinitions(), "Gci Definitions ", expect,
+ snomedOntology);
+ String con_msg = expect.getId() + " " + snomedOntology.getFsn(expect.getId());
+ return compareEquals(new HashSet<>(expect.getDefinitions()),
+ new HashSet<>(actual.getDefinitions().stream().map(x -> x.copy()).toList()), "Definitions " + con_msg)
+ & compareEquals(new HashSet<>(expect.getGciDefinitions()),
+ new HashSet<>(actual.getGciDefinitions().stream().map(x -> x.copy()).toList()),
+ "Gci Definitions " + con_msg);
+ }
+
+ @Deprecated
+ public boolean compareDefinitions(List expect, List actual, String msg, Concept con,
+ SnomedOntology snomedOntology) {
+ if (expect.size() != actual.size()) {
+ LOG.error(msg + con.getId() + " " + snomedOntology.getFsn(con.getId()) + "\n" + "Expect " + expect.size()
+ + " Actual " + actual.size() + "\n"
+ // + nid + " "
+ + UuidUtil.fromSNOMED("" + con.getId()));
+ return false;
+ }
+ return true;
+ }
+
+}
diff --git a/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedDataBuilderTestIT.java b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedDataBuilderTestIT.java
new file mode 100644
index 00000000..af52d847
--- /dev/null
+++ b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedDataBuilderTestIT.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.ikm.tinkar.reasoner.elksnomed;
+
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class SnomedINTL20241001ElkSnomedDataBuilderTestIT extends SnomedINTL20241001ElkSnomedTestBase {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(SnomedINTL20241001ElkSnomedDataBuilderTestIT.class);
+
+ @Test
+ public void statedPattern() throws Exception {
+ super.statedPattern();
+ }
+
+ @Test
+ public void count() throws Exception {
+ super.count();
+ }
+
+ @Test
+ public void build() throws Exception {
+ super.build();
+ }
+}
diff --git a/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedTestBase.java b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedTestBase.java
new file mode 100644
index 00000000..dc1991a0
--- /dev/null
+++ b/reasoner/reasoner-elk-snomed/src/test/java/dev/ikm/tinkar/reasoner/elksnomed/SnomedINTL20241001ElkSnomedTestBase.java
@@ -0,0 +1,73 @@
+/*
+ * Copyright © 2015 Integrated Knowledge Management (support@ikm.dev)
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package dev.ikm.tinkar.reasoner.elksnomed;
+
+import java.io.IOException;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import dev.ikm.tinkar.common.service.PrimitiveData;
+
+public class SnomedINTL20241001ElkSnomedTestBase extends ElkSnomedDataBuilderTest {
+
+ @SuppressWarnings("unused")
+ private static final Logger LOG = LoggerFactory.getLogger(SnomedINTL20241001ElkSnomedTestBase.class);
+
+ static {
+ stated_count = 394202;
+ active_count = 366841;
+ inactive_count = 27361;
+ test_case = "snomed-us-20241001";
+ }
+
+ public static final String db = "SnomedCT_INTL_20241001_SpinedArray-20241018";
+
+ protected String getDir() {
+ return "target/data/snomed-test-data-" + getEditionDir() + "-" + getVersion();
+ }
+
+ protected String getEdition() {
+ return "INT";
+ }
+
+ protected String getEditionDir() {
+ return "intl";
+ }
+
+ protected String getVersion() {
+ return "20241001";
+ }
+
+ protected Path axioms_file = Paths.get(getDir(),
+ "sct2_sRefset_OWLExpressionSnapshot_" + getEdition() + "_" + getVersion() + ".txt");
+
+ protected Path rels_file = Paths.get(getDir(),
+ "sct2_Relationship_Snapshot_" + getEdition() + "_" + getVersion() + ".txt");
+
+ protected Path descriptions_file = Paths.get(getDir(),
+ "sct2_Description_Snapshot-en_" + getEdition() + "_" + getVersion() + ".txt");
+
+ @BeforeAll
+ public static void startPrimitiveData() throws IOException {
+ setupPrimitiveData(db);
+ PrimitiveData.start();
+ }
+
+}
diff --git a/terms/src/main/java/dev/ikm/tinkar/terms/TinkarTerm.java b/terms/src/main/java/dev/ikm/tinkar/terms/TinkarTerm.java
index cb944bbb..e7950b83 100644
--- a/terms/src/main/java/dev/ikm/tinkar/terms/TinkarTerm.java
+++ b/terms/src/main/java/dev/ikm/tinkar/terms/TinkarTerm.java
@@ -6835,6 +6835,9 @@ public class TinkarTerm {
public static final EntityProxy.Concept TINKAR_MODEL_CONCEPT =
EntityProxy.Concept.make("Tinkar Model concept (SOLOR)", UUID.fromString("bc59d656-83d3-47d8-9507-0e656ea95463"));
+ public static final EntityProxy.Concept CONCEPT_MODEL_DATA_ATTRIBUTE =
+ EntityProxy.Concept.make("Concept model data attribute (SOLOR)", UUID.fromString("e418d7a7-2760-3746-ba2e-253b5e383147"));
+
/**
* ConceptProxy for: "Tinkar root concept".
*/