コード例 #1
0
 def get_html_correct_by_group_and_block(
         self,
         trialarray: List[ExpDetTrial]) -> str:
     if not trialarray:
         return div(italic("No trials"))
     html = """
         <table class="{CssClass.EXTRADETAIL}">
             <tr>
                 <th>Block</th>
     """.format(CssClass=CssClass)
     for g in range(N_CUES):
         # Have spaces around | to allow web browsers to word-wrap
         html += """
             <th>Group {0} P(detected | present)</th>
             <th>Group {0} P(detected | absent)</th>
             <th>Group {0} c</th>
             <th>Group {0} d'</th>
         """.format(g)
     html += """
                 </th>
             </tr>
     """
     for b in range(self.num_blocks):
         html += "<tr>" + td(str(b))
         for g in range(N_CUES):
             (p_detected_given_present,
              p_detected_given_absent,
              c,
              dprime,
              n_trials) = self.get_p_detected(trialarray, [b], [g])
             html += td(a(p_detected_given_present))
             html += td(a(p_detected_given_absent))
             html += td(a(c))
             html += td(a(dprime))
         html += "</tr>\n"
     html += """
         </table>
     """
     return html
コード例 #2
0
ファイル: ifs.py プロジェクト: tarun911/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        scoredict = self.get_score()

        # Q1
        q_a = self.get_simple_tr_qa(req, "q1")
        # Q2
        q_a += self.get_simple_tr_qa(req, "q2")
        # Q3
        q_a += self.get_simple_tr_qa(req, "q3")
        # Q4
        q_a += tr(td(self.wxstring(req, "q4_title")),
                  td("", td_class=CssClass.SUBHEADING),
                  literal=True)
        required = True
        for n in self.Q4_DIGIT_LENGTHS:
            val1 = getattr(self, "q4_len{}_1".format(n))
            val2 = getattr(self, "q4_len{}_2".format(n))
            q = (
                "… " +
                self.wxstring(req, "q4_seq_len{}_1".format(n)) +
                " / " + self.wxstring(req, "q4_seq_len{}_2".format(n))
            )
            if required:
                score = 1 if val1 or val2 else 0
                a = (
                    answer(get_correct_incorrect_none(val1)) +
                    " / " + answer(get_correct_incorrect_none(val2)) +
                    " (scores {})".format(score)
                )
            else:
                a = ""
            q_a += tr(q, a)
            if not val1 and not val2:
                required = False
        # Q5
        q_a += self.get_simple_tr_qa(req, "q5")
        # Q6
        q_a += tr(td(self.wxstring(req, "q6_title")),
                  td("", td_class=CssClass.SUBHEADING),
                  literal=True)
        for n in self.Q6_SEQUENCE_NUMS:
            nstr = str(n)
            val = getattr(self, "q6_seq" + nstr)
            q_a += tr_qa("… " + self.wxstring(req, "q6_seq" + nstr), val)
        # Q7
        q7map = {
            None: None,
            1: self.wxstring(req, "q7_a_1"),
            0.5: self.wxstring(req, "q7_a_half"),
            0: self.wxstring(req, "q7_a_0"),
        }
        q_a += tr(td(self.wxstring(req, "q7_title")),
                  td("", td_class=CssClass.SUBHEADING),
                  literal=True)
        for n in self.Q7_PROVERB_NUMS:
            nstr = str(n)
            val = getattr(self, "q7_proverb" + nstr)
            a = q7map.get(val, INVALID_VALUE)
            q_a += tr_qa("… " + self.wxstring(req, "q7_proverb" + nstr), a)
        # Q8
        q8map = {
            None: None,
            2: self.wxstring(req, "q8_a2"),
            1: self.wxstring(req, "q8_a1"),
            0: self.wxstring(req, "q8_a0"),
        }
        q_a += tr(td(self.wxstring(req, "q8_title")),
                  td("", td_class=CssClass.SUBHEADING),
                  literal=True)
        for n in self.Q8_SENTENCE_NUMS:
            nstr = str(n)
            val = getattr(self, "q8_sentence" + nstr)
            a = q8map.get(val, INVALID_VALUE)
            q_a += tr_qa("… " + self.wxstring(req, "q8_sentence_" + nstr), a)

        h = """
            <div class="{CssClass.SUMMARY}">
                <table class="{CssClass.SUMMARY}">
                    {complete_tr}
                    <tr>
                        <td>Total (higher better)</td>
                        <td>{total} / {tmax}</td>
                    </td>
                    <tr>
                        <td>Working memory index <sup>1</sup></td>
                        <td>{wm} / {wmax}</td>
                    </td>
                </table>
            </div>
            <table class="{CssClass.TASKDETAIL}">
                <tr>
                    <th width="50%">Question</th>
                    <th width="50%">Answer</th>
                </tr>
                {q_a}
            </table>
            <div class="{CssClass.FOOTNOTES}">
                [1] Sum of scores for Q4 + Q6.
            </div>
            {DATA_COLLECTION_UNLESS_UPGRADED_DIV}
        """.format(
            CssClass=CssClass,
            complete_tr=self.get_is_complete_tr(req),
            total=answer(scoredict['total']),
            tmax=self.MAX_TOTAL,
            wm=answer(scoredict['wm']),
            wmax=self.MAX_WM,
            q_a=q_a,
            DATA_COLLECTION_UNLESS_UPGRADED_DIV=DATA_COLLECTION_UNLESS_UPGRADED_DIV,  # noqa
        )
        return h
コード例 #3
0
ファイル: bdi.py プロジェクト: RudolfCardinal/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        score = self.total_score()

        # Suicidal thoughts:
        suicidality_score = getattr(self, SUICIDALITY_FN)
        if suicidality_score is None:
            suicidality_text = bold("? (not completed)")
            suicidality_css_class = CssClass.INCOMPLETE
        elif suicidality_score == 0:
            suicidality_text = str(suicidality_score)
            suicidality_css_class = ""
        else:
            suicidality_text = bold(str(suicidality_score))
            suicidality_css_class = CssClass.WARNING

        # Custom somatic score for Khandaker Insight study:
        somatic_css_class = ""
        if self.is_bdi_ii():
            somatic_values = self.get_values(
                CUSTOM_SOMATIC_KHANDAKER_BDI_II_FIELDS)
            somatic_missing = False
            somatic_score = 0
            for v in somatic_values:
                if v is None:
                    somatic_missing = True
                    somatic_css_class = CssClass.INCOMPLETE
                    break
                else:
                    somatic_score += int(v)
            somatic_text = ("incomplete"
                            if somatic_missing else str(somatic_score))
        else:
            somatic_text = "N/A"  # not the BDI-II

        # Question rows:
        q_a = ""
        qdict = TOPICS_BY_SCALE.get(self.bdi_scale)
        topic = "?"
        for q in range(1, NQUESTIONS + 1):
            if qdict:
                topic = qdict.get(q, "??")
            q_a += tr_qa(
                f"{req.sstring(SS.QUESTION)} {q} ({topic})",
                getattr(self, "q" + str(q)),
            )

        # HTML:
        tr_somatic_score = tr(
            td("Custom somatic score for Insight study <sup>[2]</sup> "
               "(sum of scores for questions {}, for BDI-II only)".format(
                   ", ".join(
                       "Q" + str(qnum)
                       for qnum in CUSTOM_SOMATIC_KHANDAKER_BDI_II_QNUMS))),
            td(somatic_text, td_class=somatic_css_class),
            literal=True,
        )
        tr_which_scale = tr_qa(
            req.wappstring(AS.BDI_WHICH_SCALE) + " <sup>[3]</sup>",
            ws.webify(self.bdi_scale),
        )
        return f"""
コード例 #4
0
ファイル: slums.py プロジェクト: RudolfCardinal/camcops
 def get_task_html(self, req: CamcopsRequest) -> str:
     score = self.total_score()
     category = self.category(req)
     h = """
         {clinician_comments}
         <div class="{CssClass.SUMMARY}">
             <table class="{CssClass.SUMMARY}">
                 {tr_is_complete}
                 {total_score}
                 {category}
             </table>
         </div>
         <table class="{CssClass.TASKDETAIL}">
             <tr>
                 <th width="80%">Question</th>
                 <th width="20%">Score</th>
             </tr>
     """.format(
         clinician_comments=self.get_standard_clinician_comments_block(
             req, self.comments),
         CssClass=CssClass,
         tr_is_complete=self.get_is_complete_tr(req),
         total_score=tr(
             req.sstring(SS.TOTAL_SCORE),
             answer(score) + f" / {self.MAX_SCORE}",
         ),
         category=tr_qa(
             req.sstring(SS.CATEGORY) + " <sup>[1]</sup>", category),
     )
     h += tr_qa(self.wxstring(req, "alert_s"),
                get_yes_no_none(req, self.alert))
     h += tr_qa(
         self.wxstring(req, "highschool_s"),
         get_yes_no_none(req, self.highschooleducation),
     )
     h += tr_qa(self.wxstring(req, "q1_s"), self.q1)
     h += tr_qa(self.wxstring(req, "q2_s"), self.q2)
     h += tr_qa(self.wxstring(req, "q3_s"), self.q3)
     h += tr(
         "Q5 <sup>[2]</sup> (money spent, money left "
         "[<i>scores 2</i>]",
         ", ".join(answer(x) for x in (self.q5a, self.q5b)),
     )
     h += tr_qa(
         "Q6 (animal fluency) [<i>≥15 scores 3, 10–14 scores 2, "
         "5–9 scores 1, 0–4 scores 0</i>]",
         self.q6,
     )
     h += tr(
         "Q7 (recall: apple, pen, tie, house, car)",
         ", ".join(
             answer(x)
             for x in (self.q7a, self.q7b, self.q7c, self.q7d, self.q7e)),
     )
     h += tr(
         "Q8 (backwards: 648, 8537)",
         ", ".join(answer(x) for x in (self.q8b, self.q8c)),
     )
     h += tr(
         "Q9 (clock: hour markers, time [<i>score 2 each</i>]",
         ", ".join(answer(x) for x in (self.q9a, self.q9b)),
     )
     h += tr(
         "Q10 (X in triangle; which is biggest?)",
         ", ".join(answer(x) for x in (self.q10a, self.q10b)),
     )
     h += tr(
         "Q11 (story: Female’s name? Job? When back to work? "
         "State she lived in? [<i>score 2 each</i>])",
         ", ".join(
             answer(x)
             for x in (self.q11a, self.q11b, self.q11c, self.q11d)),
     )
     h += f"""
         </table>
         <table class="{CssClass.TASKDETAIL}">
     """
     h += subheading_spanning_two_columns("Images of tests: clock, shapes")
     # noinspection PyTypeChecker
     h += tr(
         td(
             get_blob_img_html(self.clockpicture),
             td_width="50%",
             td_class=CssClass.PHOTO,
         ),
         td(
             get_blob_img_html(self.shapespicture),
             td_width="50%",
             td_class=CssClass.PHOTO,
         ),
         literal=True,
     )
     h += f"""
         </table>
         <div class="{CssClass.FOOTNOTES}">
             [1] With high school education:
             ≥27 normal, ≥21 MCI, ≤20 dementia.
             Without high school education:
             ≥25 normal, ≥20 MCI, ≤19 dementia.
             (Tariq et al. 2006, PubMed ID 17068312.)
             [2] Q4 (learning the five words) isn’t scored.
         </div>
     """
     return h
コード例 #5
0
 def get_task_html(self, req: CamcopsRequest) -> str:
     dict_q1 = {None: None}
     dict_q3 = {None: None}
     dict_q4 = {None: None}
     dict_q5 = {None: None}
     dict_q11 = {None: None}
     dict_q12 = {None: None}
     for option in range(1, 5):
         dict_q1[option] = self.wxstring(req, "q1_option" + str(option))
     for option in range(1, 6):
         dict_q3[option] = self.wxstring(req, "q3_option" + str(option))
         dict_q11[option] = self.wxstring(req, "q11_option" + str(option))
     for option in range(0, 6):
         prefix = str(option) + " – " if option > 0 else ""
         dict_q4[option] = prefix + self.wxstring(req,
                                                  "q4_option" + str(option))
         dict_q5[option] = prefix + self.wxstring(req,
                                                  "q5_option" + str(option))
     for option in range(1, 17):
         dict_q12[option] = self.wxstring(req,
                                          "ethnicity_option" + str(option))
     h = f"""
         <div class="{CssClass.SUMMARY}">
             <table class="{CssClass.SUMMARY}">
                 {self.get_is_complete_tr(req)}
             </table>
         </div>
         <table class="{CssClass.TASKDETAIL}">
             <tr>
                 <th width="60%">Question</th>
                 <th width="40%">Answer</th>
             </tr>
     """
     ell = "&hellip; "  # horizontal ellipsis
     sep_row = subheading_spanning_two_columns("<br>")
     blank_cell = td("", td_class=CssClass.SUBHEADING)
     h += tr_qa(self.wxstring(req, "q_doctor"), ws.webify(self.doctor))
     h += sep_row
     h += tr_qa(self.wxstring(req, "q1"), get_from_dict(dict_q1, self.q1))
     h += tr(td(self.wxstring(req, "q2")), blank_cell, literal=True)
     h += tr_qa(
         ell + self.wxstring(req, "q2_a"),
         get_yes_no_none(req, self.q2a),
         default="",
     )
     h += tr_qa(
         ell + self.wxstring(req, "q2_b"),
         get_yes_no_none(req, self.q2b),
         default="",
     )
     h += tr_qa(
         ell + self.wxstring(req, "q2_c"),
         get_yes_no_none(req, self.q2c),
         default="",
     )
     h += tr_qa(
         ell + self.wxstring(req, "q2_d"),
         get_yes_no_none(req, self.q2d),
         default="",
     )
     h += tr_qa(
         ell + self.wxstring(req, "q2_e"),
         get_yes_no_none(req, self.q2e),
         default="",
     )
     h += tr_qa(
         ell + self.wxstring(req, "q2_f"),
         get_yes_no_none(req, self.q2f),
         default="",
     )
     h += tr_qa(
         ell + ell + self.wxstring(req, "q2f_s"),
         ws.webify(self.q2f_details),
     )
     h += tr_qa(self.wxstring(req, "q3"), get_from_dict(dict_q3, self.q3))
     h += tr(td(self.wxstring(req, "q4")), blank_cell, literal=True)
     h += tr_qa(ell + self.wxstring(req, "q4_a"),
                get_from_dict(dict_q4, self.q4a))
     h += tr_qa(ell + self.wxstring(req, "q4_b"),
                get_from_dict(dict_q4, self.q4b))
     h += tr_qa(ell + self.wxstring(req, "q4_c"),
                get_from_dict(dict_q4, self.q4c))
     h += tr_qa(ell + self.wxstring(req, "q4_d"),
                get_from_dict(dict_q4, self.q4d))
     h += tr_qa(ell + self.wxstring(req, "q4_e"),
                get_from_dict(dict_q4, self.q4e))
     h += tr_qa(ell + self.wxstring(req, "q4_f"),
                get_from_dict(dict_q4, self.q4f))
     h += tr_qa(ell + self.wxstring(req, "q4_g"),
                get_from_dict(dict_q4, self.q4g))
     h += tr(td(self.wxstring(req, "q5")), blank_cell, literal=True)
     h += tr_qa(ell + self.wxstring(req, "q5_a"),
                get_from_dict(dict_q5, self.q5a))
     h += tr_qa(ell + self.wxstring(req, "q5_b"),
                get_from_dict(dict_q5, self.q5b))
     h += tr_qa(self.wxstring(req, "q6"), get_yes_no_none(req, self.q6))
     h += tr_qa(self.wxstring(req, "q7"), get_yes_no_none(req, self.q7))
     h += tr_qa(self.wxstring(req, "q8"), get_yes_no_none(req, self.q8))
     h += tr_qa(self.wxstring(req, "q9_s"), ws.webify(self.q9))
     h += sep_row
     h += tr_qa(req.sstring(SS.SEX), ws.webify(self.q10))
     h += tr_qa(self.wxstring(req, "q11"),
                get_from_dict(dict_q11, self.q11))
     h += tr_qa(self.wxstring(req, "q12"),
                get_from_dict(dict_q12, self.q12))
     h += tr_qa(
         ell + self.wxstring(req, "ethnicity_other_s"),
         ws.webify(self.q12_details),
     )
     h += """
         </table>
     """
     return h
コード例 #6
0
ファイル: das28.py プロジェクト: RudolfCardinal/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        sides_strings = [self.wxstring(req, s) for s in self.SIDES]
        states_strings = [self.wxstring(req, s) for s in self.STATES]

        joint_rows = table_row([""] + sides_strings, colspans=[1, 2, 2])

        joint_rows += table_row([""] + states_strings * 2)

        for joint in self.JOINTS:
            cells = [th(self.wxstring(req, joint))]
            for side in self.SIDES:
                for state in self.STATES:
                    value = "?"
                    fval = getattr(self, self.field_name(side, joint, state))
                    if fval is not None:
                        value = "✓" if fval else "×"

                    cells.append(td(value))

            joint_rows += tr(*cells, literal=True)

        das28_crp = self.das28_crp()
        das28_esr = self.das28_esr()

        other_rows = "".join([
            tr_qa(self.wxstring(req, f), getattr(self, f))
            for f in self.OTHER_FIELD_NAMES
        ])

        html = """
            <div class="{CssClass.SUMMARY}">
                <table class="{CssClass.SUMMARY}">
                    {tr_is_complete}
                    {das28_crp}
                    {das28_esr}
                    {swollen_joint_count}
                    {tender_joint_count}
                </table>
            </div>
            <table class="{CssClass.TASKDETAIL}">
                {joint_rows}
            </table>
            <table class="{CssClass.TASKDETAIL}">
                {other_rows}
            </table>
            <div class="{CssClass.FOOTNOTES}">
                [1] 0.56 × √(tender joint count) +
                    0.28 × √(swollen joint count) +
                    0.36 × ln(CRP + 1) +
                    0.014 x VAS disease activity +
                    0.96.
                    CRP 0–300 mg/L. VAS: 0–100mm.<br>
                    Cutoffs:
                    &lt;2.4 remission,
                    &lt;2.9 low disease activity,
                    2.9–4.6 moderate disease activity,
                    &gt;4.6 high disease activity.<br>
                [2] 0.56 × √(tender joint count) +
                    0.28 × √(swollen joint count) +
                    0.70 × ln(ESR) +
                    0.014 x VAS disease activity.
                    ESR 1–300 mm/h. VAS: 0–100mm.<br>
                    Cutoffs:
                    &lt;2.6 remission,
                    &lt;3.2 low disease activity,
                    3.2–5.1 moderate disease activity,
                    &gt;5.1 high disease activity.<br>
            </div>
        """.format(
            CssClass=CssClass,
            tr_is_complete=self.get_is_complete_tr(req),
            das28_crp=tr(
                self.wxstring(req, "das28_crp") + " <sup>[1]</sup>",
                "{} ({})".format(
                    answer(ws.number_to_dp(das28_crp, 2, default="?")),
                    self.activity_state_crp(req, das28_crp),
                ),
            ),
            das28_esr=tr(
                self.wxstring(req, "das28_esr") + " <sup>[2]</sup>",
                "{} ({})".format(
                    answer(ws.number_to_dp(das28_esr, 2, default="?")),
                    self.activity_state_esr(req, das28_esr),
                ),
            ),
            swollen_joint_count=tr(
                self.wxstring(req, "swollen_count"),
                answer(self.swollen_joint_count()),
            ),
            tender_joint_count=tr(
                self.wxstring(req, "tender_count"),
                answer(self.tender_joint_count()),
            ),
            joint_rows=joint_rows,
            other_rows=other_rows,
        )
        return html
コード例 #7
0
ファイル: nart.py プロジェクト: tarun911/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        # Table rows for individual words
        q_a = ""
        nwords = len(WORDLIST)
        ncolumns = 3
        nrows = int(math.ceil(float(nwords) / float(ncolumns)))
        column = 0
        row = 0
        # x: word index (shown in top-to-bottom then left-to-right sequence)
        for unused_loopvar in range(nwords):
            x = (column * nrows) + row
            if column == 0:  # first column
                q_a += "<tr>"
            q_a += td(ACCENTED_WORDLIST[x])
            q_a += td(answer(getattr(self, WORDLIST[x])))
            if column == (ncolumns - 1):  # last column
                q_a += "</tr>"
                row += 1
            column = (column + 1) % ncolumns

        # Annotations
        nelson = "; Nelson 1982 <sup>[1]</sup>"
        nelson_willison = "; Nelson &amp; Willison 1991 <sup>[2]</sup>"
        bright = "; Bright 2016 <sup>[3]</sup>"

        # HTML
        h = """
            <div class="{CssClass.SUMMARY}">
                <table class="{CssClass.SUMMARY}">
                    {tr_is_complete}
                    {tr_total_errors}

                    {nelson_full_scale_iq}
                    {nelson_verbal_iq}
                    {nelson_performance_iq}
                    {nelson_willison_full_scale_iq}

                    {bright_full_scale_iq}
                    {bright_general_ability}
                    {bright_verbal_comprehension}
                    {bright_perceptual_reasoning}
                    {bright_working_memory}
                    {bright_perceptual_speed}
                </table>
            </div>
            <div class="{CssClass.EXPLANATION}">
                Estimates premorbid IQ by pronunciation of irregular words.
            </div>
            <table class="{CssClass.TASKDETAIL}">
                <tr>
                    <th width="16%">Word</th><th width="16%">Correct?</th>
                    <th width="16%">Word</th><th width="16%">Correct?</th>
                    <th width="16%">Word</th><th width="16%">Correct?</th>
                </tr>
                {q_a}
            </table>
            <div class="{CssClass.FOOTNOTES}">
                [1] Nelson HE (1982), <i>National Adult Reading Test (NART):
                    For the Assessment of Premorbid Intelligence in Patients
                    with Dementia: Test Manual</i>, NFER-Nelson, Windsor, UK.
                [2] Nelson HE, Wilson J (1991)
                    <i>National Adult Reading Test (NART)</i>,
                    NFER-Nelson, Windsor, UK; see [3].
                [3] Bright P et al (2016). The National Adult Reading Test:
                    restandardisation against the Wechsler Adult Intelligence
                    Scale—Fourth edition.
                    <a href="https://www.ncbi.nlm.nih.gov/pubmed/27624393">PMID
                    27624393</a>.
            </div>
            <div class="{CssClass.COPYRIGHT}">
                NART: Copyright © Hazel E. Nelson. Used with permission.
            </div>
        """.format(
            CssClass=CssClass,
            tr_is_complete=self.get_is_complete_tr(req),
            tr_total_errors=tr_qa("Total errors", self.n_errors()),
            nelson_full_scale_iq=tr_qa(
                "Predicted WAIS full-scale IQ = 127.7 – 0.826 × errors" +
                nelson,  # noqa
                self.nelson_full_scale_iq()),
            nelson_verbal_iq=tr_qa(
                "Predicted WAIS verbal IQ = 129.0 – 0.919 × errors" + nelson,
                self.nelson_verbal_iq()),
            nelson_performance_iq=tr_qa(
                "Predicted WAIS performance IQ = 123.5 – 0.645 × errors" +
                nelson, self.nelson_performance_iq()),
            nelson_willison_full_scale_iq=tr_qa(
                "Predicted WAIS-R full-scale IQ "
                "= 130.6 – 1.24 × errors" + nelson_willison,
                self.nelson_willison_full_scale_iq()),
            bright_full_scale_iq=tr_qa(
                "Predicted WAIS-IV full-scale IQ "
                "= 126.41 – 0.9775 × errors" + bright,
                self.bright_full_scale_iq()),
            bright_general_ability=tr_qa(
                "Predicted WAIS-IV General Ability Index "
                "= 126.5 – 0.9656 × errors" + bright,
                self.bright_general_ability()),
            bright_verbal_comprehension=tr_qa(
                "Predicted WAIS-IV Verbal Comprehension Index "
                "= 126.81 – 1.0745 × errors" + bright,
                self.bright_verbal_comprehension()),
            bright_perceptual_reasoning=tr_qa(
                "Predicted WAIS-IV Perceptual Reasoning Index "
                "= 120.18 – 0.6242 × errors" + bright,
                self.bright_perceptual_reasoning()),
            bright_working_memory=tr_qa(
                "Predicted WAIS-IV Working Memory Index "
                "= 120.53 – 0.7901 × errors" + bright,
                self.bright_working_memory()),
            bright_perceptual_speed=tr_qa(
                "Predicted WAIS-IV Perceptual Speed Index "
                "= 114.53 – 0.5285 × errors" + bright,
                self.bright_perceptual_speed()),
            q_a=q_a,
        )
        return h
コード例 #8
0
ファイル: moca.py プロジェクト: RudolfCardinal/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        vsp = self.score_vsp()
        naming = self.score_naming()
        attention = self.score_attention()
        language = self.score_language()
        abstraction = self.score_abstraction()
        memory = self.score_memory()
        orientation = self.score_orientation()
        totalscore = self.total_score()
        category = self.category(req)

        h = """
            {clinician_comments}
            <div class="{CssClass.SUMMARY}">
                <table class="{CssClass.SUMMARY}">
                    {tr_is_complete}
                    {total_score}
                    {category}
                </table>
            </div>
            <table class="{CssClass.TASKDETAIL}">
                <tr>
                    <th width="69%">Question</th>
                    <th width="31%">Score</th>
                </tr>
        """.format(
            clinician_comments=self.get_standard_clinician_comments_block(
                req, self.comments),
            CssClass=CssClass,
            tr_is_complete=self.get_is_complete_tr(req),
            total_score=tr(
                req.sstring(SS.TOTAL_SCORE),
                answer(totalscore) + f" / {self.MAX_SCORE}",
            ),
            category=tr_qa(
                self.wxstring(req, "category") + " <sup>[1]</sup>", category),
        )

        h += tr(
            self.wxstring(req, "subscore_visuospatial"),
            answer(vsp) + " / 5",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Path, cube, clock/contour, clock/numbers, clock/hands",
            ", ".join(
                answer(x)
                for x in (self.q1, self.q2, self.q3, self.q4, self.q5)),
        )

        h += tr(
            self.wxstring(req, "subscore_naming"),
            answer(naming) + " / 3",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Lion, rhino, camel",
            ", ".join(answer(x) for x in (self.q6, self.q7, self.q8)),
        )

        h += tr(
            self.wxstring(req, "subscore_attention"),
            answer(attention) + " / 6",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "5 digits forwards, 3 digits backwards, tapping, serial 7s "
            "[<i>scores 3</i>]",
            ", ".join(
                answer(x) for x in (self.q9, self.q10, self.q11, self.q12)),
        )

        h += tr(
            self.wxstring(req, "subscore_language"),
            answer(language) + " / 3",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Repeat sentence 1, repeat sentence 2, fluency to letter ‘F’",
            ", ".join(answer(x) for x in (self.q13, self.q14, self.q15)),
        )

        h += tr(
            self.wxstring(req, "subscore_abstraction"),
            answer(abstraction) + " / 2",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Means of transportation, measuring instruments",
            ", ".join(answer(x) for x in (self.q16, self.q17)),
        )

        h += tr(
            self.wxstring(req, "subscore_memory"),
            answer(memory) + " / 5",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Registered on first trial [<i>not scored</i>]",
            ", ".join(
                answer(x, formatter_answer=italic) for x in (
                    self.register_trial1_1,
                    self.register_trial1_2,
                    self.register_trial1_3,
                    self.register_trial1_4,
                    self.register_trial1_5,
                )),
        )
        h += tr(
            "Registered on second trial [<i>not scored</i>]",
            ", ".join(
                answer(x, formatter_answer=italic) for x in (
                    self.register_trial2_1,
                    self.register_trial2_2,
                    self.register_trial2_3,
                    self.register_trial2_4,
                    self.register_trial2_5,
                )),
        )
        h += tr(
            "Recall FACE, VELVET, CHURCH, DAISY, RED with no cue",
            ", ".join(
                answer(x)
                for x in (self.q18, self.q19, self.q20, self.q21, self.q22)),
        )
        h += tr(
            "Recall with category cue [<i>not scored</i>]",
            ", ".join(
                answer(x, formatter_answer=italic) for x in (
                    self.recall_category_cue_1,
                    self.recall_category_cue_2,
                    self.recall_category_cue_3,
                    self.recall_category_cue_4,
                    self.recall_category_cue_5,
                )),
        )
        h += tr(
            "Recall with multiple-choice cue [<i>not scored</i>]",
            ", ".join(
                answer(x, formatter_answer=italic) for x in (
                    self.recall_mc_cue_1,
                    self.recall_mc_cue_2,
                    self.recall_mc_cue_3,
                    self.recall_mc_cue_4,
                    self.recall_mc_cue_5,
                )),
        )

        h += tr(
            self.wxstring(req, "subscore_orientation"),
            answer(orientation) + " / 6",
            tr_class=CssClass.SUBHEADING,
        )
        h += tr(
            "Date, month, year, day, place, city",
            ", ".join(
                answer(x) for x in (
                    self.q23,
                    self.q24,
                    self.q25,
                    self.q26,
                    self.q27,
                    self.q28,
                )),
        )

        h += subheading_spanning_two_columns(self.wxstring(req, "education_s"))
        h += tr_qa("≤12 years’ education?", self.education12y_or_less)
        # noinspection PyTypeChecker
        h += """
            </table>
            <table class="{CssClass.TASKDETAIL}">
                {tr_subhead_images}
                {tr_images_1}
                {tr_images_2}
            </table>
            <div class="{CssClass.FOOTNOTES}">
                [1] Normal is ≥26 (Nasreddine et al. 2005, PubMed ID 15817019).
            </div>
            <div class="{CssClass.COPYRIGHT}">
                MoCA: Copyright © Ziad Nasreddine. In 2012, could be reproduced
                without permission for CLINICAL and EDUCATIONAL use (with
                permission from the copyright holder required for any other
                use), with no special restrictions on electronic versions.
                However, as of 2021, electronic versions are prohibited without
                specific authorization from the copyright holder; see <a
                href="https://camcops.readthedocs.io/en/latest/tasks/moca.html">
                https://camcops.readthedocs.io/en/latest/tasks/moca.html</a>.
            </div>
        """.format(
            CssClass=CssClass,
            tr_subhead_images=subheading_spanning_two_columns(
                "Images of tests: trail, cube, clock", th_not_td=True),
            tr_images_1=tr(
                td(
                    get_blob_img_html(self.trailpicture),
                    td_class=CssClass.PHOTO,
                    td_width="50%",
                ),
                td(
                    get_blob_img_html(self.cubepicture),
                    td_class=CssClass.PHOTO,
                    td_width="50%",
                ),
                literal=True,
            ),
            tr_images_2=tr(
                td(
                    get_blob_img_html(self.clockpicture),
                    td_class=CssClass.PHOTO,
                    td_width="50%",
                ),
                td("", td_class=CssClass.SUBHEADING),
                literal=True,
            ),
        )
        return h
コード例 #9
0
ファイル: ifs.py プロジェクト: RudolfCardinal/camcops
    def get_task_html(self, req: CamcopsRequest) -> str:
        scoredict = self.get_score()

        # Q1
        q_a = self.get_simple_tr_qa(req, "q1")
        # Q2
        q_a += self.get_simple_tr_qa(req, "q2")
        # Q3
        q_a += self.get_simple_tr_qa(req, "q3")
        # Q4
        q_a += tr(
            td(self.wxstring(req, "q4_title")),
            td("", td_class=CssClass.SUBHEADING),
            literal=True,
        )
        required = True
        for n in self.Q4_DIGIT_LENGTHS:
            val1 = getattr(self, f"q4_len{n}_1")
            val2 = getattr(self, f"q4_len{n}_2")
            q = ("… " + self.wxstring(req, f"q4_seq_len{n}_1") + " / " +
                 self.wxstring(req, f"q4_seq_len{n}_2"))
            if required:
                score = 1 if val1 or val2 else 0
                a = (answer(get_correct_incorrect_none(val1)) + " / " +
                     answer(get_correct_incorrect_none(val2)) +
                     f" (scores {score})")
            else:
                a = ""
            q_a += tr(q, a)
            if not val1 and not val2:
                required = False
        # Q5
        q_a += self.get_simple_tr_qa(req, "q5")
        # Q6
        q_a += tr(
            td(self.wxstring(req, "q6_title")),
            td("", td_class=CssClass.SUBHEADING),
            literal=True,
        )
        for n in self.Q6_SEQUENCE_NUMS:
            nstr = str(n)
            val = getattr(self, "q6_seq" + nstr)
            q_a += tr_qa("… " + self.wxstring(req, "q6_seq" + nstr), val)
        # Q7
        q7map = {
            None: None,
            1: self.wxstring(req, "q7_a_1"),
            0.5: self.wxstring(req, "q7_a_half"),
            0: self.wxstring(req, "q7_a_0"),
        }
        q_a += tr(
            td(self.wxstring(req, "q7_title")),
            td("", td_class=CssClass.SUBHEADING),
            literal=True,
        )
        for n in self.Q7_PROVERB_NUMS:
            nstr = str(n)
            val = getattr(self, "q7_proverb" + nstr)
            a = q7map.get(val, INVALID_VALUE)
            q_a += tr_qa("… " + self.wxstring(req, "q7_proverb" + nstr), a)
        # Q8
        q8map = {
            None: None,
            2: self.wxstring(req, "q8_a2"),
            1: self.wxstring(req, "q8_a1"),
            0: self.wxstring(req, "q8_a0"),
        }
        q_a += tr(
            td(self.wxstring(req, "q8_title")),
            td("", td_class=CssClass.SUBHEADING),
            literal=True,
        )
        for n in self.Q8_SENTENCE_NUMS:
            nstr = str(n)
            val = getattr(self, "q8_sentence" + nstr)
            a = q8map.get(val, INVALID_VALUE)
            q_a += tr_qa("… " + self.wxstring(req, "q8_sentence_" + nstr), a)

        return f"""
コード例 #10
0
 def text_row(self, req: CamcopsRequest, wstringname: str) -> str:
     return tr(
         td(self.wxstring(req, wstringname)),
         td("", td_class=CssClass.SUBHEADING),
         literal=True,
     )
コード例 #11
0
    def get_task_html(self, req: CamcopsRequest) -> str:
        score = self.total_score()

        # Suicidal thoughts:
        suicidality_score = getattr(self, SUICIDALITY_FN)
        if suicidality_score is None:
            suicidality_text = bold("? (not completed)")
            suicidality_css_class = CssClass.INCOMPLETE
        elif suicidality_score == 0:
            suicidality_text = str(suicidality_score)
            suicidality_css_class = ""
        else:
            suicidality_text = bold(str(suicidality_score))
            suicidality_css_class = CssClass.WARNING

        # Custom somatic score for Khandaker Insight study:
        somatic_css_class = ""
        if self.is_bdi_ii():
            somatic_values = self.get_values(
                CUSTOM_SOMATIC_KHANDAKER_BDI_II_FIELDS)
            somatic_missing = False
            somatic_score = 0
            for v in somatic_values:
                if v is None:
                    somatic_missing = True
                    somatic_css_class = CssClass.INCOMPLETE
                    break
                else:
                    somatic_score += int(v)
            somatic_text = ("incomplete" if somatic_missing
                            else str(somatic_score))
        else:
            somatic_text = "N/A"  # not the BDI-II

        # Question rows:
        q_a = ""
        qdict = TOPICS_BY_SCALE.get(self.bdi_scale)
        topic = "?"
        for q in range(1, NQUESTIONS + 1):
            if qdict:
                topic = qdict.get(q, "??")
            q_a += tr_qa(
                "{question} {qnum} ({topic})".format(
                    question=req.wappstring("question"),
                    qnum=q,
                    topic=topic,
                ),
                getattr(self, "q" + str(q))
            )

        # HTML:
        h = """
            <div class="{CssClass.SUMMARY}">
                <table class="{CssClass.SUMMARY}">
                    {tr_is_complete}
                    {tr_total_score}
                    <tr>
                        <td>
                            Suicidal thoughts/wishes score
                            (Q{suicidality_qnum}) <sup>[1]</sup>
                        </td>
                        {td_suicidality}
                    </tr>
                    {tr_somatic_score}
                </table>
            </div>
            <div class="{CssClass.EXPLANATION}">
                All questions are scored from 0–3
                (0 free of symptoms, 3 most symptomatic).
            </div>
            <table class="{CssClass.TASKDETAIL}">
                <tr>
                    <th width="70%">Question</th>
                    <th width="30%">Answer</th>
                </tr>
                {tr_which_scale}
                {q_a}
            </table>
            <div class="{CssClass.FOOTNOTES}">
                [1] Suicidal thoughts are asked about in Q{suicidality_qnum}
                    for all of: BDI-I (1961), BDI-IA (1978), and BDI-II (1996).

                [2] Insight study:
                    <a href="https://doi.org/10.1186/ISRCTN16942542">doi:10.1186/ISRCTN16942542</a>

                [3] See the
                    <a href="https://camcops.readthedocs.io/en/latest/tasks/bdi.html">CamCOPS
                    BDI help</a> for full references and bibliography for the
                    citations that follow.

                    <b>The BDI rates “right now” [Beck1988].
                    The BDI-IA rates the past week [Beck1988].
                    The BDI-II rates the past two weeks [Beck1996b].</b>

                    1961 BDI(-I) question topics from [Beck1988].
                    1978 BDI-IA question topics from [Beck1996b].
                    1996 BDI-II question topics from [Steer1999], [Gary2018].
                </ul>

            </div>
            {data_collection_only_div}
        """.format(  # noqa
            CssClass=CssClass,
            tr_is_complete=self.get_is_complete_tr(req),
            tr_total_score=tr(
                req.wappstring("total_score"),
                answer(score) + " / {}".format(MAX_SCORE)
            ),
            suicidality_qnum=SUICIDALITY_QNUM,
            td_suicidality=td(suicidality_text, td_class=suicidality_css_class),  # noqa
            tr_somatic_score=tr(
                td(
                    "Custom somatic score for Insight study <sup>[2]</sup> "
                    "(sum of scores for questions {}, for BDI-II only)".format(
                        ", ".join("Q" + str(qnum) for qnum in
                                  CUSTOM_SOMATIC_KHANDAKER_BDI_II_QNUMS))
                ),
                td(somatic_text, td_class=somatic_css_class),
                literal=True
            ),
            tr_which_scale=tr_qa(
                req.wappstring("bdi_which_scale") + " <sup>[3]</sup>",
                ws.webify(self.bdi_scale)
            ),
            q_a=q_a,
            data_collection_only_div=DATA_COLLECTION_ONLY_DIV
        )
        return h