Lincoln Gombedza
feat: v2.0 — PICO builder, CASP appraisal, Literature Matrix, 4 databases
0c049db
"""
CASP (Critical Appraisal Skills Programme) checklists.
Adapted for student nurses — simplified from official CASP 2018/2022 checklists.
Full CASP checklists: https://casp-uk.net/casp-tools-checklists/
Supported study types:
- Systematic Review
- Randomised Controlled Trial (RCT)
- Cohort Study
- Qualitative Research
- Case-Control Study
- Diagnostic Test Study
"""
from dataclasses import dataclass, field
@dataclass
class CASPQuestion:
number: int
question: str
hint: str = ""
section: str = "" # e.g. "Validity", "Results", "Relevance"
is_screening: bool = False # screening Q — "No" → abandon appraisal
# ---------------------------------------------------------------------------
# Checklists
# ---------------------------------------------------------------------------
CHECKLISTS: dict[str, list[CASPQuestion]] = {
"Systematic Review": [
CASPQuestion(1,
"Did the review address a clearly focused question?",
"Consider PICO: population, intervention, comparator, outcome.",
"Validity", is_screening=True),
CASPQuestion(2,
"Did the authors look for the right type of papers?",
"Check databases searched, publication types included.",
"Validity", is_screening=True),
CASPQuestion(3,
"Do you think all the important, relevant studies were included?",
"Look for a comprehensive search strategy — CINAHL, MEDLINE, Cochrane etc.",
"Validity"),
CASPQuestion(4,
"Did the review's authors do enough to assess the quality of the included studies?",
"A quality checklist or tool (e.g. CASP, Cochrane RoB) should have been used.",
"Validity"),
CASPQuestion(5,
"If the results of the review have been combined, was it reasonable to do so?",
"Were studies similar enough to pool? Was heterogeneity addressed?",
"Results"),
CASPQuestion(6,
"What are the overall results of the review?",
"Is there a summary statistic (e.g. pooled relative risk, odds ratio, NNT)?",
"Results"),
CASPQuestion(7,
"How precise are the results?",
"Look for confidence intervals around the summary estimate.",
"Results"),
CASPQuestion(8,
"Can the results be applied to the local population?",
"Is the study population comparable to your patients / setting?",
"Relevance"),
CASPQuestion(9,
"Were all important outcomes considered?",
"Especially patient-centred outcomes relevant to nursing practice.",
"Relevance"),
CASPQuestion(10,
"Are the benefits worth the harms and costs?",
"Weigh clinical significance vs statistical significance.",
"Relevance"),
],
"RCT": [
CASPQuestion(1,
"Did the trial address a clearly focused issue?",
"Was the PICO clearly stated?",
"Validity", is_screening=True),
CASPQuestion(2,
"Was the assignment of patients to treatments randomised?",
"Look for: random number table, computer-generated, concealed allocation.",
"Validity", is_screening=True),
CASPQuestion(3,
"Were all of the patients who entered the trial properly accounted for at its conclusion?",
"Check for loss to follow-up >20%, intention-to-treat analysis.",
"Validity"),
CASPQuestion(4,
"Were patients, health workers and study personnel 'blind' to treatment?",
"Double-blind most rigorous — note if single- or open-label.",
"Validity"),
CASPQuestion(5,
"Were the groups similar at the start of the trial?",
"Check baseline characteristics table — age, sex, severity.",
"Validity"),
CASPQuestion(6,
"Aside from the experimental intervention, were the groups treated equally?",
"Co-interventions should be identical between arms.",
"Validity"),
CASPQuestion(7,
"How large was the treatment effect?",
"Absolute risk reduction (ARR), relative risk reduction (RRR), NNT.",
"Results"),
CASPQuestion(8,
"How precise was the estimate of the treatment effect?",
"95% confidence intervals — are they clinically acceptable?",
"Results"),
CASPQuestion(9,
"Can the results be applied to the local population?",
"Inclusion/exclusion criteria — does your patient fit?",
"Relevance"),
CASPQuestion(10,
"Were all clinically important outcomes considered?",
"Patient-reported outcomes, quality of life, nursing-sensitive indicators.",
"Relevance"),
CASPQuestion(11,
"Are the benefits worth the harms and costs?",
"Consider resource implications for nursing practice.",
"Relevance"),
],
"Cohort Study": [
CASPQuestion(1,
"Did the study address a clearly focused issue?",
"Population, exposure, outcome, and follow-up period clearly stated?",
"Validity", is_screening=True),
CASPQuestion(2,
"Was the cohort recruited in an acceptable way?",
"Representativeness of the source population.",
"Validity", is_screening=True),
CASPQuestion(3,
"Was the exposure accurately measured to minimise bias?",
"Objective vs self-reported exposure; blinded measurement.",
"Validity"),
CASPQuestion(4,
"Was the outcome accurately measured to minimise bias?",
"Objective outcome definition; blinded outcome assessors.",
"Validity"),
CASPQuestion(5,
"Have the authors identified all important confounding factors?",
"Confounders controlled for in the analysis? (age, sex, comorbidities)",
"Validity"),
CASPQuestion(6,
"Was the follow-up of subjects complete enough?",
">80% follow-up generally considered adequate.",
"Validity"),
CASPQuestion(7,
"What are the results of this study?",
"Relative risk (RR), hazard ratio (HR), absolute risk.",
"Results"),
CASPQuestion(8,
"How precise are the results?",
"95% confidence intervals — wide CIs = less certainty.",
"Results"),
CASPQuestion(9,
"Do you believe the results?",
"Dose-response relationship? Biologically plausible?",
"Results"),
CASPQuestion(10,
"Can the results be applied to the local population?",
"Compare study population characteristics to your patients.",
"Relevance"),
CASPQuestion(11,
"Do the results of this study fit with other available evidence?",
"Consistent with systematic reviews / other cohort studies?",
"Relevance"),
CASPQuestion(12,
"What are the implications for practice?",
"How does this change nursing assessment, intervention, or education?",
"Relevance"),
],
"Qualitative": [
CASPQuestion(1,
"Was there a clear statement of the aims of the research?",
"Research question / phenomenon of interest clearly defined?",
"Validity", is_screening=True),
CASPQuestion(2,
"Is a qualitative methodology appropriate?",
"Does the research seek to understand meaning, experience, or perspective?",
"Validity", is_screening=True),
CASPQuestion(3,
"Was the research design appropriate to address the aims of the research?",
"Grounded theory, phenomenology, ethnography, thematic analysis — fit for purpose?",
"Validity"),
CASPQuestion(4,
"Was the recruitment strategy appropriate to the aims of the research?",
"Purposive sampling? Rationale for selection clearly stated?",
"Validity"),
CASPQuestion(5,
"Was the data collected in a way that addressed the research issue?",
"Interviews, focus groups, observation — justified? Data saturation reached?",
"Validity"),
CASPQuestion(6,
"Has the relationship between researcher and participants been adequately considered?",
"Reflexivity addressed? Positionality of researcher stated?",
"Validity"),
CASPQuestion(7,
"Have ethical issues been taken into consideration?",
"Ethical approval, informed consent, confidentiality, data protection.",
"Validity"),
CASPQuestion(8,
"Was the data analysis sufficiently rigorous?",
"Audit trail? Member checking? Independent coding? Trustworthiness criteria?",
"Results"),
CASPQuestion(9,
"Is there a clear statement of findings?",
"Themes clearly described with supporting quotes?",
"Results"),
CASPQuestion(10,
"How valuable is the research?",
"Transferable to other settings? Implications for nursing practice?",
"Relevance"),
],
"Case-Control": [
CASPQuestion(1,
"Did the study address a clearly focused issue?",
"Exposure, disease/outcome, and population clearly defined?",
"Validity", is_screening=True),
CASPQuestion(2,
"Did the authors use an appropriate method to answer their question?",
"Is a case-control design the right choice for this research question?",
"Validity", is_screening=True),
CASPQuestion(3,
"Were the cases recruited in an acceptable way?",
"Clear case definition? Incident vs prevalent cases?",
"Validity"),
CASPQuestion(4,
"Were the controls selected in an acceptable way?",
"Controls from same source population as cases?",
"Validity"),
CASPQuestion(5,
"Was the exposure accurately measured to minimise bias?",
"Recall bias? Interviewer bias? Same methods for cases and controls?",
"Validity"),
CASPQuestion(6,
"Have the authors taken account of the potential confounding factors?",
"Matching or statistical adjustment for age, sex, comorbidities?",
"Validity"),
CASPQuestion(7,
"What are the results of this study?",
"Odds ratio (OR) with 95% CI is the key measure.",
"Results"),
CASPQuestion(8,
"How precise are the results?",
"Wide confidence intervals = high uncertainty.",
"Results"),
CASPQuestion(9,
"Do you believe the results?",
"Dose-response? Consistency with other evidence? Biological plausibility?",
"Results"),
CASPQuestion(10,
"Can the results be applied to the local population?",
"Were cases/controls representative of your patient population?",
"Relevance"),
CASPQuestion(11,
"What are the implications for practice?",
"Risk factor modification, screening, patient education implications.",
"Relevance"),
],
}
# ---------------------------------------------------------------------------
# Helpers
# ---------------------------------------------------------------------------
def detect_study_type(title: str, abstract: str = "") -> str:
"""Infer the most appropriate CASP checklist from study text."""
text = (title + " " + abstract).lower()
if any(kw in text for kw in ["systematic review", "meta-analysis", "meta analysis"]):
return "Systematic Review"
if any(kw in text for kw in ["randomized controlled", "randomised controlled", " rct ", "randomized trial"]):
return "RCT"
if any(kw in text for kw in ["cohort study", "cohort design", "prospective study", "retrospective cohort"]):
return "Cohort Study"
if any(kw in text for kw in ["case-control", "case control"]):
return "Case-Control"
if any(kw in text for kw in ["qualitative", "grounded theory", "phenomenolog", "ethnograph", "thematic analysis", "interviews"]):
return "Qualitative"
return "Systematic Review" # default to highest-level checklist
def get_checklist(study_type: str) -> list[CASPQuestion]:
return CHECKLISTS.get(study_type, CHECKLISTS["Systematic Review"])
def available_checklists() -> list[str]:
return list(CHECKLISTS.keys())
def score_to_quality(yes_count: int, total: int) -> tuple[str, str]:
"""Return (quality_label, colour) based on CASP score."""
if total == 0:
return "Not assessed", "secondary"
pct = yes_count / total
if pct >= 0.8:
return "High quality", "success"
if pct >= 0.6:
return "Moderate quality", "warning"
return "Low quality / poor reporting", "error"