Skip to content

Commit

Permalink
refactor: Update MayoVsPROPKDChart component and Mayo score calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
berntpopp committed Sep 8, 2024
1 parent c3b1641 commit e111d11
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 34 deletions.
64 changes: 44 additions & 20 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,31 @@

<v-main>
<v-container>
<v-alert v-if="errorMessage" type="error" outlined class="mb-3">
{{ errorMessage }}
</v-alert>

<!-- Step 1: Patient Information Section -->
<v-row>
<v-col cols="12" md="12">
<v-card outlined class="pa-1 mb-2">
<v-card-title>
<v-icon class="mr-2">mdi-numeric-1-circle-outline</v-icon>
<v-icon :color="isStep1Valid ? 'green' : 'red'" class="mr-2">mdi-numeric-1-circle-outline</v-icon>
Patient Information
</v-card-title>
<v-card-text class="pa-1">
<v-row dense>
<v-col cols="12" sm="2" md="2">
<v-text-field v-model="patientId" label="Patient ID" dense outlined density="compact" />
<v-text-field v-model="patientId" label="Patient ID" required dense outlined density="compact" />
</v-col>
<v-col cols="12" sm="2" md="2">
<v-text-field v-model="age" label="Age" type="number" :min="20" :max="80" dense outlined density="compact" />
<v-text-field v-model="age" label="Age" type="number" :min="20" :max="80" required dense outlined density="compact" />
</v-col>
<v-col cols="12" sm="2" md="2">
<v-text-field v-model="height" label="Height (m)" type="number" step="0.01" min="1" dense outlined density="compact" />
<v-text-field v-model="height" label="Height (m)" type="number" step="0.01" min="1" required dense outlined density="compact" />
</v-col>
<v-col cols="12" sm="2" md="2">
<v-select v-model="sex" :items="['Male', 'Female']" label="Sex" dense outlined density="compact" />
<v-select v-model="sex" :items="['Male', 'Female']" label="Sex" required dense outlined density="compact" />
</v-col>
<v-col cols="12" sm="2" md="2">
<v-select v-model="familyHistory" :items="['Positive', 'Negative']" label="Family History" dense outlined density="compact" />
Expand All @@ -60,10 +64,8 @@
<!-- Mayo Score Section -->
<v-card class="equal-height-card pa-1 mb-2" outlined>
<v-card-title class="d-flex justify-space-between align-center">
<span>
<v-icon class="mr-2">mdi-numeric-2-circle-outline</v-icon>
Mayo Score
</span>
<v-icon :color="isMayoScoreCalculated ? 'green' : 'red'" class="mr-2">mdi-numeric-2-circle-outline</v-icon>
Mayo Score
<v-select
v-model="inputMethod"
:items="['Ellipsoid Equation', 'Stereology Method']"
Expand Down Expand Up @@ -110,10 +112,8 @@
<!-- PROPKD Score Section -->
<v-card class="small-card pa-1" outlined>
<v-card-title class="d-flex justify-space-between">
<span>
<v-icon class="mr-2">mdi-numeric-3-circle-outline</v-icon>
PROPKD Score
</span>
<v-icon :color="isPROPKDScoreCalculated ? 'green' : 'red'" class="mr-2">mdi-numeric-3-circle-outline</v-icon>
PROPKD Score
<v-btn small color="primary" @click="calculatePROPKDScore" density="compact">Calculate</v-btn>
</v-card-title>
<v-card-text class="pa-1">
Expand Down Expand Up @@ -226,8 +226,20 @@ export default {
mayoScore: 1, // Set a default valid score
propkdScore: 0,
mayoClass: 'low',
errorMessage: null, // To display validation errors
};
},
computed: {
isStep1Valid() {
return this.patientId && this.age && this.height && this.sex;
},
isMayoScoreCalculated() {
return this.mayoScore > 1;
},
isPROPKDScoreCalculated() {
return this.propkdScore > 0;
},
},
methods: {
toggleTheme() {
this.isDark = !this.isDark;
Expand All @@ -238,9 +250,16 @@ export default {
if (volume < 359.484) return 'high';
return 'very high';
},
validateStep1() {
if (!this.isStep1Valid) {
this.errorMessage = 'Please fill in all required fields in Step 1: Patient ID, Age, Height, and Sex.';
return false;
}
this.errorMessage = null; // Clear error message if valid
return true;
},
calculateHtTKV() {
if (!this.age || !this.height || this.height <= 0) {
alert('Please enter a valid age and height.');
if (!this.validateStep1()) {
return;
}
Expand All @@ -257,7 +276,7 @@ export default {
!this.kidneyLeft.width ||
!this.kidneyLeft.depth
) {
alert('Please enter valid kidney dimensions.');
this.errorMessage = 'Please enter valid kidney dimensions for both kidneys.';
return;
}
Expand All @@ -274,17 +293,15 @@ export default {
totalVolume = rightKidneyVolume + leftKidneyVolume;
} else {
if (!this.kidneyVolume || this.kidneyVolume <= 0) {
alert('Please enter a valid kidney volume.');
this.errorMessage = 'Please enter a valid total kidney volume.';
return;
}
totalVolume = this.kidneyVolume;
}
const htAdjustedTKV = totalVolume / this.height;
// Clamp the Mayo score to ensure it's within the valid range (1 to 5)
this.mayoClass = this.getMayoClass(htAdjustedTKV);
this.mayoScore = Math.min(Math.max(htAdjustedTKV, 1), 5); // Ensure Mayo Score is between 1 and 5
this.mayoScore = Math.min(Math.max(htAdjustedTKV, 1), 5); // Ensure Mayo Score is between 1 and 5
const newDataPoint = { x: this.age, y: htAdjustedTKV, patientId: this.patientId, mayoClass: this.mayoClass };
Expand All @@ -297,15 +314,22 @@ export default {
];
this.chartData = newChartData;
this.errorMessage = null; // Clear error message after successful calculation
},
calculatePROPKDScore() {
if (!this.sex || !this.mutationClass) {
this.errorMessage = 'Sex and Mutation Class are required to calculate PROPKD Score.';
return;
}
const sexScore = this.sex === 'Male' ? 1 : 0;
const mutationScore = this.mutationClass === 'PKD2 mutation' ? 0 :
this.mutationClass === 'Nontruncating PKD1 mutation' ? 2 : 4;
const hypertensionScore = this.hypertension ? 2 : 0;
const urologicalEventScore = this.firstUrologicalEvent ? 2 : 0;
this.propkdScore = Number(sexScore + mutationScore + hypertensionScore + urologicalEventScore) || 0;
this.errorMessage = null; // Clear error message after successful calculation
},
},
};
Expand Down
45 changes: 31 additions & 14 deletions src/components/MayoVsPROPKDChart.vue
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export default {
// Mapping Mayo and PROPKD scores to risk categories
const mayoToRisk = (mayoScore) => {
console.log('Converting Mayo Score:', mayoScore); // Debug
if (typeof mayoScore !== 'number' || mayoScore < 1 || mayoScore > 5) {
console.warn('Invalid Mayo Score:', mayoScore);
mayoScore = 1; // Default to low risk if invalid
Expand All @@ -54,6 +55,7 @@ export default {
};
const propkdToRisk = (propkdScore) => {
console.log('Converting PROPKD Score:', propkdScore); // Debug
if (typeof propkdScore !== 'number' || propkdScore < 0 || propkdScore > 9) {
console.warn('Invalid PROPKD Score:', propkdScore);
propkdScore = 0; // Default to low risk if invalid
Expand All @@ -65,11 +67,19 @@ export default {
// Create the chart
const createChart = () => {
if (!canvas.value) {
console.error('Canvas element is not available'); // Debug
return;
}
const ctx = canvas.value.getContext('2d');
console.log('Mayo Score:', props.mayoScore, 'PROPKD Score:', props.propkdScore); // Debug
const mayoRisk = mayoToRisk(props.mayoScore);
const propkdRisk = propkdToRisk(props.propkdScore);
console.log('Mayo Risk:', mayoRisk, 'PROPKD Risk:', propkdRisk); // Debug
const getPatientCoords = (mayoRisk, propkdRisk) => {
const xMap = { low: 1, intermediate: 2, high: 3 };
const yMap = { low: 1, intermediate: 2, high: 3 };
Expand All @@ -78,7 +88,8 @@ export default {
const patientCoords = getPatientCoords(mayoRisk, propkdRisk);
// Plugin to draw the colored background
console.log('Patient Coordinates:', patientCoords); // Debug
const backgroundPlugin = {
id: 'backgroundPlugin',
beforeDraw: (chart) => {
Expand Down Expand Up @@ -107,6 +118,10 @@ export default {
}
};
if (chartInstance) {
chartInstance.destroy(); // Destroy previous chart instance
}
chartInstance = new ChartJS(ctx, {
type: 'scatter',
data: {
Expand All @@ -122,7 +137,8 @@ export default {
},
options: {
responsive: true,
maintainAspectRatio: false, // Ensures square plot
maintainAspectRatio: true, // Keep aspect ratio intact
aspectRatio: 1, // Ensure the chart is square
scales: {
x: {
type: 'linear',
Expand Down Expand Up @@ -170,31 +186,32 @@ export default {
});
};
// Resize chart on window resize
const resizeChart = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// Watch for changes in props and update chart
watch(
() => [props.mayoScore, props.propkdScore],
() => {
if (chartInstance) {
chartInstance.destroy();
}
console.log('Props changed:', { mayoScore: props.mayoScore, propkdScore: props.propkdScore }); // Debug
createChart();
}
);
// Resize chart on window resize
const resizeChart = () => {
if (chartInstance) {
chartInstance.resize();
}
};
onMounted(() => {
createChart();
window.addEventListener('resize', resizeChart);
});
onBeforeUnmount(() => {
window.removeEventListener('resize', resizeChart);
if (chartInstance) {
chartInstance.destroy(); // Cleanup chart on unmount
}
});
return {
Expand All @@ -206,8 +223,8 @@ export default {

<style scoped>
canvas {
max-width: 500px;
height: 500px;
width: 70% !important;
height: 70% !important;
margin: 0 auto;
}
</style>

0 comments on commit e111d11

Please sign in to comment.