All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.ikm.elk.snomed.ConceptComparer Maven / Gradle / Ivy

package dev.ikm.elk.snomed;

/*-
 * #%L
 * ELK Integration with SNOMED
 * %%
 * Copyright (C) 2023 - 2024 Integrated Knowledge Management
 * %%
 * 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.
 * #L%
 */

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import dev.ikm.elk.snomed.SnomedConcreteRoles.SnomedConcreteRole;
import dev.ikm.elk.snomed.model.Concept;
import dev.ikm.elk.snomed.model.ConcreteRole;
import dev.ikm.elk.snomed.model.Definition;
import dev.ikm.elk.snomed.model.Role;
import dev.ikm.elk.snomed.model.RoleGroup;

public class ConceptComparer {

	private static final Logger LOG = LoggerFactory.getLogger(ConceptComparer.class);

	private SnomedRoles roles;

	private SnomedConcreteRoles concreteRoles;

	private HashSet mis_match_cons = new HashSet<>();
	private int root_mis_match_cnt = 0;

	private int mis_match_cnt = 0;
	private int mis_match_sno_roles_ungrouped_cnt = 0;
	private int mis_match_nnf_roles_ungrouped_cnt = 0;
	private int mis_match_sno_roles_grouped_cnt = 0;
	private int mis_match_nnf_roles_grouped_cnt = 0;
	private int mis_match_grouping_issue_cnt = 0;

	public ConceptComparer(SnomedRoles roles, SnomedConcreteRoles concreteRoles) {
		this.roles = roles;
		this.concreteRoles = concreteRoles;
	}

	public int getMisMatchCount() {
		return mis_match_cnt;
	}

	public void logErrors() {
		LOG.info("Mis match: " + mis_match_cnt);
		LOG.info("Mis match ungrouped: " + mis_match_sno_roles_ungrouped_cnt + " SNOMED roles "
				+ mis_match_nnf_roles_ungrouped_cnt + " NNF roles");
		LOG.info("Mis match grouped: " + mis_match_sno_roles_grouped_cnt + " SNOMED roles "
				+ mis_match_nnf_roles_grouped_cnt + " NNF roles");
		LOG.info("Mis match grouping issue: " + mis_match_grouping_issue_cnt);
	}

	private static class SnomedRoleGroup {
		List roles = new ArrayList<>();
		List numberProperties = new ArrayList<>();
	}

	private List getRoleGroups(long con, SnomedRoles roles, SnomedConcreteRoles concrete_roles) {
		HashMap groups = new HashMap<>();
		for (SnomedRoles.SnomedRole role : roles.getGroupedRoles(con)) {
			groups.putIfAbsent(role.relationshipGroup, new SnomedRoleGroup());
			groups.get(role.relationshipGroup).roles.add(role);
		}
		for (SnomedConcreteRole role : concrete_roles.getGroupedConcreteRoles(con)) {
			groups.putIfAbsent(role.relationshipGroup, new SnomedRoleGroup());
			groups.get(role.relationshipGroup).numberProperties.add(role);
		}
		return new ArrayList<>(groups.values());
	}

	private boolean compareUngrouped(Concept concept, List sno_roles_ungrouped,
			Set nnf_roles_ungrouped) {
		boolean mis_match = false;
		for (SnomedRoles.SnomedRole sno_role : sno_roles_ungrouped) {
			boolean match = nnf_roles_ungrouped.stream().anyMatch(nnf_role -> compare(sno_role, nnf_role));
			if (!match) {
				LOG.error("No NNF roleU for " + concept + " " + sno_role);
				mis_match = true;
			}
		}
		return mis_match;
	}

	private boolean compareUngrouped(Concept concept, Set nnf_roles_ungrouped,
			List sno_roles_ungrouped) {
		boolean mis_match = false;
		for (Role nnf_role : nnf_roles_ungrouped) {
			boolean match = sno_roles_ungrouped.stream().anyMatch(sno_role -> compare(sno_role, nnf_role));
			if (!match) {
				LOG.error("No SNOMED roleU for " + concept + " " + nnf_role);
				mis_match = true;
			}
		}
		return mis_match;
	}

	private boolean compareUngroupedConcrete(Concept concept, List sno_roles_ungrouped,
			Set nnf_roles_ungrouped) {
		boolean mis_match = false;
		for (SnomedConcreteRole sno_role : sno_roles_ungrouped) {
			boolean match = nnf_roles_ungrouped.stream().anyMatch(nnf_role -> compare(sno_role, nnf_role));
			if (!match) {
				LOG.error("No NNF roleU for " + concept + " " + sno_role);
				mis_match = true;
			}
		}
		return mis_match;
	}

	private boolean compareUngroupedConcrete(Concept concept, Set nnf_roles_ungrouped,
			List sno_roles_ungrouped) {
		boolean mis_match = false;
		for (ConcreteRole nnf_role : nnf_roles_ungrouped) {
			boolean match = sno_roles_ungrouped.stream().anyMatch(sno_role -> compare(sno_role, nnf_role));
			if (!match) {
				LOG.error("No SNOMED roleU for " + concept + " " + nnf_role);
				mis_match = true;
			}
		}
		return mis_match;
	}

	public void compare(Concept concept, Definition definition) {
		List sno_roles_ungrouped = roles.getUngroupedRoles(concept.getId());
		List sno_croles_ungrouped = concreteRoles.getUngroupedConcreteRoles(concept.getId());
		List sno_roles_grouped = getRoleGroups(concept.getId(), roles, concreteRoles);
		//
		Set nnf_roles_ungrouped = definition.getUngroupedRoles();
		Set nnf_croles_ungrouped = definition.getUngroupedConcreteRoles();
		Set nnf_roles_grouped = definition.getRoleGroups();
		//
		boolean mis_match = false;
		List mis_match_sno_roles_grouped = new ArrayList<>();
		List mis_match_nnf_roles_grouped = new ArrayList<>();
		if (compareUngrouped(concept, sno_roles_ungrouped, nnf_roles_ungrouped)) {
			mis_match = true;
			mis_match_sno_roles_ungrouped_cnt++;
		}
		if (compareUngrouped(concept, nnf_roles_ungrouped, sno_roles_ungrouped)) {
			mis_match = true;
			mis_match_nnf_roles_ungrouped_cnt++;
		}
		if (compareUngroupedConcrete(concept, sno_croles_ungrouped, nnf_croles_ungrouped)) {
			mis_match = true;
//			mis_match_sno_roles_ungrouped_cnt++;
		}
		if (compareUngroupedConcrete(concept, nnf_croles_ungrouped, sno_croles_ungrouped)) {
			mis_match = true;
//			mis_match_nnf_roles_ungrouped_cnt++;
		}
		{
			boolean inc = false;
			for (SnomedRoleGroup sno_role : sno_roles_grouped) {
				boolean match = nnf_roles_grouped.stream()
						.anyMatch(nnf_role -> compare(sno_role.roles, nnf_role.getRoles())
								&& compareConcrete(sno_role.numberProperties, nnf_role.getConcreteRoles()));
				if (!match) {
					LOG.error("No NNF roleG for " + concept + " " + sno_role);
					mis_match = true;
					mis_match_sno_roles_grouped.add(sno_role);
					inc = true;
				}
			}
			if (inc)
				mis_match_sno_roles_grouped_cnt++;
		}
		{
			boolean inc = false;
			for (RoleGroup nnf_role : nnf_roles_grouped) {
				boolean match = sno_roles_grouped.stream()
						.anyMatch(sno_role -> compare(sno_role.roles, nnf_role.getRoles())
								&& compareConcrete(sno_role.numberProperties, nnf_role.getConcreteRoles()));
				if (!match) {
					LOG.error("No SNOMED roleG for " + concept + " " + nnf_role);
					mis_match = true;
					mis_match_nnf_roles_grouped.add(nnf_role);
					inc = true;
				}
			}
			if (inc)
				mis_match_nnf_roles_grouped_cnt++;
		}
		if (mis_match) {
			mis_match_cnt++;
			LOG.info("SNO rolesU:");
			sno_roles_ungrouped.stream()
					.sorted(Comparator.comparingLong((SnomedRoles.SnomedRole x) -> x.relationshipGroup)
							.thenComparingLong((SnomedRoles.SnomedRole x) -> x.typeId)
							.thenComparingLong((SnomedRoles.SnomedRole x) -> x.destinationId))
					.forEach(x -> LOG.info("\t" + x));
			LOG.info("SNO concreteRolesU:");
			sno_croles_ungrouped.stream().forEach(x -> LOG.info("\t" + x));
			LOG.info("SNO rolesG:");
			sno_roles_grouped.stream().forEach(rg -> {
				LOG.info("Group:");
				rg.roles.forEach(r -> LOG.info("\t" + r));
				rg.numberProperties.forEach(r -> LOG.info("\t" + r));
			});
			LOG.info("NNF rolesU:");
			definition.getUngroupedRoles().forEach(x -> LOG.info("\t" + x));
			LOG.info("NNF concreteRolesU:");
			definition.getUngroupedConcreteRoles().forEach(x -> LOG.info("\t" + x));
			LOG.info("NNF rolesG:");
			definition.getRoleGroups().forEach(rg -> {
				LOG.info("Group:");
				rg.getRoles().forEach(r -> LOG.info("\t" + r));
				rg.getConcreteRoles().forEach(y -> LOG.info("\t" + y));
			});
			// TODO
//			if (!mis_match_cons.stream().anyMatch(x -> isa.hasAncestor(concept.getId(), x))) {
//				LOG.info("Root mis-match: " + concept.getId());
//				root_mis_match_cnt++;
//			}
			mis_match_cons.add(concept.getId());
			LOG.info("Root mis-match cnt: " + root_mis_match_cnt);
//			if (mis_match_roles_grouped.size() > 0 && mis_match_props_grouped.size() > 0) {
//				if (compare(mis_match_roles_grouped, mis_match_props_grouped)) {
//					LOG.warn("Grouping issue");
//					mis_match_grouping_issue_cnt++;
//					grouping_issue_concepts.add(concept);
//				} else {
//					LOG.error("Not a grouping issue - compare");
//					boolean ancestor_grouping_issue = grouping_issue_concepts.stream().anyMatch(
//							x -> isa.hasAncestor(SnomedOwlOntology.getId(concept), SnomedOwlOntology.getId(x)));
//					if (ancestor_grouping_issue)
//						LOG.warn("Grouping issue with ancestor");
//				}
//			} else {
//				LOG.error("Not a grouping issue - size");
//			}
		}
	}

	private boolean compare(List sno_roles, Set nnf_roles) {
		return sno_roles.stream()
				.allMatch(sno_role -> nnf_roles.stream().anyMatch(nnf_role -> compare(sno_role, nnf_role)))
				&& nnf_roles.stream()
						.allMatch(nnf_role -> sno_roles.stream().anyMatch(sno_role -> compare(sno_role, nnf_role)));
	}

	private boolean compare(SnomedRoles.SnomedRole sno_role, Role nnf_role) {
		return sno_role.typeId == nnf_role.getRoleType().getId()
				&& sno_role.destinationId == nnf_role.getConcept().getId();
	}

	private boolean compareConcrete(List sno_roles,
			Set nnf_roles) {
		return sno_roles.stream()
				.allMatch(sno_role -> nnf_roles.stream().anyMatch(nnf_role -> compare(sno_role, nnf_role)))
				&& nnf_roles.stream()
						.allMatch(nnf_role -> sno_roles.stream().anyMatch(sno_role -> compare(sno_role, nnf_role)));
	}

	private boolean compare(SnomedConcreteRole sno_role, ConcreteRole nnf_role) {
		BigDecimal sno_value = new BigDecimal(sno_role.value.replace("#", ""));
		BigDecimal nnf_value = new BigDecimal(nnf_role.getValue());
		return sno_role.typeId == nnf_role.getConcreteRoleType().getId() && sno_value.compareTo(nnf_value) == 0;
	}

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy