Skip to content

Commit

Permalink
feat: add resource patient age filter tests
Browse files Browse the repository at this point in the history
  • Loading branch information
pl-buiquang committed Feb 4, 2025
1 parent 8c1b606 commit 2db5c77
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 40 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -40,42 +40,21 @@ class QueryBuilderBasicResource(val querySolver: ResourceResolver) {
(year_min, month_min, day_min, year_max, month_max, day_max)
}

def addAgeColumn(dataFrame: DataFrame, patientAge: PatientAge): DataFrame = {
val (year_min, _, _, year_max, _, _) = getDecomposedAgeMinAndMax(patientAge)
if (year_max == 0 & year_min == 0) {
dataFrame.withColumn(
QueryColumn.AGE,
F.datediff(F.col(s"${QueryBuilderUtils.getDateColumn(criterionId)}"),
F.col(QueryBuilderUtils.getPatientBirthColumn(criterionId))))
} else {
dataFrame.withColumn(
colName = QueryColumn.AGE,
F.datediff(F.col(s"${QueryBuilderUtils.getDateColumn(criterionId)}"),
F.col(QueryBuilderUtils.getPatientBirthColumn(criterionId))) / 365.25
)
}
def addAgeColumn(dataFrame: DataFrame): DataFrame = {
dataFrame.withColumn(QueryColumn.AGE,
F.datediff(F.col(s"${QueryBuilderUtils.getDateColumn(criterionId)}"),
F.col(QueryBuilderUtils.getPatientBirthColumn(criterionId))))
}

def getAgeFilter(patientAge: PatientAge, dateIsNotNull: Boolean): Column = {
val (year_min, month_min, day_min, year_max, month_max, day_max) =
getDecomposedAgeMinAndMax(patientAge)
var sparkFilterList = new ListBuffer[Column]()
sparkFilterList = if (year_max == 0 & year_min == 0) {
if (patientAge.maxAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) <= month_max * 30 + day_max
}
if (patientAge.minAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) >= month_min * 30 + day_min
}
sparkFilterList
} else {
if (patientAge.maxAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) <= year_max
}
if (patientAge.minAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) >= year_min
}
sparkFilterList
val sparkFilterList = new ListBuffer[Column]()
if (patientAge.maxAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) <= month_max * 30 + day_max + year_max * 365.25
}
if (patientAge.minAge.isDefined) {
sparkFilterList += F.col(QueryColumn.AGE) >= month_min * 30 + day_min + year_min * 365.25
}
val unifiedSparkFilter = sparkFilterList.toList.reduce(_ && _)
if (!dateIsNotNull)
Expand All @@ -97,16 +76,14 @@ class QueryBuilderBasicResource(val querySolver: ResourceResolver) {
criterionId,
datePreference,
basicResource.resourceType)
val criterionDataFrameWithAgeColumn: DataFrame =
addAgeColumn(criterionDataFrameWithDateColumn, patientAge)
val criterionDataFrameWithAgeColumn: DataFrame = addAgeColumn(criterionDataFrameWithDateColumn)

val ageBasedSparkFilter: Column = getAgeFilter(patientAge, dateIsNotNull)

if (logger.isDebugEnabled)
logger.debug(
s"Basic Resource : filterByPatientAge : filter=$ageBasedSparkFilter, df.head=${criterionDataFrameWithDateColumn.head(10).toList.slice(0, 10)}")
var filteredCriterionDataFrame =
criterionDataFrameWithAgeColumn.filter(ageBasedSparkFilter === true)
var filteredCriterionDataFrame = criterionDataFrameWithAgeColumn.filter(ageBasedSparkFilter === true)
filteredCriterionDataFrame = dropTemporaryAgeColumns(filteredCriterionDataFrame)
if (logger.isDebugEnabled)
logger.debug(
Expand All @@ -129,7 +106,9 @@ class QueryBuilderBasicResource(val querySolver: ResourceResolver) {
var operator = code.operator
if (operator != ">=" || n != 1) {
operator = if (operator == "=") "==" else operator
val groupByColumns = ListBuffer[String](QueryBuilderUtils.getSubjectColumn(criterionId), QueryBuilderUtils.buildColName(criterionId, codeColumn))
val groupByColumns = ListBuffer[String](
QueryBuilderUtils.getSubjectColumn(criterionId),
QueryBuilderUtils.buildColName(criterionId, codeColumn))
val filterPatientDataFrame: DataFrame = criterionDataFrame
.groupBy(groupByColumns.head, groupByColumns.tail.toList: _*)
.count()
Expand All @@ -144,7 +123,8 @@ class QueryBuilderBasicResource(val querySolver: ResourceResolver) {
}
if (filterDataframe.isDefined) {
val filterPatientDataFrame = filterDataframe.get
return criterionDataFrame.join(filterPatientDataFrame,
return criterionDataFrame.join(
filterPatientDataFrame,
criterionDataFrame(subjectColumn) <=> filterPatientDataFrame(subjectColumn),
"left_semi")
}
Expand Down Expand Up @@ -306,9 +286,9 @@ class QueryBuilderBasicResource(val querySolver: ResourceResolver) {
isInTemporalConstraint)
criterionDataFrame = filterByUniqueCodes(criterionDataFrame, basicResource, criterionId)
criterionDataFrame = qbUtils.cleanDataFrame(criterionDataFrame,
isInTemporalConstraint,
selectedColumns,
subjectColumn)
isInTemporalConstraint,
selectedColumns,
subjectColumn)

if (logger.isDebugEnabled) {
logger.debug(
Expand Down
3 changes: 3 additions & 0 deletions src/test/resources/testCases/patientAge/expected.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
subject_id
7
1
36 changes: 36 additions & 0 deletions src/test/resources/testCases/patientAge/request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
{
"sourcePopulation": {
"caresiteCohortList": [
57664
]
},
"_type": "request",
"request": {
"_type": "andGroup",
"_id": 0,
"isInclusive": true,
"criteria": [
{
"_type": "basicResource",
"_id": 1,
"isInclusive": true,
"resourceType": "medicationRequestAphp",
"filterSolr": "(codeList:R26) AND active:true",
"filterFhir": "codeList=R26",
"occurrence": {
"n": 1,
"operator": ">=",
"sameEncounter": false,
"sameDay": false
},
"patientAge": {
"minAge": "18-2-4",
"maxAge": "20-0-0",
"datePreference": ["encounter_start_date"]
}
}
],
"temporalConstraints": []
},
"id": 3
}
15 changes: 15 additions & 0 deletions src/test/resources/testCases/patientAge/resource_1.csv
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
_subject;patient_birthdate;encounter_start_date
1;1977-04-01T02:00:00Z;1995-06-10T02:00:00Z
1;1977-04-01T02:00:00Z;2021-12-03T14:09:00Z
1;1977-04-01T02:00:00Z;2021-12-03T14:09:00Z
4;1978-04-01T02:00:00Z;1996-06-01T02:00:00Z
4;1978-03-31T02:00:00Z;2021-12-03T14:09:00Z
6;1979-03-31T02:00:00Z;2021-12-03T14:09:00Z
7;1980-03-31T02:00:00Z;2000-02-03T14:09:00Z
7;1980-03-31T02:00:00Z;2021-12-03T14:09:00Z
7;1980-03-31T02:00:00Z;2021-12-03T14:09:00Z
7;1980-03-31T02:00:00Z;2021-12-03T14:09:00Z
7;1980-03-31T02:00:00Z;2021-12-03T14:09:00Z
8;1981-03-31T02:00:00Z;2021-12-03T14:09:00Z
9;1982-03-31T02:00:00Z;2021-12-03T14:09:00Z

Original file line number Diff line number Diff line change
Expand Up @@ -215,4 +215,8 @@ class QueryBuilderTest extends AnyFunSuiteLike with DatasetComparer {
testCaseEvaluate("nAmongMUniqueFields")
}

test("patientAge") {
testCaseEvaluate("patientAge")
}

}

0 comments on commit 2db5c77

Please sign in to comment.