Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 10 additions & 5 deletions backend/api/management/commands/fill_db_mock_patient_data.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,14 @@ def handle(self, *args, **kwargs):

# Generate mock data for SURGERY_CASE
for pat, visit in visits:
surg1_start = visit.ADM_DTM + timedelta(hours=2)
surg2_start = visit.ADM_DTM + timedelta(days=1)
for start_time in [surg1_start, surg2_start]:
if random.random() < 0.3: # ~30% of visits get only one surgery
surgery_starts = [visit.ADM_DTM + timedelta(hours=2)]
else:
surgery_starts = [
visit.ADM_DTM + timedelta(hours=2),
visit.ADM_DTM + timedelta(days=1)
]
for start_time in surgery_starts:
surg_end = make_aware(fake.date_time_between(start_date=start_time, end_date=start_time + timedelta(hours=5)))

surgeon = fake.random_element(elements=surgeons)
Expand Down Expand Up @@ -201,7 +206,6 @@ def handle(self, *args, **kwargs):
# Generate mock data for BILLING_CODES
codes, _, _ = get_all_cpt_code_filters()
for surg in surgeries:
for rank in range(random.randint(1, 5)):
BILLING_CODES.objects.create(
VISIT_NO=surg.VISIT_NO,
CODE_TYPE_DESC=fake.sentence(),
Expand All @@ -211,8 +215,9 @@ def handle(self, *args, **kwargs):
PROV_ID=surg.SURGEON_PROV_ID,
PROV_NAME=surg.SURGEON_PROV_NAME,
PRESENT_ON_ADM_F=fake.random_element(elements=('Y', None)),
CODE_RANK=rank,
CODE_RANK=1,
)

self.stdout.write(self.style.SUCCESS('Successfully generated billing codes data'))

# Generate mock data for VISIT_LABS
Expand Down
27 changes: 18 additions & 9 deletions frontend/src/Components/Utilities/LeftToolBox/LeftToolBox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,20 @@ function LeftToolBox() {
const procedureFetch = await fetch(`${import.meta.env.VITE_QUERY_URL}get_procedure_counts`);
const procedureInput = await procedureFetch.json() as { result: { procedureName: string, procedureCodes: string[], count: number, overlapList: { [key: string]: number } }[] };

// Process the result into the data type required.
const result = procedureInput.result.map((procedure) => {
const procedureOverlapList = Object.keys(procedure.overlapList).map((subProcedureName) => ({
procedureName: subProcedureName,
count: procedure.overlapList[subProcedureName],
codes: procedureInput.result.find((p) => p.procedureName === subProcedureName)?.procedureCodes || [],
}));
// For each procedure, create a ProcedureEntry object
const procedures = procedureInput.result.map((procedure) => {
// Overlap List (Co-occurences of procedures)
const procedureOverlapList = Object.keys(procedure.overlapList).map((subProcedureName) => {
// Strip "Only " prefix for lookup
const baseSubProcedureName = subProcedureName.startsWith('Only ') ? subProcedureName.replace(/^Only\s+/, '') : subProcedureName;
return {
procedureName: subProcedureName,
count: procedure.overlapList[subProcedureName],
// Access the codes for this sub-procedure by looking up the procedure's codes for that name
codes: procedureInput.result.find((p) => p.procedureName === baseSubProcedureName)?.procedureCodes || [],
};
});
// Sort the co-occurrence list by count, and prioritize "Only" procedures
procedureOverlapList.sort((a, b) => {
if (a.procedureName.includes('Only')) {
return -1;
Expand All @@ -40,15 +47,17 @@ function LeftToolBox() {

return b.count - a.count;
});
// Return the ProcedureEntry object
return {
procedureName: procedure.procedureName,
count: procedure.count,
codes: procedure.procedureCodes,
overlapList: procedureOverlapList,
};
});
const tempSurgeryList: ProcedureEntry[] = result;
let tempMaxCaseCount = (max(result, (d) => d.count)) || 0;

const tempSurgeryList: ProcedureEntry[] = procedures;
let tempMaxCaseCount = (max(procedures, (d) => d.count)) || 0;

tempMaxCaseCount *= 1.1;
setMaxCaseCount(tempMaxCaseCount);
Expand Down
27 changes: 21 additions & 6 deletions frontend/src/Interfaces/Store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@
const surgeons = this._allCases.map((d) => [d.SURGEON_PROV_ID, d.SURGEON_PROV_NAME]);
const anesths = this._allCases.map((d) => [d.ANESTH_PROV_ID, d.ANESTH_PROV_NAME]);
return Object.fromEntries(
[...surgeons, ...anesths].filter((d) => d[0] !== null && d[1] !== null)
[...surgeons, ...anesths].filter((d) => d[0] !== null && d[1] !== null),
);
}

get filteredCases() {
return this._allCases.filter((d) => {
const cases = this._allCases.filter((d) => {
// Date range filter
if (!(d.CASE_DATE >= this.provenanceState.rawDateRange[0] && d.CASE_DATE <= this.provenanceState.rawDateRange[1])) {
return false;
Expand Down Expand Up @@ -117,15 +117,28 @@

// If there are selected procedures, filter cases based on the selected procedures
const procedureFiltered = hasAnyProcedure && !this.provenanceState.proceduresSelection.some((procedure) => {
// This case's procedure codes. Example: [A code matching ECMO, A code matching CABG, ...]
const patientCodes = d.ALL_CODES.split(',');

// Sub-procedures selected (overlapList)
// If sub-procedures selected (overlapList) Example: ["ECMO" is selected as the sub-procedure of "CABG"]
if (procedure.overlapList && procedure.overlapList.length > 0) {
return procedure.codes.some((code) => patientCodes.includes(code))
&& procedure.overlapList.some((subProcedure) => subProcedure.codes.some((code) => patientCodes.includes(code)));
return procedure.overlapList.some((subProcedure) => {
// Handle "Only " sub-procedure logic
if (subProcedure.procedureName.startsWith('Only ')) {
// Only include cases where the patients codes is the same or subset of the sub-procedure codes
// Example: Patients codes are ["123"] and subProcedure codes are ["123", "456", "789"] (All ECMO codes)
return patientCodes.length > 0 && patientCodes.every((code) => subProcedure.codes.includes(code));
}
// Otherwise, check if the patient has at least one of both the main procedure and the sub-procedure codes
// (Example: At least one from both "ECMO" codes & "CABG" codes)
return (
procedure.codes.some((code) => patientCodes.includes(code))
&& subProcedure.codes.some((code) => patientCodes.includes(code))
);
});
}

// Main procedure selected
// Only the Main procedure selected: Check if the patient has at least one of the main procedure codes
return procedure.codes.some((code) => patientCodes.includes(code));
});
if (procedureFiltered) {
Expand All @@ -134,6 +147,8 @@

return true;
});
console.log('Filtered cases:', cases);

Check failure on line 150 in frontend/src/Interfaces/Store.ts

View workflow job for this annotation

GitHub Actions / Push Docker image to Docker Hub

Unexpected console statement
return cases;
}

get filterRange() {
Expand Down
Loading