Coverage for tasks/deakin_s1_healthreview.py: 93%
126 statements
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
« prev ^ index » next coverage.py v6.5.0, created at 2022-11-08 23:14 +0000
1#!/usr/bin/env python
3"""
4camcops_server/tasks/deakin_s1_healthreview.py
6===============================================================================
8 Copyright (C) 2012, University of Cambridge, Department of Psychiatry.
9 Created by Rudolf Cardinal (rnc1001@cam.ac.uk).
11 This file is part of CamCOPS.
13 CamCOPS is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
18 CamCOPS is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with CamCOPS. If not, see <https://www.gnu.org/licenses/>.
26===============================================================================
28"""
30from sqlalchemy.sql.schema import Column
31from sqlalchemy.sql.sqltypes import Integer, String, Text, UnicodeText
33from camcops_server.cc_modules.cc_constants import CssClass
34from camcops_server.cc_modules.cc_html import tr_qa
35from camcops_server.cc_modules.cc_request import CamcopsRequest
36from camcops_server.cc_modules.cc_sqla_coltypes import (
37 BoolColumn,
38 CamcopsColumn,
39 MIN_ZERO_CHECKER,
40 PermittedValueChecker,
41 ZERO_TO_FOUR_CHECKER,
42)
43from camcops_server.cc_modules.cc_task import Task, TaskHasPatientMixin
46# =============================================================================
47# DeakinS1HealthReview
48# =============================================================================
50FREQUENCY_COMMENT = (
51 "Frequency (0 did not use, 1 occasionally, 2 monthly, 3 weekly, 4 daily)"
52)
55class DeakinS1HealthReview(TaskHasPatientMixin, Task):
56 """
57 Server implementation of the DeakinS1HealthReview task.
58 """
60 __tablename__ = "deakin_1_healthreview" # historically fixed
61 shortname = "Deakin_S1_HealthReview"
62 info_filename_stem = "deakin_s1_healthreview"
64 ethnicity = CamcopsColumn(
65 "ethnicity",
66 Integer,
67 permitted_value_checker=PermittedValueChecker(minimum=1, maximum=16),
68 comment="Ethnicity code, per GMC Patient Questionnaire (1-16)",
69 )
70 ethnicity_text = CamcopsColumn(
71 "ethnicity_text",
72 UnicodeText,
73 exempt_from_anonymisation=True,
74 comment="Ethnicity, description",
75 ) # Seems to be unused by the client!
76 ethnicity_other_details = Column(
77 "ethnicity_other_details",
78 UnicodeText,
79 comment="Ethnicity, other, details",
80 )
82 handedness = CamcopsColumn(
83 "handedness",
84 String(length=1), # was Text
85 permitted_value_checker=PermittedValueChecker(
86 permitted_values=["L", "R"]
87 ),
88 comment="Handedness (L, R)",
89 )
90 education = CamcopsColumn(
91 "education", Text, exempt_from_anonymisation=True
92 )
94 allergies = BoolColumn("allergies")
95 allergy_asthma = BoolColumn("allergy_asthma")
96 allergy_pollen_dust = BoolColumn("allergy_pollen_dust")
97 allergy_dermatitis = BoolColumn("allergy_dermatitis")
98 allergy_food = BoolColumn("allergy_food")
99 allergy_dander = BoolColumn("allergy_dander")
100 allergy_other = BoolColumn("allergy_other")
101 allergy_details = Column("allergy_details", Text)
103 vaccinations_last3months = BoolColumn("vaccinations_last3months")
104 vaccination_details = Column("vaccination_details", Text)
106 infections_last3months = BoolColumn("infections_last3months")
107 infection_recent_respiratory = BoolColumn("infection_recent_respiratory")
108 infection_recent_gastroenteritis = BoolColumn(
109 "infection_recent_gastroenteritis",
110 constraint_name="ck_deakin_1_healthreview_inf_recent_gastro",
111 )
112 infection_recent_urinary = BoolColumn("infection_recent_urinary")
113 infection_recent_sexual = BoolColumn("infection_recent_sexual")
114 infection_recent_hepatitis = BoolColumn("infection_recent_hepatitis")
115 infection_recent_other = BoolColumn("infection_recent_other")
116 infection_recent_details = Column("infection_recent_details", Text)
118 infections_chronic = BoolColumn("infections_chronic")
119 infection_chronic_respiratory = BoolColumn("infection_chronic_respiratory")
120 infection_chronic_gastroenteritis = BoolColumn(
121 "infection_chronic_gastroenteritis",
122 constraint_name="ck_deakin_1_healthreview_inf_chronic_gastro",
123 )
124 infection_chronic_urinary = BoolColumn("infection_chronic_urinary")
125 infection_chronic_sexual = BoolColumn("infection_chronic_sexual")
126 infection_chronic_hepatitis = BoolColumn("infection_chronic_hepatitis")
127 infection_chronic_other = BoolColumn("infection_chronic_other")
128 infection_chronic_details = Column("infection_chronic_details", Text)
130 immune_disorders = BoolColumn("immune_disorders")
131 immunity_ms = BoolColumn("immunity_ms")
132 immunity_sle = BoolColumn("immunity_sle")
133 immunity_arthritis = BoolColumn("immunity_arthritis")
134 immunity_hiv = BoolColumn("immunity_hiv")
135 immunity_graves = BoolColumn("immunity_graves")
136 immunity_diabetes = BoolColumn("immunity_diabetes")
137 immunity_other = BoolColumn("immunity_other")
138 immunity_details = Column("immunity_details", Text)
140 family_history = BoolColumn("family_history")
141 familyhistory_ms = BoolColumn("familyhistory_ms")
142 familyhistory_sle = BoolColumn("familyhistory_sle")
143 familyhistory_arthritis = BoolColumn("familyhistory_arthritis")
144 familyhistory_graves = BoolColumn("familyhistory_graves")
145 familyhistory_diabetes = BoolColumn("familyhistory_diabetes")
146 familyhistory_psychosis_sz = BoolColumn("familyhistory_psychosis_sz")
147 familyhistory_bipolar = BoolColumn("familyhistory_bipolar")
148 familyhistory_details = Column("familyhistory_details", Text)
150 health_anything_else = BoolColumn("health_anything_else")
151 health_anything_else_details = Column(
152 "health_anything_else_details", UnicodeText
153 )
155 drug_history = Column("drug_history", UnicodeText)
156 first_antipsychotic_medication = Column(
157 "first_antipsychotic_medication", UnicodeText
158 )
160 recreational_drug_in_last_3_months = BoolColumn(
161 "recreational_drug_in_last_3_months",
162 constraint_name="ck_deakin_1_healthreview_recdruglast3mo",
163 )
165 recdrug_tobacco_frequency = CamcopsColumn(
166 "recdrug_tobacco_frequency",
167 Integer,
168 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
169 comment=FREQUENCY_COMMENT,
170 )
171 recdrug_tobacco_cigsperweek = CamcopsColumn(
172 "recdrug_tobacco_cigsperweek",
173 Integer,
174 permitted_value_checker=MIN_ZERO_CHECKER,
175 comment="Tobacco: cigarettes per week",
176 )
177 recdrug_tobacco_prevheavy = BoolColumn("recdrug_tobacco_prevheavy")
179 recdrug_cannabis_frequency = CamcopsColumn(
180 "recdrug_cannabis_frequency",
181 Integer,
182 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
183 comment=FREQUENCY_COMMENT,
184 )
185 recdrug_cannabis_jointsperweek = CamcopsColumn(
186 "recdrug_cannabis_jointsperweek",
187 Integer,
188 permitted_value_checker=MIN_ZERO_CHECKER,
189 comment="Cannabis: joints per week",
190 )
191 recdrug_cannabis_prevheavy = BoolColumn("recdrug_cannabis_prevheavy")
193 recdrug_alcohol_frequency = CamcopsColumn(
194 "recdrug_alcohol_frequency",
195 Integer,
196 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
197 comment=FREQUENCY_COMMENT,
198 )
199 recdrug_alcohol_unitsperweek = CamcopsColumn(
200 "recdrug_alcohol_unitsperweek",
201 Integer,
202 permitted_value_checker=MIN_ZERO_CHECKER,
203 comment="Alcohol: units per week",
204 )
205 recdrug_alcohol_prevheavy = BoolColumn("recdrug_alcohol_prevheavy")
207 recdrug_mdma_frequency = CamcopsColumn(
208 "recdrug_mdma_frequency",
209 Integer,
210 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
211 comment=FREQUENCY_COMMENT,
212 )
213 recdrug_mdma_prevheavy = BoolColumn("recdrug_mdma_prevheavy")
215 recdrug_cocaine_frequency = CamcopsColumn(
216 "recdrug_cocaine_frequency",
217 Integer,
218 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
219 comment=FREQUENCY_COMMENT,
220 )
221 recdrug_cocaine_prevheavy = BoolColumn("recdrug_cocaine_prevheavy")
223 recdrug_crack_frequency = CamcopsColumn(
224 "recdrug_crack_frequency",
225 Integer,
226 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
227 comment=FREQUENCY_COMMENT,
228 )
229 recdrug_crack_prevheavy = BoolColumn("recdrug_crack_prevheavy")
231 recdrug_heroin_frequency = CamcopsColumn(
232 "recdrug_heroin_frequency",
233 Integer,
234 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
235 comment=FREQUENCY_COMMENT,
236 )
237 recdrug_heroin_prevheavy = BoolColumn("recdrug_heroin_prevheavy")
239 recdrug_methadone_frequency = CamcopsColumn(
240 "recdrug_methadone_frequency",
241 Integer,
242 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
243 comment=FREQUENCY_COMMENT,
244 )
245 recdrug_methadone_prevheavy = BoolColumn("recdrug_methadone_prevheavy")
247 recdrug_amphetamines_frequency = CamcopsColumn(
248 "recdrug_amphetamines_frequency",
249 Integer,
250 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
251 comment=FREQUENCY_COMMENT,
252 )
253 recdrug_amphetamines_prevheavy = BoolColumn(
254 "recdrug_amphetamines_prevheavy",
255 constraint_name="ck_deakin_1_healthreview_amphetprevheavy",
256 )
258 recdrug_benzodiazepines_frequency = CamcopsColumn(
259 "recdrug_benzodiazepines_frequency",
260 Integer,
261 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
262 comment=FREQUENCY_COMMENT,
263 )
264 recdrug_benzodiazepines_prevheavy = BoolColumn(
265 "recdrug_benzodiazepines_prevheavy",
266 constraint_name="ck_deakin_1_healthreview_benzoprevheavy",
267 )
269 recdrug_ketamine_frequency = CamcopsColumn(
270 "recdrug_ketamine_frequency",
271 Integer,
272 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
273 comment=FREQUENCY_COMMENT,
274 )
275 recdrug_ketamine_prevheavy = BoolColumn("recdrug_ketamine_prevheavy")
277 recdrug_legalhighs_frequency = CamcopsColumn(
278 "recdrug_legalhighs_frequency",
279 Integer,
280 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
281 comment=FREQUENCY_COMMENT,
282 )
283 recdrug_legalhighs_prevheavy = BoolColumn("recdrug_legalhighs_prevheavy")
285 recdrug_inhalants_frequency = CamcopsColumn(
286 "recdrug_inhalants_frequency",
287 Integer,
288 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
289 comment=FREQUENCY_COMMENT,
290 )
291 recdrug_inhalants_prevheavy = BoolColumn("recdrug_inhalants_prevheavy")
293 recdrug_hallucinogens_frequency = CamcopsColumn(
294 "recdrug_hallucinogens_frequency",
295 Integer,
296 permitted_value_checker=ZERO_TO_FOUR_CHECKER,
297 comment=FREQUENCY_COMMENT,
298 )
299 recdrug_hallucinogens_prevheavy = BoolColumn(
300 "recdrug_hallucinogens_prevheavy",
301 constraint_name="ck_deakin_1_healthreview_hallucinogenprevheavy",
302 )
304 recdrug_details = Column("recdrug_details", UnicodeText)
306 recdrug_prevheavy = BoolColumn("recdrug_prevheavy")
307 recdrug_prevheavy_details = Column(
308 "recdrug_prevheavy_details", UnicodeText
309 )
311 mri_claustrophobic = BoolColumn("mri_claustrophobic")
312 mri_difficulty_lying_1_hour = BoolColumn("mri_difficulty_lying_1_hour")
313 mri_nonremovable_metal = BoolColumn("mri_nonremovable_metal")
314 mri_metal_from_operations = BoolColumn("mri_metal_from_operations")
315 mri_tattoos_nicotine_patches = BoolColumn("mri_tattoos_nicotine_patches")
316 mri_worked_with_metal = BoolColumn("mri_worked_with_metal")
317 mri_previous_brain_scan = BoolColumn("mri_previous_brain_scan")
318 mri_previous_brain_scan_details = Column(
319 "mri_previous_brain_scan_details", UnicodeText
320 )
321 other_relevant_things = BoolColumn("other_relevant_things")
322 other_relevant_things_details = Column(
323 "other_relevant_things_details", UnicodeText
324 )
326 willing_to_participate_in_further_studies = BoolColumn(
327 "willing_to_participate_in_further_studies",
328 constraint_name="ck_deakin_1_healthreview_wtpifs",
329 )
331 @staticmethod
332 def longname(req: "CamcopsRequest") -> str:
333 _ = req.gettext
334 return _(
335 "Deakin JB — Antibody-mediated psychosis study — health review"
336 )
338 def is_complete(self) -> bool:
339 return (
340 self.all_fields_not_none(
341 [
342 "ethnicity",
343 "handedness",
344 "education",
345 "allergies",
346 "vaccinations_last3months",
347 "infections_last3months",
348 "infections_chronic",
349 "immune_disorders",
350 "health_anything_else",
351 "recreational_drug_in_last_3_months",
352 "recdrug_prevheavy",
353 "mri_claustrophobic",
354 "mri_difficulty_lying_1_hour",
355 "mri_nonremovable_metal",
356 "mri_metal_from_operations",
357 "mri_tattoos_nicotine_patches",
358 "mri_worked_with_metal",
359 "mri_previous_brain_scan",
360 "other_relevant_things",
361 "willing_to_participate_in_further_studies",
362 ]
363 )
364 and self.field_contents_valid()
365 )
367 def get_drug_frequency_row(self, fieldname: str) -> str:
368 drug_frequency_dict = {
369 0: "Did not use",
370 1: "Occasionally",
371 2: "Monthly",
372 3: "Weekly",
373 4: "Daily",
374 }
375 frequency = drug_frequency_dict.get(getattr(self, fieldname), None)
376 return tr_qa(fieldname, frequency)
378 def get_task_html(self, req: CamcopsRequest) -> str:
379 def twocol_bool_row(fieldname: str) -> str:
380 return self.get_twocol_bool_row(req, fieldname)
382 return f"""
383 <div class="{CssClass.SUMMARY}">
384 <table class="{CssClass.SUMMARY}">
385 {self.get_is_complete_tr(req)}
386 </table>
387 </div>
388 <table class="{CssClass.TASKDETAIL}">
389 <tr>
390 <th width="50%">Question</th>
391 <th width="50%">Answer</th>
392 </tr>
393 """ + (
394 self.get_twocol_val_row("ethnicity")
395 +
396 # UNUSED BY CLIENT! # self.get_twocol_string_row("ethnicity_text") + # noqa
397 self.get_twocol_string_row("ethnicity_other_details")
398 + self.get_twocol_string_row("handedness")
399 + self.get_twocol_string_row("education")
400 + twocol_bool_row("allergies")
401 + twocol_bool_row("allergy_asthma")
402 + twocol_bool_row("allergy_pollen_dust")
403 + twocol_bool_row("allergy_dermatitis")
404 + twocol_bool_row("allergy_food")
405 + twocol_bool_row("allergy_dander")
406 + twocol_bool_row("allergy_other")
407 + self.get_twocol_string_row("allergy_details")
408 + twocol_bool_row("vaccinations_last3months")
409 + self.get_twocol_string_row("vaccination_details")
410 + twocol_bool_row("infections_last3months")
411 + twocol_bool_row("infection_recent_respiratory")
412 + twocol_bool_row("infection_recent_gastroenteritis")
413 + twocol_bool_row("infection_recent_urinary")
414 + twocol_bool_row("infection_recent_sexual")
415 + twocol_bool_row("infection_recent_hepatitis")
416 + twocol_bool_row("infection_recent_other")
417 + self.get_twocol_string_row("infection_recent_details")
418 + twocol_bool_row("infections_chronic")
419 + twocol_bool_row("infection_chronic_respiratory")
420 + twocol_bool_row("infection_chronic_gastroenteritis")
421 + twocol_bool_row("infection_chronic_urinary")
422 + twocol_bool_row("infection_chronic_sexual")
423 + twocol_bool_row("infection_chronic_hepatitis")
424 + twocol_bool_row("infection_chronic_other")
425 + self.get_twocol_string_row("infection_chronic_details")
426 + twocol_bool_row("immune_disorders")
427 + twocol_bool_row("immunity_ms")
428 + twocol_bool_row("immunity_sle")
429 + twocol_bool_row("immunity_arthritis")
430 + twocol_bool_row("immunity_hiv")
431 + twocol_bool_row("immunity_graves")
432 + twocol_bool_row("immunity_diabetes")
433 + twocol_bool_row("immunity_other")
434 + self.get_twocol_string_row("immunity_details")
435 + twocol_bool_row("family_history")
436 + twocol_bool_row("familyhistory_ms")
437 + twocol_bool_row("familyhistory_sle")
438 + twocol_bool_row("familyhistory_arthritis")
439 + twocol_bool_row("familyhistory_graves")
440 + twocol_bool_row("familyhistory_diabetes")
441 + twocol_bool_row("familyhistory_psychosis_sz")
442 + twocol_bool_row("familyhistory_bipolar")
443 + self.get_twocol_string_row("familyhistory_details")
444 + twocol_bool_row("health_anything_else")
445 + self.get_twocol_string_row("health_anything_else_details")
446 + self.get_twocol_string_row("drug_history")
447 + self.get_twocol_string_row("first_antipsychotic_medication")
448 + twocol_bool_row("recreational_drug_in_last_3_months")
449 + self.get_drug_frequency_row("recdrug_tobacco_frequency")
450 + self.get_twocol_val_row("recdrug_tobacco_cigsperweek")
451 + twocol_bool_row("recdrug_tobacco_prevheavy")
452 + self.get_drug_frequency_row("recdrug_cannabis_frequency")
453 + self.get_twocol_val_row("recdrug_cannabis_jointsperweek")
454 + twocol_bool_row("recdrug_cannabis_prevheavy")
455 + self.get_drug_frequency_row("recdrug_alcohol_frequency")
456 + self.get_twocol_val_row("recdrug_alcohol_unitsperweek")
457 + twocol_bool_row("recdrug_alcohol_prevheavy")
458 + self.get_drug_frequency_row("recdrug_mdma_frequency")
459 + twocol_bool_row("recdrug_mdma_prevheavy")
460 + self.get_drug_frequency_row("recdrug_cocaine_frequency")
461 + twocol_bool_row("recdrug_cocaine_prevheavy")
462 + self.get_drug_frequency_row("recdrug_crack_frequency")
463 + twocol_bool_row("recdrug_crack_prevheavy")
464 + self.get_drug_frequency_row("recdrug_heroin_frequency")
465 + twocol_bool_row("recdrug_heroin_prevheavy")
466 + self.get_drug_frequency_row("recdrug_methadone_frequency")
467 + twocol_bool_row("recdrug_methadone_prevheavy")
468 + self.get_drug_frequency_row("recdrug_amphetamines_frequency")
469 + twocol_bool_row("recdrug_amphetamines_prevheavy")
470 + self.get_drug_frequency_row("recdrug_benzodiazepines_frequency")
471 + twocol_bool_row("recdrug_benzodiazepines_prevheavy")
472 + self.get_drug_frequency_row("recdrug_ketamine_frequency")
473 + twocol_bool_row("recdrug_ketamine_prevheavy")
474 + self.get_drug_frequency_row("recdrug_legalhighs_frequency")
475 + twocol_bool_row("recdrug_legalhighs_prevheavy")
476 + self.get_drug_frequency_row("recdrug_inhalants_frequency")
477 + twocol_bool_row("recdrug_inhalants_prevheavy")
478 + self.get_drug_frequency_row("recdrug_hallucinogens_frequency")
479 + twocol_bool_row("recdrug_hallucinogens_prevheavy")
480 + self.get_twocol_string_row("recdrug_details")
481 + twocol_bool_row("recdrug_prevheavy")
482 + self.get_twocol_string_row("recdrug_prevheavy_details")
483 + twocol_bool_row("mri_claustrophobic")
484 + twocol_bool_row("mri_difficulty_lying_1_hour")
485 + twocol_bool_row("mri_nonremovable_metal")
486 + twocol_bool_row("mri_metal_from_operations")
487 + twocol_bool_row("mri_tattoos_nicotine_patches")
488 + twocol_bool_row("mri_worked_with_metal")
489 + twocol_bool_row("mri_previous_brain_scan")
490 + self.get_twocol_string_row("mri_previous_brain_scan_details")
491 + twocol_bool_row("other_relevant_things")
492 + self.get_twocol_string_row("other_relevant_things_details")
493 + twocol_bool_row("willing_to_participate_in_further_studies")
494 + "</table>"
495 )