"""Functionalities to process neuroqol data."""
from typing import List, Tuple, Type
import pandas as pd
from dispel.data.levels import Level
from dispel.data.measures import MeasureValue, MeasureValueDefinitionPrototype
from dispel.data.raw import RawDataSet, RawDataSetDefinition, RawDataValueDefinition
from dispel.data.validators import GREATER_THAN_ZERO
from dispel.data.values import AbbreviatedValue as AV
from dispel.data.values import ValueDefinition
from dispel.processing.core import ProcessingResult, ProcessingStep
from dispel.processing.data_set import transformation
from dispel.processing.extract import ExtractStep
from dispel.processing.level import ProcessingStepGroup
from dispel.providers.registry import process_factory
TASK_NAME = AV("NeuroQol Assessment", "neuroqol")
NEUROQOL_SUBTEST_NAME = [
"upper_extremity",
"lower_extremity",
"sleep",
"fatigue",
"anxiety",
"depression",
"stigma",
"cognitive_function",
"ability_participate_social_roles",
"satisfaction_social_roles",
]
r"""The name of the neuroqol sub tests."""
[docs]
def get_theta_scores(
levels: List[Level],
) -> Tuple[pd.DataFrame, List[Type[MeasureValue]]]:
"""Create a data frame with standard error theta and t scores."""
len_levels = len(levels)
theta_scores = [float] * len_levels
standard_errors = [float] * len_levels
level_names = [""] * len_levels
measure_values = [MeasureValue] * len_levels
# Enumerate through the levels to read the mobile_computed information
for it, level in enumerate(levels):
_id = str(level.id)
measure_id = f"mobile_computed_theta_score_{_id}"
level_names[it] = _id
measure_value = level.measure_set.get(measure_id)
measure_values[it] = measure_value # type: ignore
theta_scores[it] = measure_value.value
standard_errors[it] = level.measure_set.get_raw_value(
f"mobile_computed_standard_error_{_id}"
)
# Create a single dataframe with all the information
df = pd.DataFrame(
{
"level_name": level_names,
"theta_score": theta_scores,
"standard_error": standard_errors,
}
)
df["t_score"] = df["theta_score"] * 10 + 50
return df, measure_values
[docs]
class ListNeuroqolThetaScores(ProcessingStep):
"""Gather individual scores in the same data frame."""
[docs]
def process_reading(self, reading, **kwargs):
"""Gather theta scores."""
definitions = [
RawDataValueDefinition("level_name", "level name"),
RawDataValueDefinition("theta_score", "theta score"),
RawDataValueDefinition("standard_error", "standard error"),
RawDataValueDefinition("t_score", "T score"),
]
new_data_set_id = "theta_scores"
data, measure_values = get_theta_scores(reading.levels)
raw_data_sets = [
RawDataSet(
definition=RawDataSetDefinition(
id=new_data_set_id,
source=None,
value_definitions_list=definitions,
is_computed=True,
),
data=data,
)
]
yield ProcessingResult(
step=self,
sources=measure_values,
result=Level(
id_="all_levels",
start=reading.evaluation.start,
end=reading.evaluation.end,
raw_data_sets=raw_data_sets,
),
)
[docs]
class ExtractNeuroqolStandardError(ExtractNeuroqol):
"""Extract subset standard error."""
[docs]
@transformation
def get_standard_error(self, data: pd.DataFrame) -> float:
"""Get t_score."""
return float(data.loc[data.level_name == self.level_name].standard_error)
[docs]
def get_definition(self, **kwargs) -> ValueDefinition:
"""Overwrite get_definition."""
description = f"Standard Error for {self.level_name}."
return MeasureValueDefinitionPrototype(
measure_name=AV("Standard error", "standard_error"),
data_type="float",
validator=GREATER_THAN_ZERO,
description=description,
modalities=[AV(self.level_name)],
).create_definition(**kwargs)
EXTRACTION_STEPS: List[ProcessingStep] = []
for name in NEUROQOL_SUBTEST_NAME:
EXTRACTION_STEPS.append(ExtractNeuroqolTScore(name))
EXTRACTION_STEPS.append(ExtractNeuroqolStandardError(name))
STEPS: List[ProcessingStep] = [
# We filter on only one level to create the data set a single time
ListNeuroqolThetaScores(),
ProcessingStepGroup(
EXTRACTION_STEPS, level_filter="all_levels", task_name=TASK_NAME
),
]
process_neuroqol = process_factory(
task_name=TASK_NAME,
steps=STEPS,
codes="neuroqol-activity",
)