Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: add thresholds to variable model #584

Merged
merged 1 commit into from
Nov 25, 2024
Merged
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
12 changes: 0 additions & 12 deletions frontend-v2/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,27 +17,15 @@ import "react-toastify/dist/ReactToastify.css";
import { SimulationContext } from "./contexts/SimulationContext";
import { SimulateResponse } from "./app/backendApi";
import { CollapsibleSidebarProvider } from "./shared/contexts/CollapsibleSidebarContext";
import { useModelTimeIntervals } from "./hooks/useModelTimeIntervals";

type Threshold = { lower: number; upper: number };
export type Thresholds = { [key: string]: Threshold };

const THRESHOLDS: Thresholds = {};

function App() {
const dispatch = useAppDispatch();
const isAuth = useSelector(isAuthenticated);
const error = useSelector((state: RootState) => state.login.error);
const [intervals, setIntervals] = useModelTimeIntervals();
const [simulations, setSimulations] = useState<SimulateResponse[]>([]);
const [thresholds, setThresholds] = useState<Thresholds>(THRESHOLDS);
const simulationContext = {
simulations,
setSimulations,
intervals,
setIntervals,
thresholds,
setThresholds,
};

const onLogin = (username: string, password: string) => {
Expand Down
16 changes: 16 additions & 0 deletions frontend-v2/src/app/backendApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3507,6 +3507,10 @@ export type Variable = {
upper_bound?: number | null;
/** default value for this variable */
default_value?: number;
/** lower threshold for this variable */
lower_threshold?: number | null;
/** upper threshold for this variable */
upper_threshold?: number | null;
/** True if default_value is stored as the log of this value */
is_log?: boolean;
/** name of the variable */
Expand Down Expand Up @@ -3553,6 +3557,10 @@ export type VariableRead = {
upper_bound?: number | null;
/** default value for this variable */
default_value?: number;
/** lower threshold for this variable */
lower_threshold?: number | null;
/** upper threshold for this variable */
upper_threshold?: number | null;
/** True if default_value is stored as the log of this value */
is_log?: boolean;
/** name of the variable */
Expand Down Expand Up @@ -3598,6 +3606,10 @@ export type PatchedVariable = {
upper_bound?: number | null;
/** default value for this variable */
default_value?: number;
/** lower threshold for this variable */
lower_threshold?: number | null;
/** upper threshold for this variable */
upper_threshold?: number | null;
/** True if default_value is stored as the log of this value */
is_log?: boolean;
/** name of the variable */
Expand Down Expand Up @@ -3644,6 +3656,10 @@ export type PatchedVariableRead = {
upper_bound?: number | null;
/** default value for this variable */
default_value?: number;
/** lower threshold for this variable */
lower_threshold?: number | null;
/** upper threshold for this variable */
upper_threshold?: number | null;
/** True if default_value is stored as the log of this value */
is_log?: boolean;
/** name of the variable */
Expand Down
5 changes: 1 addition & 4 deletions frontend-v2/src/contexts/SimulationContext.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,7 @@
import { createContext } from "react";
import { SimulateResponse, TimeIntervalRead } from "../app/backendApi";
import { Thresholds } from "../App";
import { SimulateResponse } from "../app/backendApi";

export const SimulationContext = createContext({
simulations: [] as SimulateResponse[],
setSimulations: (simulations: SimulateResponse[]) => {},
thresholds: {} as Thresholds,
setThresholds: (thresholds: Thresholds) => {},
});
14 changes: 1 addition & 13 deletions frontend-v2/src/features/model/VariableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// src/components/ProjectTable.tsx
import { FC, useEffect, useContext } from "react";
import { FC, useEffect } from "react";
import { Control, useFieldArray, useForm } from "react-hook-form";
import {
TableCell,
Expand All @@ -25,7 +25,6 @@ import { useSelector } from "react-redux";
import { RootState } from "../../app/store";
import { selectIsProjectShared } from "../login/loginSlice";
import useEditProtocol from "./useEditProtocol";
import { SimulationContext } from "../../contexts/SimulationContext";

interface Props {
project: ProjectRead;
Expand Down Expand Up @@ -80,7 +79,6 @@ const VariableRow: FC<Props> = ({
control,
name: "model.derived_variables",
});
const { thresholds, setThresholds } = useContext(SimulationContext);

const {
handleSubmit,
Expand Down Expand Up @@ -246,16 +244,6 @@ const VariableRow: FC<Props> = ({
pkpd_model: model.id,
type,
});

if (type === "AUC") {
setThresholds({
...thresholds,
[variable.name]: {
lower: 0,
upper: Infinity,
},
});
}
};

const removeDerived = (index: number | number[]) => {
Expand Down
32 changes: 15 additions & 17 deletions frontend-v2/src/features/model/secondary/ThresholdsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChangeEvent, FC, useContext, useState } from "react";
import { ChangeEvent, FC, useState } from "react";
import {
MenuItem,
Select,
Expand All @@ -21,9 +21,9 @@ import {
useProjectRetrieveQuery,
useUnitListQuery,
useVariableListQuery,
useVariableUpdateMutation,
VariableRead,
} from "../../../app/backendApi";
import { SimulationContext } from "../../../contexts/SimulationContext";

function VariableRow({
variable,
Expand All @@ -32,32 +32,30 @@ function VariableRow({
variable: VariableRead;
unit: UnitRead | undefined;
}) {
const { thresholds, setThresholds } = useContext(SimulationContext);
const [updateVariable] = useVariableUpdateMutation();
const [unitSymbol, setUnitSymbol] = useState<string | undefined>(
unit?.symbol,
);
function onChangeLowerThreshold(event: ChangeEvent<HTMLInputElement>) {
const newValue = parseFloat(event.target.value);
const oldThresholds = thresholds[variable.name];
if (!isNaN(newValue)) {
setThresholds({
...thresholds,
[variable.name]: {
...oldThresholds,
lower: newValue,
updateVariable({
id: variable.id,
variable: {
...variable,
lower_threshold: newValue,
},
});
}
}
function onChangeUpperThreshold(event: ChangeEvent<HTMLInputElement>) {
const newValue = parseFloat(event.target.value);
const oldThresholds = thresholds[variable.name];
if (!isNaN(newValue)) {
setThresholds({
...thresholds,
[variable.name]: {
...oldThresholds,
upper: newValue,
updateVariable({
id: variable.id,
variable: {
...variable,
upper_threshold: newValue,
},
});
}
Expand All @@ -76,14 +74,14 @@ function VariableRow({
<TableCell>
<TextField
type="number"
defaultValue={thresholds[variable.name]?.lower}
defaultValue={variable.lower_threshold || 0}
onChange={onChangeLowerThreshold}
/>
</TableCell>
<TableCell>
<TextField
type="number"
defaultValue={thresholds[variable.name]?.upper}
defaultValue={variable.upper_threshold || Infinity}
onChange={onChangeUpperThreshold}
/>
</TableCell>
Expand Down
27 changes: 4 additions & 23 deletions frontend-v2/src/features/results/useParameters.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { useContext } from "react";

import {
SimulateResponse,
TimeIntervalRead,
Expand All @@ -11,9 +9,7 @@ import {
timesPerInterval,
valuesPerInterval,
} from "./utils";
import { SimulationContext } from "../../contexts/SimulationContext";
import { useVariables } from "./useVariables";
import { Thresholds } from "../../App";
import { useModelTimeIntervals } from "../../hooks/useModelTimeIntervals";
import { useUnits } from "./useUnits";

Expand Down Expand Up @@ -66,32 +62,21 @@ const timeOverLowerThresholdPerInterval = (
intervalValues: number[],
intervalTimes: number[],
variable: VariableRead,
thresholds: Thresholds,
) => {
const threshold = variable && thresholds[variable.name];
return timeOverThreshold(
intervalTimes,
intervalValues,
threshold?.lower || 0,
);
const threshold = variable?.lower_threshold || 0;
return timeOverThreshold(intervalTimes, intervalValues, threshold);
};

const timeOverUpperThresholdPerInterval = (
intervalValues: number[],
intervalTimes: number[],
variable: VariableRead,
thresholds: Thresholds,
) => {
const threshold = variable && thresholds[variable.name];
return timeOverThreshold(
intervalTimes,
intervalValues,
threshold?.upper || Infinity,
);
const threshold = variable?.upper_threshold || Infinity;
return timeOverThreshold(intervalTimes, intervalValues, threshold);
};

export function useParameters() {
const { thresholds } = useContext(SimulationContext);
const [baseIntervals] = useModelTimeIntervals();
const variables = useVariables();
const intervals = useNormalisedIntervals(baseIntervals);
Expand Down Expand Up @@ -176,7 +161,6 @@ export function useParameters() {
intervalValues,
intervalTimes,
variable,
thresholds,
),
)
: 0;
Expand Down Expand Up @@ -205,7 +189,6 @@ export function useParameters() {
intervalValues,
intervalTimes,
variable,
thresholds,
),
)
: 0;
Expand Down Expand Up @@ -234,13 +217,11 @@ export function useParameters() {
intervalValues,
intervalTimes,
variable,
thresholds,
) -
timeOverUpperThresholdPerInterval(
intervalValues,
intervalTimes,
variable,
thresholds,
),
)
: 0;
Expand Down
36 changes: 36 additions & 0 deletions pkpdapp/pkpdapp/migrations/0017_auto_20241125_1415.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
#
# This file is part of PKPDApp (https://github.com/pkpdapp-team/pkpdapp) which
# is released under the BSD 3-clause license. See accompanying LICENSE.md for
# copyright notice and full license details.
#
# Generated by Django 3.2.25 on 2024-11-25 14:15

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('pkpdapp', '0016_auto_20241122_1523'),
]

operations = [
migrations.AddField(
model_name='variable',
name='lower_threshold',
field=models.FloatField(
blank=True,
help_text='lower threshold for this variable',
null=True
),
),
migrations.AddField(
model_name='variable',
name='upper_threshold',
field=models.FloatField(
blank=True,
help_text='upper threshold for this variable',
null=True
),
),
]
8 changes: 8 additions & 0 deletions pkpdapp/pkpdapp/models/variable.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,12 @@ class Variable(StoredModel):
default_value = models.FloatField(
default=1, help_text="default value for this variable"
)
lower_threshold = models.FloatField(
blank=True, null=True, help_text="lower threshold for this variable"
)
upper_threshold = models.FloatField(
blank=True, null=True, help_text="upper threshold for this variable"
)

is_log = models.BooleanField(
default=False,
Expand Down Expand Up @@ -411,4 +417,6 @@ def copy(self, variable, new_project):
self.unit_symbol = variable.unit_symbol
self.constant = variable.constant
self.protocol = new_protocol
self.lower_threshold = variable.lower_threshold
self.upper_threshold = variable.upper_threshold
self.save()
20 changes: 20 additions & 0 deletions pkpdapp/schema.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4847,6 +4847,16 @@ components:
type: number
format: double
description: default value for this variable
lower_threshold:
type: number
format: double
nullable: true
description: lower threshold for this variable
upper_threshold:
type: number
format: double
nullable: true
description: upper threshold for this variable
is_log:
type: boolean
description: True if default_value is stored as the log of this value
Expand Down Expand Up @@ -5656,6 +5666,16 @@ components:
type: number
format: double
description: default value for this variable
lower_threshold:
type: number
format: double
nullable: true
description: lower threshold for this variable
upper_threshold:
type: number
format: double
nullable: true
description: upper threshold for this variable
is_log:
type: boolean
description: True if default_value is stored as the log of this value
Expand Down