Skip to content

Commit

Permalink
Added visit detail entity (#174)
Browse files Browse the repository at this point in the history
Co-authored-by: Pavel Grafkin <pavgra@gmail.com>
Co-authored-by: Vitaly Koulakov <vitaly.koulakov@gmail.com>
Co-authored-by: Chris Knoll <cknoll@ohdsi.org>
  • Loading branch information
4 people authored Sep 23, 2022
1 parent dba4027 commit 665a097
Show file tree
Hide file tree
Showing 62 changed files with 2,117 additions and 221 deletions.
8 changes: 4 additions & 4 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>org.ohdsi</groupId>
<artifactId>circe</artifactId>
<version>1.9.5-SNAPSHOT</version>
<version>1.10.0-SNAPSHOT</version>
<properties>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
Expand Down Expand Up @@ -77,17 +77,17 @@
<repository>
<id>ohdsi</id>
<name>repo.ohdsi.org</name>
<url>http://repo.ohdsi.org:8085/nexus/content/repositories/releases</url>
<url>https://repo.ohdsi.org/nexus/content/repositories/releases</url>
</repository>
<repository>
<id>ohdsi.thirdparty</id>
<name>repo.ohdsi.org</name>
<url>http://repo.ohdsi.org:8085/nexus/content/repositories/thirdparty</url>
<url>https://repo.ohdsi.org/nexus/content/repositories/thirdparty</url>
</repository>
<repository>
<id>ohdsi.snapshots</id>
<name>repo.ohdsi.org-snapshots</name>
<url>http://repo.ohdsi.org:8085/nexus/content/repositories/snapshots</url>
<url>https://repo.ohdsi.org/nexus/content/repositories/snapshots</url>
<releases>
<enabled>false</enabled>
</releases>
Expand Down
2 changes: 2 additions & 0 deletions src/main/java/org/ohdsi/circe/check/Checker.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.ohdsi.circe.check.checkers.AttributeCheck;
import org.ohdsi.circe.check.checkers.ConceptCheck;
import org.ohdsi.circe.check.checkers.ConceptSetCriteriaCheck;
import org.ohdsi.circe.check.checkers.ConceptSetSelectionCheck;
import org.ohdsi.circe.check.checkers.CriteriaContradictionsCheck;
import org.ohdsi.circe.check.checkers.DeathTimeWindowCheck;
import org.ohdsi.circe.check.checkers.DomainTypeCheck;
Expand Down Expand Up @@ -55,6 +56,7 @@ private List<Check> getChecks() {
checks.add(new ExitCriteriaDaysOffsetCheck());
checks.add(new RangeCheck());
checks.add(new ConceptCheck());
checks.add(new ConceptSetSelectionCheck());
checks.add(new AttributeCheck());
checks.add(new TextCheck());
checks.add(new IncompleteRuleCheck());
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/org/ohdsi/circe/check/Constants.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ interface Criteria {
String PROCEDURE_OCCURRENCE = "procedure occurrence";
String SPECIMEN = "specimen";
String VISIT_OCCURRENCE = "visit occurrence";
String VISIT_DETAIL = "visit detail";
String PAYER_PLAN_PERIOD = "payer plan period";
String OBSERVATION_PERIOD = "observation period";
String LOCATION_REGION = "location region";
Expand Down Expand Up @@ -94,12 +95,18 @@ interface Attributes {
String ANATOMIC_SITE_ATTR = "anatomic site";
String DISEASE_STATUS_ATTR = "disease status";
String PLACE_OF_SERVICE_ATTR = "place of service";
String ADMITTED_FROM_ATTR = "admitted from";
String DISCHARGED_TO_ATTR = "discharged to";
String LOCATION_REGION_START_DATE_ATTR = "location region start date";
String LOCATION_REGION_END_DATE_ATTR = "location region end date";
String STOP_REASON_ATTR = "stop reason";
String UNIQUE_DEVICE_ID_ATTR = "unique device id";
String LOT_NUMBER_ATTR = "lot number";
String VALUE_AS_STRING_ATTR = "value as string";
String SOURCE_ID_ATTR = "source id";
String VISIT_DETAIL_START_DATE_ATTR = "visit detail start date";
String VISIT_DETAIL_END_DATE_ATTR = "visit detail end date";
String VISIT_DETAIL_LENGTH_ATTR = "visit detail length";
String VISIT_DETAIL_TYPE_ATTR = "visit detail type";
}
}
23 changes: 4 additions & 19 deletions src/main/java/org/ohdsi/circe/check/checkers/Comparisons.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,25 +26,7 @@
import java.util.function.Predicate;
import java.util.stream.Collectors;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.ohdsi.circe.cohortdefinition.ConceptSet;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.DateRange;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.NumericRange;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ObservationFilter;
import org.ohdsi.circe.cohortdefinition.Period;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import org.ohdsi.circe.cohortdefinition.Window;
import org.ohdsi.circe.cohortdefinition.*;
import org.ohdsi.circe.vocabulary.Concept;

public class Comparisons {
Expand Down Expand Up @@ -173,6 +155,9 @@ public static boolean compare(Criteria c1, Criteria c2) {
} else if (c1 instanceof VisitOccurrence) {
VisitOccurrence vo1 = (VisitOccurrence) c1, vo2 = (VisitOccurrence) c2;
result = Objects.equals(vo1.codesetId, vo2.codesetId);
} else if (c1 instanceof VisitDetail) {
VisitDetail vd1 = (VisitDetail) c1, vd2 = (VisitDetail) c2;
result = Objects.equals(vd1.codesetId, vd2.codesetId);
}
}
return result;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,22 +19,7 @@
package org.ohdsi.circe.check.checkers;

import org.ohdsi.circe.check.Constants;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DemographicCriteria;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ObservationPeriod;
import org.ohdsi.circe.cohortdefinition.PayerPlanPeriod;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import org.ohdsi.circe.cohortdefinition.*;
import org.ohdsi.circe.vocabulary.Concept;

import java.util.Objects;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,19 +24,7 @@
import org.ohdsi.circe.check.WarningSeverity;
import org.ohdsi.circe.check.operations.Execution;
import org.ohdsi.circe.check.utils.CriteriaNameHelper;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import org.ohdsi.circe.cohortdefinition.*;

public class ConceptSetCriteriaCheck extends BaseCriteriaCheck {

Expand Down Expand Up @@ -109,6 +97,11 @@ protected void checkCriteria(Criteria criteria, String groupName, WarningReporte
.then(c -> match((VisitOccurrence)c)
.when(visitOccurrence -> Objects.isNull(visitOccurrence.codesetId)
&& Objects.isNull(visitOccurrence.visitSourceConcept))
.then(addWarning))
.isA(VisitDetail.class)
.then(c -> match((VisitDetail)c)
.when(visitDetail -> Objects.isNull(visitDetail.codesetId)
&& Objects.isNull(visitDetail.visitDetailSourceConcept))
.then(addWarning));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Copyright 2017 Observational Health Data Sciences and Informatics
* 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.
*
* Authors: Vitaly Koulakov
*
*/

package org.ohdsi.circe.check.checkers;

import org.ohdsi.circe.check.WarningSeverity;
import org.ohdsi.circe.check.operations.Execution;
import org.ohdsi.circe.check.utils.CriteriaNameHelper;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitDetail;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;

import java.util.Objects;
import java.util.function.Function;

import static org.ohdsi.circe.check.operations.Operations.match;

public class ConceptSetSelectionCheck extends BaseValueCheck {
@Override
protected BaseCheckerFactory getFactory(WarningReporter reporter, String name) {
return ConceptSetSelectionCheckerFactory.getFactory(reporter, name);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
/*
* Copyright 2017 Observational Health Data Sciences and Informatics
* 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.
*
* Authors: Sergey Suvorov
*
*/

package org.ohdsi.circe.check.checkers;

import org.ohdsi.circe.check.Constants;
import org.ohdsi.circe.cohortdefinition.ConceptSetSelection;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DemographicCriteria;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ObservationPeriod;
import org.ohdsi.circe.cohortdefinition.PayerPlanPeriod;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitDetail;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import org.ohdsi.circe.vocabulary.Concept;

import java.util.Objects;
import java.util.function.Consumer;

import static org.ohdsi.circe.check.Constants.Attributes.UNIT_ATTR;
import static org.ohdsi.circe.check.operations.Operations.match;

public class ConceptSetSelectionCheckerFactory extends BaseCheckerFactory{
private static final String WARNING_EMPTY_VALUE = "%s in the %s has empty %s value";

private ConceptSetSelectionCheckerFactory(WarningReporter reporter, String groupName) {
super(reporter, groupName);
}

public static ConceptSetSelectionCheckerFactory getFactory(WarningReporter reporter, String groupName) {
return new ConceptSetSelectionCheckerFactory(reporter, groupName);
}

@Override
protected Consumer<Criteria> getCheck(Criteria criteria) {
Consumer<Criteria> result = c -> { };
if (criteria instanceof VisitDetail) {
result = c -> {
VisitDetail vd = (VisitDetail) c;
checkConcept(vd.visitDetailTypeCS, Constants.Criteria.VISIT_DETAIL, Constants.Attributes.VISIT_DETAIL_TYPE_ATTR);
checkConcept(vd.genderCS, Constants.Criteria.VISIT_DETAIL, Constants.Attributes.GENDER_ATTR);
checkConcept(vd.providerSpecialtyCS, Constants.Criteria.VISIT_DETAIL, Constants.Attributes.PROVIDER_SPECIALITY_ATTR);
checkConcept(vd.placeOfServiceCS, Constants.Criteria.VISIT_DETAIL, Constants.Attributes.PLACE_OF_SERVICE_ATTR);
};
}
return result;
}

@Override
protected Consumer<DemographicCriteria> getCheck(DemographicCriteria criteria) {
return c -> {};
}

private void checkConcept(ConceptSetSelection conceptSetSelection, String criteriaName, String attribute) {
Consumer<String> warning = (t) -> reporter.add(t, groupName, criteriaName, attribute);
match(conceptSetSelection)
.when(r -> Objects.nonNull(r) && Objects.isNull(r.codesetId))
.then(() -> warning.accept(WARNING_EMPTY_VALUE));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,15 @@

package org.ohdsi.circe.check.checkers;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import org.ohdsi.circe.cohortdefinition.ConceptSet;
import org.ohdsi.circe.cohortdefinition.ConditionEra;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DoseEra;
import org.ohdsi.circe.cohortdefinition.DrugEra;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.LocationRegion;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import java.util.function.Supplier;

import org.ohdsi.circe.cohortdefinition.*;

class CriteriaCheckerFactory {

Expand Down Expand Up @@ -76,9 +68,34 @@ Function<Criteria, Boolean> getCriteriaChecker(Criteria criteria) {
result = c -> Objects.equals(((Specimen)c).codesetId, conceptSet.id);
} else if (criteria instanceof VisitOccurrence) {
result = c -> Objects.equals(((VisitOccurrence) c).codesetId, conceptSet.id);
} else if (criteria instanceof VisitDetail) {
result = c -> Objects.equals(((VisitDetail) c).codesetId, conceptSet.id) || checkConceptSetSelection(c);
} else if (criteria instanceof LocationRegion) {
result = c -> Objects.equals(((LocationRegion) c).codesetId, conceptSet.id);
}
return result;
}

private boolean checkConceptSetSelection(Criteria criteria) {
boolean result = false;
for (Supplier<ConceptSetSelection> supplier : getSuppliers(criteria)) {
ConceptSetSelection conceptSetSelection = supplier.get();
if (Objects.nonNull(conceptSetSelection)) {
result = result || Objects.equals(conceptSetSelection.codesetId, conceptSet.id);
}
}
return result;
}

private static <T extends Criteria> List<Supplier<ConceptSetSelection>> getSuppliers(T criteria) {
List<Supplier<ConceptSetSelection>> suppliers = new ArrayList<>();
if (criteria instanceof VisitDetail) {
suppliers.add(() -> ((VisitDetail) criteria).placeOfServiceCS);
suppliers.add(() -> ((VisitDetail) criteria).genderCS);
suppliers.add(() -> ((VisitDetail) criteria).providerSpecialtyCS);
suppliers.add(() -> ((VisitDetail) criteria).visitDetailTypeCS);
}

return suppliers;
}
}
16 changes: 5 additions & 11 deletions src/main/java/org/ohdsi/circe/check/checkers/DomainTypeCheck.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,7 @@
import org.ohdsi.circe.check.WarningSeverity;
import org.ohdsi.circe.check.operations.Execution;
import org.ohdsi.circe.check.utils.CriteriaNameHelper;
import org.ohdsi.circe.cohortdefinition.CohortExpression;
import org.ohdsi.circe.cohortdefinition.ConditionOccurrence;
import org.ohdsi.circe.cohortdefinition.Criteria;
import org.ohdsi.circe.cohortdefinition.Death;
import org.ohdsi.circe.cohortdefinition.DeviceExposure;
import org.ohdsi.circe.cohortdefinition.DrugExposure;
import org.ohdsi.circe.cohortdefinition.Measurement;
import org.ohdsi.circe.cohortdefinition.Observation;
import org.ohdsi.circe.cohortdefinition.ProcedureOccurrence;
import org.ohdsi.circe.cohortdefinition.Specimen;
import org.ohdsi.circe.cohortdefinition.VisitOccurrence;
import org.ohdsi.circe.cohortdefinition.*;

public class DomainTypeCheck extends BaseCriteriaCheck {

Expand Down Expand Up @@ -91,6 +81,10 @@ protected void checkCriteria(Criteria criteria, String groupName, WarningReporte
.isA(VisitOccurrence.class)
.then(c -> match((VisitOccurrence)c)
.when(visitOccurrence -> Objects.isNull(visitOccurrence.visitType))
.then(addWarning))
.isA(VisitDetail.class)
.then(c -> match((VisitDetail)c)
.when(visitDetail -> Objects.isNull(visitDetail.visitDetailTypeCS))
.then(addWarning));
}

Expand Down
Loading

0 comments on commit 665a097

Please sign in to comment.