def get_clinical_text(self): if not self.is_complete(): return CTV_DICTLIST_INCOMPLETE return [{ "content": u"BMI: {} kg⋅m<sup>–2</sup> [{}]. Mass: {} kg. " "Height: {} m.".format( ws.number_to_dp(self.bmi(), BMI_DP), self.category(), ws.number_to_dp(self.mass_kg, KG_DP), ws.number_to_dp(self.height_m, M_DP) ) }]
def get_clinical_text(self): if not self.is_complete(): return CTV_DICTLIST_INCOMPLETE tto_qol = self.get_tto_qol() rs_qol = self.get_rs_qol() mean_qol = mean([tto_qol, rs_qol]) return [{ "content": u"Quality of life: time trade-off {}, rating scale {}," " mean {}.".format( ws.number_to_dp(tto_qol, DP), ws.number_to_dp(rs_qol, DP), ws.number_to_dp(mean_qol, DP) ) }]
def get_clinical_text(self): if not self.is_complete(): return CTV_DICTLIST_INCOMPLETE return [{ "content": u"Quality of life: {}".format( ws.number_to_dp(self.utility, DP)) }]
def get_task_html(self): h = u""" <div class="summary"> <table class="summary"> """ + self.get_is_complete_tr() h += tr_qa("Utility", ws.number_to_dp(self.utility, DP, default=None)) h += u""" </table> </div> <div class="explanation"> Quality of life (QoL) has anchor values of 0 (none) and 1 (perfect health). The Standard Gamble offers a trade-off to determine utility (QoL). Values <0 and >1 are possible with some gambles. </div> <table class="taskdetail"> <tr><th width="50%">Measure</th><th width="50%">Value</th></tr> """ h += tr_qa("Category choice: start time", self.category_start_time) h += tr_qa("Category choice: responded?", get_yes_no_none(self.category_responded)) h += tr_qa("Category choice: response time", self.category_response_time) h += tr_qa("Category choice: category chosen", self.category_chosen) h += tr_qa("Gamble: fixed option", self.gamble_fixed_option) h += tr_qa("Gamble: lottery option for <i>p</i>", self.gamble_lottery_option_p) h += tr_qa(u"Gamble: lottery option for <i>q</i> = 1 – <i>p</i>", self.gamble_lottery_option_q) h += tr_qa("Gamble: lottery on left?", get_yes_no_none(self.gamble_lottery_on_left)) h += tr_qa("Gamble: starting <i>p</i>", self.gamble_starting_p) h += tr_qa("Gamble: start time", self.gamble_start_time) h += tr_qa("Gamble: responded?", get_yes_no_none(self.gamble_responded)) h += tr_qa("Gamble: response time", self.gamble_response_time) h += tr_qa("Gamble: <i>p</i>", ws.number_to_dp(self.gamble_p, DP, default=None)) h += tr_qa("Calculated utility", ws.number_to_dp(self.utility, DP, default=None)) h += u""" </table> """ return h
def get_task_html(self): tto_qol = self.get_tto_qol() rs_qol = self.get_rs_qol() mean_qol = mean([tto_qol, rs_qol]) h = u""" <div class="summary"> <table class="summary"> """ h += self.get_is_complete_tr() h += tr("Mean QoL", answer(ws.number_to_dp(mean_qol, DP, default=None), formatter_answer=identity)) h += u""" </table> </div> <div class="explanation"> Quality of life (QoL) has anchor values of 0 (none) and 1 (perfect health), and can be asked about in several ways. </div> <table class="taskdetail"> <tr> <th width="33%">Scale</th> <th width="33%">Answer</th> <td width="33%">Implied QoL</th> </tr> """ h += tr(WSTRING("qolbasic_tto_q_s"), answer(ws.number_to_dp(self.tto, DP, default=None)), answer(ws.number_to_dp(tto_qol, DP, default=None), formatter_answer=identity)) h += tr(WSTRING("qolbasic_rs_q_s"), answer(ws.number_to_dp(self.rs, DP, default=None)), answer(ws.number_to_dp(rs_qol, DP, default=None), formatter_answer=identity)) h += u""" </table> """ return h
def get_html_table_row(self): return (u"<tr>" + u"<td>{}</td>" * 13 + u"</th>").format( self.trial, self.trial_ignoring_catch_trials, self.target_presented, self.target_time, ws.number_to_dp(self.intensity, DP), self.choice_time, self.responded, self.response_time, self.response_latency_ms, self.yes, self.no, ws.webify(self.caught_out_reset), ws.webify(self.trial_num_in_calculation_sequence) )
def get_task_html(self): h = u""" <div class="summary"> <table class="summary"> {iscomplete} </table> <table class="summary"> <tr> <th>Domain (with score range)</th> <th>Frequency (total score)</th> <th>Distress (total score)</th> </tr> """.format(iscomplete=self.get_is_complete_tr()) h += tr( u"Overall <sup>[1]</sup> ({low}–{high})".format( low=ALL_MIN, high=ALL_MAX), self.frequency_score(ALL), self.distress_score(ALL)) h += tr( u"Positive symptoms ({low}–{high})".format( low=POS_MIN, high=POS_MAX), self.frequency_score(POSITIVE), self.distress_score(POSITIVE)) h += tr( u"Negative symptoms ({low}–{high})".format( low=NEG_MIN, high=NEG_MAX), self.frequency_score(NEGATIVE), self.distress_score(NEGATIVE)) h += tr( u"Depressive symptoms ({low}–{high})".format( low=DEP_MIN, high=DEP_MAX), self.frequency_score(DEPRESSIVE), self.distress_score(DEPRESSIVE)) h += u""" </table> <table class="summary"> <tr> <th>Domain</th> <th>Weighted frequency score <sup>[3]</sup></th> <th>Weighted distress score <sup>[3]</sup></th> </tr> """ h += tr("Overall ({n} questions)".format(n=len(ALL)), ws.number_to_dp(self.weighted_frequency_score(ALL), DP), ws.number_to_dp(self.weighted_distress_score(ALL), DP)) h += tr("Positive symptoms ({n} questions)".format(n=len(POSITIVE)), ws.number_to_dp(self.weighted_frequency_score(POSITIVE), DP), ws.number_to_dp(self.weighted_distress_score(POSITIVE), DP)) h += tr("Negative symptoms ({n} questions)".format(n=len(NEGATIVE)), ws.number_to_dp(self.weighted_frequency_score(NEGATIVE), DP), ws.number_to_dp(self.weighted_distress_score(NEGATIVE), DP)) h += tr( "Depressive symptoms ({n} questions)".format(n=len(DEPRESSIVE)), ws.number_to_dp(self.weighted_frequency_score(DEPRESSIVE), DP), ws.number_to_dp(self.weighted_distress_score(DEPRESSIVE), DP)) h += u""" </table> </div> <div class="explanation"> FREQUENCY: 1 {f1}, 2 {f2}, 3 {f3}, 4 {f4}. DISTRESS: 1 {d1}, 2 {d2}, 3 {d3}, 4 {d4}. </div> <table class="taskdetail"> <tr> <th width="70%"> Question (P positive, N negative, D depressive) </th> <th width="15%">Frequency ({low}–{high})</th> <th width="15%">Distress ({low}–{high}) <sup>[2]</sup></th> </tr> """.format( f1=WSTRING("cape42_frequency_option1"), f2=WSTRING("cape42_frequency_option2"), f3=WSTRING("cape42_frequency_option3"), f4=WSTRING("cape42_frequency_option4"), d1=WSTRING("cape42_distress_option1"), d2=WSTRING("cape42_distress_option2"), d3=WSTRING("cape42_distress_option3"), d4=WSTRING("cape42_distress_option4"), low=MIN_SCORE_PER_Q, high=MAX_SCORE_PER_Q, ) for q in ALL: h += tr( u"{q}. ".format(q=q) + WSTRING("cape42_q" + str(q)) + u" (<i>" + self.question_category(q) + "</i>)", answer(self.get_frequency(q)), answer( self.get_distress_score(q) if self.endorsed(q) else None, default=str(MIN_SCORE_PER_Q)) ) h += u""" </table> <div class="footnotes"> [1] “Total” score is the overall frequency score (the sum of frequency scores for all questions). [2] Distress coerced to 1 if frequency is 1. [3] Sum score per dimension divided by number of completed items. Shown to {dp} decimal places. Will be in the range {low}–{high}, or blank if not calculable. </div> """.format( low=MIN_SCORE_PER_Q, high=MAX_SCORE_PER_Q, dp=DP, ) return h
def get_task_html(self): if self.modality == MODALITY_AUDITORY: modality = WSTRING("auditory") elif self.modality == MODALITY_VISUAL: modality = WSTRING("visual") else: modality = None h = u""" <div class="summary"> <table class="summary"> {} </table> </div> <div class="explanation"> The ExpDet-Threshold task measures visual and auditory thresholds for stimuli on a noisy background, using a single-interval up/down method. It is intended as a prequel to the Expectation–Detection task. </div> <table class="taskconfig"> <tr> <th width="50%">Configuration variable</th> <th width="50%">Value</th> </tr> """.format( self.get_is_complete_tr(), ) h += tr_qa("Modality", modality) h += tr_qa("Target number", self.target_number) h += tr_qa("Background filename", ws.webify(self.background_filename)) h += tr_qa("Background intensity", self.background_intensity) h += tr_qa("Target filename", ws.webify(self.target_filename)) h += tr_qa("(For visual targets) Target duration (s)", self.visual_target_duration_s) h += tr_qa("Start intensity (minimum)", self.start_intensity_min) h += tr_qa("Start intensity (maximum)", self.start_intensity_max) h += tr_qa("Initial (large) intensity step", self.initial_large_intensity_step) h += tr_qa("Main (small) intensity step", self.main_small_intensity_step) h += tr_qa("Number of trials in main sequence", self.num_trials_in_main_sequence) h += tr_qa("Probability of a catch trial", self.p_catch_trial) h += tr_qa("Prompt", self.prompt) h += tr_qa("Intertrial interval (ITI) (s)", self.iti_s) h += u""" </table> <table class="taskdetail"> <tr><th width="50%">Measure</th><th width="50%">Value</th></tr> """ h += tr_qa("Finished?", get_yes_no_none(self.finished)) h += tr_qa("Logistic intercept", ws.number_to_dp(self.intercept, DP)) h += tr_qa("Logistic slope", ws.number_to_dp(self.slope, DP)) h += tr_qa("Logistic k (= slope)", ws.number_to_dp(self.k, DP)) h += tr_qa(u"Logistic theta (= –intercept/slope)", ws.number_to_dp(self.theta, DP)) h += tr_qa("Intensity for {}% detection".format(100*LOWER_MARKER), ws.number_to_dp(self.logistic_x_from_p(LOWER_MARKER), DP)) h += tr_qa("Intensity for 50% detection", ws.number_to_dp(self.theta, DP)) h += tr_qa("Intensity for {}% detection".format(100*UPPER_MARKER), ws.number_to_dp(self.logistic_x_from_p(UPPER_MARKER), DP)) h += u""" </table> """ h += self.get_trial_html() return h
def get_task_html(self): h = u""" <div class="summary"> <table class="summary"> """ h += self.get_is_complete_tr() h += tr_qa("BMI (kg/m<sup>2</sup>)", ws.number_to_dp(self.bmi(), BMI_DP)) h += tr_qa("Category <sup>[1]</sup>", self.category()) h += u""" </table> </div> <table class="taskdetail"> """ h += tr_qa("Mass (kg)", ws.number_to_dp(self.mass_kg, KG_DP)) h += tr_qa("Height (m)", ws.number_to_dp(self.height_m, M_DP)) h += tr_qa("Comment", ws.webify(self.comment)) h += u""" </table> <div class="footnotes"> [1] Categorization <b>for adults</b> (square brackets inclusive, parentheses exclusive; AN anorexia nervosa): <13 very severely underweight (WHO grade 3; RCPsych severe AN, high risk); [13, 15] very severely underweight (WHO grade 3; RCPsych severe AN, medium risk); [15, 16) severely underweight (WHO grade 3; AN); [16, 17) underweight (WHO grade 2; AN); [17, 17.5) underweight (WHO grade 1; below ICD-10/RCPsych AN cutoff); [17.5, 18.5) underweight (WHO grade 1); [18.5, 25) normal (healthy weight); [25, 30) overweight; [30, 35) obese class I (moderately obese); [35, 40) obese class II (severely obese); ≥40 obese class III (very severely obese). Sources: <ul> <li>WHO Expert Committee on Physical Status (1995, PMID 8594834) defined ranges as: <16 grade 3 thinness, [16, 17) grade 2 thinness, [17, 18.5) grade 1 thinness, [18.5, 25) normal, [25, 30) grade 1 overweight, [30, 40) grade 2 overweight, ≥40 grade 3 overweight (sections 7.2.1 and 8.7.1 and p452).</li> <li>WHO (1998 “Obesity: preventing and managing the global epidemic”) use the categories [25, 30) “pre-obese”, [30, 35) obese class I, [35, 40) obese class II, ≥40 obese class III (p9).</li> <li>A large number of web sources that don’t cite a primary reference use: <15 very severely underweight; [15, 16) severely underweight; [16, 18.5) underweight; [18.5, 25] normal (healthy weight); [25, 30) obese class I (moderately obese); [35, 40) obese class II (severely obese); ≥40 obese class III (very severely obese); <li>The WHO (2010 “Nutrition Landscape Information System (NILS) country profile indicators: interpretation guide”) use <16 “severe thinness” (previously grade 3 thinness), (16, 17] “moderate thinness” (previously grade 2 thinness), [17, 18.5) “underweight” (previously grade 1 thinness). (p3).</li> <li>ICD-10 BMI threshold for anorexia nervosa is ≤17.5 (WHO, 1992). Subsequent references (e.g. RCPsych, below) use <17.5.</li> <li>In anorexia nervosa: <17.5 anorexia (threshold for diagnosis), <15 severe anorexia; 13–15 medium risk, <13 high risk (of death) (Royal College of Psychiatrists, 2010, report CR162, pp. 11, 15, 20, 56).</li> </ul> </div> """ return h