Auto-Research PipelineA durable, human-gated pipeline for computational research
Research runb1eefce32671· 8 September 2026

Do children under 5 years have higher SARS-CoV-2 upper-respiratory viral loads (lower RT-PCR cycle threshold values) than adults, once testing setting and calendar time are accounted for?

CompleteArchived runEpidemiology & Public Health · Modelled on American Journal of Epidemiology

Paper

Testing Indication, Not Age: A Replication Attempt of the Reported SARS-CoV-2 Viral-Load Excess in Children Under 5 Years

Abstract

A widely cited 2020 report of a 4.5-cycle lower reverse-transcription polymerase chain reaction (RT-PCR) cycle threshold (Ct) in children under 5 years than in adults, read as a 10- to 100-fold viral-load excess, shaped debate on reopening childcare and schools. We attempted replication in de-identified records of 15,524 severe acute respiratory syndrome coronavirus 2 (SARS-CoV-2) RT-PCR tests from the Children's Hospital of Philadelphia in 2020; each person's first quantifiable positive specimen gave 786 individuals. Exposure was age group, outcome Ct in cycles. Crude mean Ct was 0.50 cycles higher in children aged 0-4 years than in adults aged 18 years or more (95% confidence interval (CI): -0.89, 1.89); after adjustment for testing stream, sex and calendar block it was -0.72 cycles (95% CI: -2.33, 0.88), reproduced by direct standardisation (-0.72; 95% CI: -2.29, 0.80). The adjusted risk ratio for a high-viral-load specimen (Ct < 25) was 1.22 (95% CI: 0.93, 1.61). These data exclude a 3-cycle deficit in young children and, a fortiori, the excess originally reported; the crude-to-adjusted sign reversal is generated by testing indication.

KeywordsCOVID-19SARS-CoV-2confounding factors, epidemiologiccycle thresholdselection biasviral loadchild, preschoolreplication studies

§Ask about this paper

Grounded in this run

Questions are answered from this run's record — the paper, the executed analysis, the data provenance and the referee report. Nothing else is consulted.

This run is finished, so the recorded paper cannot be rewritten. Questions are still answered from its record.

Pipeline

1.Literature review

Attempt 3Done

Literature review complete (live:agent:claude-opus-5): 10 key papers, 18 grounded sources, 6 open gaps.

Summary

Whether young children carry more SARS-CoV-2 RNA in the upper respiratory tract than adults became a policy question in 2020, when viral load was the only widely available proxy for infectiousness during debates about reopening schools and childcare. The literature divides into three positions. The first is anchored by Heald-Sargent et al. (2020), who compared 145 patients with mild-to-moderate COVID-19 tested within one week of symptom onset at a Chicago children's hospital and reported median cycle threshold (Ct) values of 6.5 in children under 5 years against 11.1 in children 5-17 years and 11.0 in adults, a roughly 4.5-cycle gap that they interpreted as a 10- to 100-fold excess of virus in the youngest children. The second position, represented by Madera et al. (2021) in more than five thousand cases, Baggio et al. (2021) restricted to the first five days after symptom onset, Chung et al. (2021) in community home-swab surveillance and Yonker et al. (2021) in 110 children, finds no material age difference; Chung et al. give the most directly comparable estimate, an adjusted difference of -0.7 cycles (95% CI -2.2 to 0.9) between symptomatic children and symptomatic adults, and show that symptom status rather than age drives Ct. The third position, from the largest study (Jones et al., 2021; 25,381 German cases), places the youngest subjects marginally lower, by 0.5 log10 units or less, and attributes part of that to swab size rather than biology.

The disagreement is epidemiologic rather than virological. Every one of these studies conditions on being tested and testing positive, so three biases dominate. Ct is a single snapshot of a trajectory, making days since infection the primary unmeasured confounder. Testing indication is nearly collinear with age in hospital laboratory records, because children arrive through emergency and inpatient streams while adults are screened at drive-through sites, so setting confounds the age contrast and may modify it. Conditioning on a positive test in a convenience sample can induce a collider association between age and viral load (Griffith et al., 2020; Hernan et al., 2004). On top of this, Ct is not a viral load: it depends on assay, target, specimen adequacy and collection technique, and the College of American Pathologists has cautioned explicitly against reading it quantitatively (Rhoads et al., 2021). Because specimen quality plausibly differs between a struggling toddler and a cooperative adult, the measurement error may be differential by age. The field's methodological toolkit -- effect estimates with compatibility intervals rather than significance tests, restriction or stratification by testing stream, one record per person, and quantitative bias analysis -- is well established but has rarely been applied to this specific contrast.

Key papers (10)

  1. Age-Related Differences in Nasopharyngeal Severe Acute Respiratory Syndrome Coronavirus 2 (SARS-CoV-2) Levels in Patients With Mild to Moderate Coronavirus Disease 2019 (COVID-19). Heald-Sargent T, Muller WJ, Zheng X, Rippe J, Patel AB, Kociolek LK; JAMA Pediatrics 174(9):902-903, 2020.
    The origin of the claim under test. In 145 patients tested within a week of symptom onset it reported median Ct 6.5 (IQR 4.8-12.0) in children under 5 years versus 11.1 (6.3-15.7) in children 5-17 and 11.0 (6.9-17.5) in adults on the Abbott m2000 platform, and read the roughly 4.5-cycle gap as a 10- to 100-fold viral excess in the youngest. It supplies the effect size that any replication must be powered to exclude.
  2. Nasopharyngeal SARS-CoV-2 viral loads in young children do not differ significantly from those in older children and adults. Madera S, Crawford E, Langelier C, Tran NK, Thornborrow E, Miller S, DeRisi JL; Scientific Reports 11:3044, 2021.
    The largest early US contradiction of the Heald-Sargent finding, using more than five thousand RT-PCR-confirmed cases across multiple centres and reporting no discernible difference in viral nucleic acid between young children and adults. It establishes that the discrepancy is not a matter of sample size alone.
  3. Comparison of Symptoms and RNA Levels in Children and Adults With SARS-CoV-2 Infection in the Community Setting. Chung E, Chow EJ, Wilcox NC, et al.; JAMA Pediatrics 175(10):e212025, 2021.
    The most directly comparable published estimate and the model for how the contrast should be reported: an adjusted mean Ct difference of -0.7 cycles (95% CI -2.2 to 0.9) for symptomatic children versus symptomatic adults and -0.6 (95% CI -4.0 to 2.8) for asymptomatic comparisons, against a much larger symptomatic-versus-asymptomatic contrast of about -3 cycles in both age groups. It shows that clinical presentation, not age, structures the Ct distribution.
  4. Estimating infectiousness throughout SARS-CoV-2 infection course. Jones TC, Biele G, Muhlemann B, et al.; Science 373(6551):eabi5273, 2021.
    The best-powered study in the field, with 25,381 German cases including 6,110 from test centres attended by presymptomatic, asymptomatic and mildly symptomatic subjects. It places the youngest subjects at most 0.5 log10 units (under about 1.7 cycles) below older subjects and explicitly attributes part of the gap to smaller swab sizes, framing specimen quality as an age-differential measurement problem rather than a nuisance.
  5. Severe Acute Respiratory Syndrome Coronavirus 2 (SARS-CoV-2) Viral Load in the Upper Respiratory Tract of Children and Adults With Early Acute Coronavirus Disease 2019 (COVID-19). Baggio S, L'Huillier AG, Yerly S, et al.; Clinical Infectious Diseases 73(1):148-150, 2021.
    Demonstrates the standard confounding control in this literature -- restriction to the first five days after symptom onset -- in 53 children and 352 adults in Geneva, and finds no significant difference. It is the template for handling time since infection when that variable is recorded.
  6. Comparison of Upper Respiratory Viral Load Distributions in Asymptomatic and Symptomatic Children Diagnosed with SARS-CoV-2 Infection in Pediatric Hospital Testing Programs. Kociolek LK, Muller WJ, Yee R, et al.; Journal of Clinical Microbiology 59(1):e02593-20, 2020.
    The reference for how much the testing programme itself -- asymptomatic screening versus symptomatic diagnostic testing -- shifts the viral-load distribution within paediatric hospitals. It is the direct justification for treating testing stream as a confounder rather than a design detail.
  7. College of American Pathologists (CAP) Microbiology Committee Perspective: Caution Must Be Used in Interpreting the Cycle Threshold (Ct) Value. Rhoads D, Peaper DR, She RC, Nolte FS, Wojewoda CM, Anderson NW, Pritt BS; Clinical Infectious Diseases 72(10):e685-e686, 2021.
    The authoritative statement that Ct is not a quantitative viral load: it depends on assay, target gene, specimen adequacy, collection technique and transport. It is the basis for treating Ct as a proxy measured with error, and for the concern that the error may differ systematically between toddlers and adults.
  8. Collider bias undermines our understanding of COVID-19 disease risk and severity. Griffith GJ, Morris TT, Tudball MJ, et al.; Nature Communications 11:5749, 2020.
    The canonical COVID-19 treatment of selection bias in samples defined by having been tested. Since both age and viral load plausibly influence the probability of being tested and of testing positive, conditioning on a positive test can create an age-Ct association in the sample that does not exist in the source population.
  9. Bias due to misclassification in the estimation of relative risk. Copeland KT, Checkoway H, McMichael AJ, Holbrook RH; American Journal of Epidemiology 105(5):488-495, 1977.
    Supplies the classical result that non-differential misclassification of a dichotomous exposure biases the estimate toward the null. This is the tool needed when the analytic data have been perturbed for de-identification, because it bounds the direction in which such perturbation can move an estimate.
  10. Estimating epidemiologic dynamics from cross-sectional viral load distributions. Hay JA, Kennedy-Shaffer L, Kanjilal S, Lennon NJ, Gabriel SB, Lipsitch M, Mina MJ; Science 373(6552):eabh0635, 2021.
    Shows that the population distribution of Ct values shifts systematically with the epidemic growth rate. It establishes calendar time as a confounder of any Ct comparison spanning a period of changing incidence, and therefore as a variable that must be adjusted for in age contrasts drawn from surveillance or laboratory records.

Methods in use

  • Ct treated as a continuous outcome on the cycle scale (roughly 3.3 cycles per log10 of RNA copies), with age-group contrasts reported as differences in mean Ct with 95% confidence intervals rather than as p-values
  • Linear regression and ANCOVA adjusting for testing setting, sex and calendar period; quantile (median) regression when the Ct distribution is skewed or left-censored
  • Non-parametric group comparisons (Wilcoxon rank-sum, Kruskal-Wallis) in the smaller descriptive studies
  • Dichotomisation of Ct at a high-viral-load cut-point (commonly 25 or 30 cycles) with reporting of risk differences and risk ratios, motivated by culture-positivity thresholds
  • Restriction to a fixed window after symptom onset, or adjustment for symptom status, as the standard control for confounding by time since infection
  • Restriction or stratification by a single homogeneous testing stream (drive-through, emergency, inpatient, pre-procedural screening) to control confounding by testing indication
  • One record per person (first positive test) to avoid within-person correlation, or cluster-robust standard errors when repeat tests are retained
  • Bootstrap and heteroscedasticity-robust standard errors for skewed outcomes and unequal group variances
  • Directed acyclic graphs and the structural theory of selection bias to distinguish confounding from collider stratification bias in samples conditioned on testing
  • Quantitative bias analysis for exposure misclassification and unmeasured confounding, following good-practice guidance, rather than narrative limitation sections

Open gaps

  • No study has reported the crude and testing-stream-stratified child-adult Ct contrasts side by side within a single laboratory using a single assay, so readers cannot see how much of the reported age gradient is generated by testing indication rather than by age itself; a Simpson-type reversal between the crude and stratified estimates would be substantively important.
  • The 2020 claim of a 10- to 100-fold viral excess in children under 5 years has never been directly tested for replication in an independent paediatric hospital population of the kind that generated it, with the confounding structure made explicit.
  • The field reports repeated statements of no significant difference rather than intervals precise enough to exclude the originally claimed effect; what is needed is an estimate whose 95% confidence interval rules out a difference of about 4.5 cycles, which is a question of precision rather than of statistical significance.
  • Identifying assumptions are almost never stated. Because days since symptom onset is absent from laboratory extracts, it should be explicit that such contrasts are associations conditional on presenting for testing, and that a causal reading requires no unmeasured confounding by time since onset and severity given setting and calendar time, no age-differential specimen-quality error, and no selection into the tested-and-positive sample that depends jointly on age and viral load.
  • De-identified public laboratory extracts are frequently perturbed before release, yet the consequences of that perturbation for effect estimation are essentially never analysed; applying the classical misclassification results to bound the direction of the resulting bias would be methodologically useful well beyond this question.
  • Calendar time is known to shift the population Ct distribution with the epidemic growth rate, but age contrasts in laboratory records are rarely adjusted for calendar period, leaving open how much of the between-study heterogeneity reflects differing epidemic phases at the time of sampling.
Grounded search sources (18) · mode: live:agent:claude-opus-5

2.Ideation

Attempt 2Done

3 candidate ideas generated; selected: “Testing indication, not age: a replication attempt of the reported viral-load excess in children under 5 years in 2020 paediatric hospital RT-PCR records”.

  1. Idea 1Selected

    Testing indication, not age: a replication attempt of the reported viral-load excess in children under 5 years in 2020 paediatric hospital RT-PCR records

    Hypothesis. Among SARS-CoV-2 RT-PCR-positive specimens collected at a single paediatric hospital laboratory, children under 5 years have a mean cycle threshold at least 3 cycles lower (i.e. viral load at least about 8-fold higher) than adults aged 18 years or more, and this difference persists after adjustment for testing stream (drive-through versus on-site collection, order-set versus individually ordered test, patient class), sex and calendar day. The hypothesis is refuted if the adjusted difference in mean Ct for the under-5 versus 18-and-over contrast has a 95% confidence interval that excludes -3 cycles.

    Dataset. COVID-19 PCR testing at the Children's Hospital of Philadelphia, 2020 chop_covid_testing

    Test plan, novelty and risk

    Test plan. Dataset: chop_covid_testing (15,524 RT-PCR tests, pandemic days 4-107, 2020). Sample filters, applied in this order and each reported with the number of records lost: keep result == 'positive' (865 records; drop the 14,358 negatives, whose ct_result is the fixed non-detection ceiling of 45, and the 301 invalid results); drop records with missing ct_result (5) and with ct_result >= 45 (3), which are non-quantifiable; keep one record per subject_id, the earliest by pan_day and then by test_id, to remove within-person correlation from repeat testing. Expected analytic sample about 780-790 specimens from as many individuals. Exposure: age group from the `age` field, primary contrast 0-4 years versus 18 years and over, with 5-11 and 12-17 years carried as intermediate categories and a per-10-year linear trend as a secondary parameterisation. Outcome: ct_result in cycles, treated as continuous (lower Ct = higher viral load; roughly 3.3 cycles per log10 RNA copies). Covariates for confounding by testing indication and epidemic phase: drive_thru_ind (0/1), orderset (0/1), patient_class collapsed to inpatient / emergency / outpatient-or-observation / not-recorded, gender, and calendar time as a restricted set of pandemic-period indicators (roughly monthly blocks of pan_day). Estimators: (1) crude difference in mean Ct by age group with Welch (unequal-variance) 95% confidence intervals; (2) ordinary least squares of ct_result on age group and covariates with heteroscedasticity-robust (HC3) standard errors, reporting the adjusted mean difference and 95% CI for each age group against the 18-and-over reference; (3) direct standardisation of age-group mean Ct to the joint distribution of testing stream and calendar block in the whole positive sample, with nonparametric bootstrap percentile 95% CIs (2,000 resamples, fixed seed); (4) a dichotomous high-viral-load outcome (Ct < 25) analysed with a log-binomial or Poisson-with-robust-variance model to give a risk ratio and risk difference with 95% CIs; (5) median regression as a distribution-robust check. Stratified analysis: repeat the primary contrast within the drive-through stream and within the on-site stream separately, and report the two stratum-specific estimates alongside the crude one, so that any Simpson-type reversal is visible. Bias analysis: because the released records were de-identified by permutation, apply the classical result for non-differential misclassification of a dichotomous exposure to bound the direction of the attenuation, and report the factor by which the observed contrast would have to be attenuated to be compatible with a -4.5 cycle true difference. Refutation criteria: the hypothesis is refuted if the adjusted under-5 versus adult mean difference and its 95% CI lie entirely above -3 cycles; it is supported if the CI lies entirely below -3; it is inconclusive if the CI spans -3.

    Novelty. The literature contains one small paediatric-hospital study reporting a 4.5-cycle deficit in children under 5, and several larger community or multi-centre studies reporting no material difference, but no one has attempted the replication in a second paediatric hospital laboratory while making the confounding structure explicit. Crucially, no published analysis reports the crude and testing-stream-stratified contrasts side by side, even though in a children's hospital the age variable is almost perfectly confounded with reason for testing: children arrive through emergency and inpatient streams, adults are largely staff and caregivers swabbed at a drive-through site. The contribution is a precise interval rather than another 'no significant difference' statement, plus an explicit statement of the assumptions under which the contrast could be read causally.

    Expected outcome. The crude difference is expected to be small and in the opposite direction to the hypothesis, on the order of +1 cycle (children under 5 having slightly lower viral load than adults), with a 95% CI roughly one and a quarter cycles wide on each side, and the setting-stratified estimates are expected to differ from the crude estimate and possibly to change sign, because drive-through collection and order-set testing are strongly associated with both age and Ct. The most likely conclusion is that the hypothesis is refuted: the data will exclude a 3-cycle deficit in the under-5s, and by extension the 10- to 100-fold excess originally claimed, while being compatible with a difference of at most one to two cycles in either direction.

    Main risk. Days since symptom onset and symptom status are not recorded, so the age contrast remains confounded by where in the infection course each group is sampled; testing stream is only a proxy for that. The released data were de-identified by permutation, which for a dichotomous exposure biases toward the null and so cannot manufacture a positive point estimate where a large negative one is true, but does mean the interval should be read as a bound rather than a precise adjusted estimate. Finally, the sample is everyone tested at one hospital, so conditioning on a positive test can induce collider bias if both age and viral load affect the probability of being tested.

  2. Idea 2

    Does the testing stream explain the age gradient in SARS-CoV-2 test positivity at a paediatric hospital?

    Hypothesis. The crude increase in RT-PCR test positivity with age observed across a paediatric hospital's 2020 testing programme is at least halved once testing stream (drive-through, order-set, patient class) and calendar period are adjusted for; that is, the adjusted odds ratio for positivity comparing adults aged 18 and over with children under 5 is less than half the crude odds ratio on the log scale. The hypothesis is refuted if the adjusted log odds ratio retains more than half of the crude log odds ratio.

    Dataset. COVID-19 PCR testing at the Children's Hospital of Philadelphia, 2020 chop_covid_testing

    Test plan, novelty and risk

    Test plan. Dataset: chop_covid_testing. Sample: all 15,223 tests with a valid result after excluding the 301 invalid results; report the count lost. Outcome: positive versus negative. Exposure: age group (0-4, 5-11, 12-17, 18-49, 50 and over). Estimator: logistic regression with cluster-robust standard errors by subject_id, first crude and then adjusted for drive_thru_ind, orderset, patient_class, gender and monthly blocks of pan_day; report crude and adjusted odds ratios with 95% CIs, plus risk differences from marginal standardisation of the fitted adjusted model with bootstrap CIs. Refutation: the adjusted log odds ratio for 18-and-over versus 0-4 remains above half the crude value.

    Novelty. Age gradients in test positivity are routinely reported from laboratory extracts and routinely read as gradients in infection risk, but positivity in a hospital testing programme is jointly determined by who is tested and why. Decomposing how much of the gradient survives adjustment for testing stream is a direct demonstration of indication-driven bias in a familiar surveillance statistic.

    Expected outcome. A crude gradient from roughly 4 percent positivity in children under 5 to roughly 9 percent in adults aged 50 and over, attenuating substantially but probably not by half after adjustment, so the hypothesis is likely to be refuted while still showing that a material part of the gradient is indication-driven.

    Main risk. Testing stream is measured coarsely, so residual confounding by indication is certain, and the analysis cannot separate genuine age differences in infection risk from age differences in exposure and in the threshold for being tested. The estimand is also not a population prevalence, which limits its interest.

  3. Idea 3

    Confounding by the sick-quitter effect: how much of the crude association between smoking cessation and 10-year mortality is explained by baseline age and illness?

    Hypothesis. In the NHEFS cohort, the crude 10-year all-cause mortality risk in those who quit smoking exceeds that in continuing smokers by at least 5 percentage points, and adjustment for baseline age, sex, education, smoking history and prevalent disease removes at least three quarters of that crude risk difference. The hypothesis is refuted if the standardised risk difference retains more than a quarter of the crude risk difference.

    Dataset. NHANES I Epidemiologic Follow-up Study smoking cessation cohort nhefs_cohort

    Test plan, novelty and risk

    Test plan. Dataset: nhefs_cohort (1,629 smokers). Exposure: qsmk. Outcome: death by 1982. Estimator: crude risk difference and risk ratio with 95% CIs from a binomial model; then standardisation (parametric g-formula) over baseline age, sex, race, education, smokeintensity, smokeyrs, exercise, active and the disease-history indicators, with nonparametric bootstrap 95% CIs (fixed seed); inverse-probability-of-treatment weighted estimates as a cross-check; E-value for the standardised risk ratio. Refutation: the standardised risk difference retains more than a quarter of the crude value.

    Novelty. The sick-quitter phenomenon is folklore in tobacco epidemiology but is usually asserted rather than quantified as the fraction of a crude association removed by adjustment. Reporting the crude, standardised and IP-weighted risk differences side by side with an E-value gives an explicit accounting.

    Expected outcome. A crude excess mortality risk in quitters of roughly 5 to 10 percentage points, driven almost entirely by quitters being older and sicker, with the standardised risk difference close to zero and a wide interval.

    Main risk. The exposure-outcome contrast is heavily studied with this exact dataset and the direction of confounding is well known, so the study risks being a demonstration rather than a discovery. With about 300 deaths the standardised estimate will be imprecise, and reverse causation, illness causing cessation, is indistinguishable from confounding without information on the timing of quitting.

Ranking rationale

Idea 1 is ranked first because it takes a specific, published, quantified claim (a roughly 4.5-cycle viral-load deficit in children under 5) and subjects it to a genuine replication attempt in independent data of the same type, in a sample large enough that the resulting confidence interval can exclude the claimed effect rather than merely fail to detect it; it also has an internal methodological payoff, since testing stream is almost collinear with age in a children's hospital and the crude and stratified contrasts can be shown side by side. Idea 2 uses the same dataset but asks a weaker question, because a positivity gradient in a hospital convenience sample has no clean target parameter and residual confounding by indication cannot be bounded. Idea 3 is competently answerable and would produce a clean quantitative accounting, but the NHEFS smoking-cessation contrast is the single most analysed exposure-outcome pair in the causal-inference teaching literature, so the direction and rough magnitude of the confounding are already documented and the study would be a demonstration rather than a test.

3.Experimentation

Attempt 3Done

Experiment succeeded in 1 round (3.878s).

Succeeded1 round · exit 0 · 3.878s

Data provenance

Datasetchop_covid_testing

COVID-19 PCR testing at the Children's Hospital of Philadelphia, 2020

Source
R package 'medicaldata', mirrored by the Rdatasets archive; deidentified records from the Children's Hospital of Philadelphia
Citation
Higgins, P.D.R. (2021) medicaldata: Data Package for Medical Datasets. R package version 0.2.0. https://CRAN.R-project.org/package=medicaldata. Data donated by Amrom E. Obstfeld; deidentified, time-shifted and value-permuted records of SARS-CoV-2 RT-PCR testing at the Children's Hospital of Philadelphia in 2020. There is no source publication for this dataset -- the package's source field is a data-donation acknowledgement only.
Licence
Redistributed in the R package 'medicaldata' under MIT (LICENSE file: copyright 2021, medicaldata authors) via the Rdatasets archive. No separate data licence is stated. The records are real patient data that have been deidentified, time-shifted and permuted -- not synthetic.
File
https://vincentarelbundock.github.io/Rdatasets/csv/medicaldata/covid_testing.csv
Observations
15,524
Variables (15)
subject_id, gender, pan_day, test_id, clinic_name, result, demo_group, age, drive_thru_ind, ct_result, orderset, payor_group, patient_class, col_rec_tat, rec_ver_tat
Units
pan_day is the day of the pandemic period on which the test was collected, running from 4 to 107. result is 'negative' (14,358), 'positive' (865) or 'invalid' (301). ct_result is the RT-PCR cycle threshold, where lower values mean higher viral load and the value is only interpretable for positive tests. age is in years (0 for infants). col_rec_tat is collection-to-receipt turnaround and rec_ver_tat receipt-to-verification turnaround, both in hours. drive_thru_ind and orderset are 0/1 indicators.
Retrieved
8 Sept 2026, 15:46
Checksum
sha256 fc7d7c522749144b…

Real, publicly available data — downloaded and checksum-verified before the analysis ran, never simulated.

Result (RESULT_JSON)

{
  "sample": {
    "rows_loaded": 15524,
    "result_negative": 14358,
    "result_invalid": 301,
    "result_positive": 865,
    "dropped_ct_missing": 5,
    "dropped_ct_at_ceiling_45": 3,
    "positive_quantifiable_tests": 857,
    "dropped_repeat_positive_tests": 71,
    "analytic_n": 786
  },
  "n_analysed": 786,
  "n_individuals": 786,
  "pan_day_min": 10,
  "pan_day_max": 107,
  "overall_mean_ct": 28.984796437659035,
  "overall_sd_ct": 7.2913358947784115,
  "overall_median_ct": 28.365,
  "descriptives_by_age_group": {
    "0-4": {
      "n": 186,
      "mean_ct": 29.188064516129035,
      "sd_ct": 8.048353299169191,
      "median_ct": 28.99,
      "p25_ct": 21.595,
      "p75_ct": 36.95,
      "pct_drive_thru": 0.3602150537634409,
      "pct_orderset": 0.6827956989247311,
      "pct_emergency_or_inpatient": 0.41935483870967744,
      "pct_male": 0.3709677419354839,
      "median_pan_day": 32,
      "n_hi_vl": 73,
      "risk_hi_vl": 0.3924731182795699
    },
    "5-11": {
      "n": 117,
      "mean_ct": 28.92119658119658,
      "sd_ct": 7.602818121159843,
      "median_ct": 28.19,
      "p25_ct": 22.18,
      "p75_ct": 36.2,
      "pct_drive_thru": 0.49572649572649574,
      "pct_orderset": 0.8290598290598291,
      "pct_emergency_or_inpatient": 0.3504273504273504,
      "pct_male": 0.5128205128205128,
      "median_pan_day": 53,
      "n_hi_vl": 44,
      "risk_hi_vl": 0.37606837606837606
    },
    "12-17": {
      "n": 168,
      "mean_ct": 29.358333333333334,
      "sd_ct": 6.909778861307767,
      "median_ct": 28.57,
      "p25_ct": 23.51,
      "p75_ct": 36.095,
      "pct_drive_thru": 0.4523809523809524,
      "pct_orderset": 0.8452380952380952,
      "pct_emergency_or_inpatient": 0.2916666666666667,
      "pct_male": 0.5297619047619048,
      "median_pan_day": 84.5,
      "n_hi_vl": 57,
      "risk_hi_vl": 0.3392857142857143
    },
    "18+": {
      "n": 315,
      "mean_ct": 28.689174603174603,
      "sd_ct": 6.91443868827219,
      "median_ct": 27.96,
      "p25_ct": 22.744999999999997,
      "p75_ct": 35.065,
      "pct_drive_thru": 0.7968253968253968,
      "pct_orderset": 0.8507936507936508,
      "pct_emergency_or_inpatient": 0.08888888888888889,
      "pct_male": 0.49523809523809526,
      "median_pan_day": 71,
      "n_hi_vl": 120,
      "risk_hi_vl": 0.380952380952381
    }
  },
  "crude_mean_ct_difference_vs_18plus": {
    "0-4": {
      "diff": 0.4988899129544322,
      "lcl": -0.8919687673791592,
      "ucl": 1.8897485932880236,
      "se": 0.7071308833828485
    },
    "5-11": {
      "diff": 0.23202197802197588,
      "lcl": -1.3530744420513237,
      "ucl": 1.8171183980952752,
      "se": 0.8036276920737634
    },
    "12-17": {
      "diff": 0.6691587301587347,
      "lcl": -0.6295771185357264,
      "ucl": 1.967894578853196,
      "se": 0.6602823342946575
    }
  },
  "adjusted_mean_ct_difference_vs_18plus_hc3": {
    "0-4": {
      "diff": -0.723154072664272,
      "lcl": -2.327816122348293,
      "ucl": 0.8815079770197491,
      "se": 0.8187201715650853
    },
    "5-11": {
      "diff": 0.06255102415590841,
      "lcl": -1.6605094407749872,
      "ucl": 1.785611489086804,
      "se": 0.8791286363025937
    },
    "12-17": {
      "diff": 0.7544298105256146,
      "lcl": -0.6384289409010113,
      "ucl": 2.147288561952241,
      "se": 0.7106552785731362
    }
  },
  "standardised_mean_ct_difference_vs_18plus_bootstrap": {
    "0-4": {
      "diff": -0.7231540726642685,
      "lcl": -2.2860773544572948,
      "ucl": 0.8043939292408588
    },
    "5-11": {
      "diff": 0.06255102415590841,
      "lcl": -1.7068562935186748,
      "ucl": 1.6454540614319817
    },
    "12-17": {
      "diff": 0.7544298105256182,
      "lcl": -0.5879355687201818,
      "ucl": 2.1062232909419794
    }
  },
  "adjusted_age_trend_per_10_years": {
    "diff_per_10y": 0.04969227199744353,
    "lcl": -0.3314207832601781,
    "ucl": 0.4308053272550651
  },
  "median_regression_difference_vs_18plus": {
    "0-4": {
      "diff": 0.06500099998226005,
      "lcl": -2.57461669981893,
      "ucl": 2.7046186997834503
    },
    "5-11": {
      "diff": -0.30000000011887096,
      "lcl": -3.198579120519065,
      "ucl": 2.5985791202813227
    },
    "12-17": {
      "diff": 0.5360094762145309,
      "lcl": -1.8910031514170311,
      "ucl": 2.963022103846093
    }
  },
  "high_viral_load_ct_lt_25_risk_ratio_vs_18plus": {
    "0-4": {
      "rr": 1.2246902208206631,
      "lcl": 0.9309446906756556,
      "ucl": 1.6111227143743636
    },
    "5-11": {
      "rr": 1.041027766121899,
      "lcl": 0.7712503449060434,
      "ucl": 1.4051712482135437
    },
    "12-17": {
      "rr": 0.8697152728174202,
      "lcl": 0.6674614426315144,
      "ucl": 1.1332559567631355
    }
  },
  "high_viral_load_ct_lt_25_risk_difference_vs_18plus": {
    "0-4": {
      "rd": 0.07900865055029616,
      "lcl": -0.026674555575315752,
      "ucl": 0.18822945518491585
    },
    "5-11": {
      "rd": 0.014329323038268171,
      "lcl": -0.09401361421521336,
      "ucl": 0.13230651811216815
    },
    "12-17": {
      "rd": -0.048459520367670206,
      "lcl": -0.14062457738971176,
      "ucl": 0.041621085693551454
    }
  },
  "stratified_by_testing_stream_0_4_vs_18plus": {
    "drive_thru": {
      "diff": -0.7839442231075715,
      "lcl": -2.8555335113529425,
      "ucl": 1.2876450651377995,
      "se": 1.0433874950548527,
      "n_0_4": 67,
      "n_18plus": 251,
      "mean_ct_0_4": 27.52,
      "mean_ct_18plus": 28.30394422310757
    },
    "on_site": {
      "diff": -0.07277310924370184,
      "lcl": -2.397294571398226,
      "ucl": 2.2517483529108224,
      "se": 1.1757821223100653,
      "n_0_4": 119,
      "n_18plus": 64,
      "mean_ct_0_4": 30.1272268907563,
      "mean_ct_18plus": 30.200000000000003
    }
  },
  "interaction_age0_4_x_drive_thru": {
    "diff": -1.4828106919184378,
    "lcl": -4.221608253872865,
    "ucl": 1.255986870035989
  },
  "sensitivity_all_positive_tests_cluster_robust": {
    "n_tests": 857,
    "n_subjects": 786,
    "diff": -0.1993512518837406,
    "lcl": -1.6376602095456312,
    "ucl": 1.23895770577815
  },
  "sensitivity_exclude_age_over_100": {
    "n": 785,
    "dropped": 1,
    "diff": -0.678600107562275,
    "lcl": -2.2827690551257738,
    "ucl": 0.925568840001224
  },
  "age_variable_internal_validity_check": {
    "positivity_by_age_group": {
      "0-4": {
        "n_tests": 5754,
        "n_positive": 220,
        "positivity": 0.03823427181091415
      },
      "5-11": {
        "n_tests": 2833,
        "n_positive": 128,
        "positivity": 0.04518178609248147
      },
      "12-17": {
        "n_tests": 2425,
        "n_positive": 175,
        "positivity": 0.07216494845360824
      },
      "18+": {
        "n_tests": 4211,
        "n_positive": 342,
        "positivity": 0.08121586321538826
      }
    },
    "adjusted_rr_positive_0_4_vs_18plus": 0.4931218787204185,
    "lcl": 0.4095220339925216,
    "ucl": 0.5937877991619755
  },
  "bias_analysis": {
    "attenuation_needed_for_true_minus4p5_at_point": 0.1607009050365049,
    "attenuation_needed_for_true_minus4p5_at_lcl": 0.517292471632954,
    "nondifferential_attenuation_could_reconcile_lcl": true,
    "bias_required_to_reach_minus3_cycles": 2.276845927335728,
    "u_ct_effect_needed_if_prevalence_gap_0p5": 4.553691854671456,
    "u_prevalence_gap_needed_if_ct_effect_5cycles": 0.4553691854671456
  },
  "fold_change_translation": {
    "adjusted_fold_higher_viral_load_0_4_vs_18plus": 1.6507871034748185,
    "lcl": 0.5427997731688575,
    "ucl": 5.020448046781037,
    "claimed_fold_in_literature": 22.62741699796952,
    "log10_copies_difference_point": 0.2191375977770521,
    "log10_copies_difference_lcl": -0.267123629399924,
    "log10_copies_difference_ucl": 0.7053988249540283
  },
  "hypothesis_threshold_cycles": -3,
  "claimed_literature_difference_cycles": -4.5,
  "hypothesis_refuted": true,
  "hypothesis_supported": false,
  "n_bootstrap": 2000,
  "seed": 20200401
}
Experiment script · experiment_v1.py
"""Are RT-PCR cycle thresholds lower in children under 5 than in adults?
Real data: SARS-CoV-2 RT-PCR records, Children's Hospital of Philadelphia, 2020
(medicaldata::covid_testing via Rdatasets), loaded from disk - never simulated."""
import json
import numpy as np
import pandas as pd
from scipy import stats
from statsmodels.regression.quantile_regression import QuantReg
from dataset import load

SEED, N_BOOT, HI_CUT = 20200401, 2000, 25.0
CLAIMED, REFUTE = -4.5, -3.0
AGE_BINS = [-0.001, 4.999, 11.999, 17.999, 1000.0]
LABS, REF = ["0-4", "5-11", "12-17", "18+"], "18+"
SETLEV = ["not recorded", "emergency", "inpatient", "outpatient/observation", "not applicable"]
BLKLEV = ["d04-33", "d34-63", "d64-93", "d94-107"]
Z = stats.norm.ppf(0.975)


def collapse(x):
    if pd.isna(x):
        return "not recorded"
    return {"inpatient": "inpatient", "emergency": "emergency",
            "not applicable": "not applicable"}.get(x, "outpatient/observation")


def prep(f):
    f = f.copy()
    f["ageg"] = pd.cut(f["age"], bins=AGE_BINS, labels=LABS).astype(str)
    f["setting"] = f["patient_class"].map(collapse)
    f["block"] = pd.cut(f["pan_day"], bins=[3, 33, 63, 93, 108], labels=BLKLEV).astype(str)
    return f


def design(f, age=True, interact=False):
    p = [pd.Series(1.0, index=f.index, name="const")]
    if age:
        p += [(f["ageg"] == a).astype(float).rename("age_" + a) for a in LABS if a != REF]
    p.append(f["drive_thru_ind"].astype(float).rename("drive_thru"))
    p.append(f["orderset"].astype(float).rename("orderset"))
    p += [(f["setting"] == s).astype(float).rename("set_" + s) for s in SETLEV[1:]]
    p.append((f["gender"] == "male").astype(float).rename("male"))
    p += [(f["block"] == b).astype(float).rename("blk_" + b) for b in BLKLEV[1:]]
    if interact:
        p.append(((f["ageg"] == "0-4") * f["drive_thru_ind"]).astype(float).rename("age04_x_dt"))
    X = pd.concat(p, axis=1)
    return X.values.astype(float), list(X.columns)


def ols(X, y, hc3=False):
    A = np.linalg.pinv(X.T @ X)
    b = A @ (X.T @ y)
    if not hc3:
        return b, None
    r = y - X @ b
    h = np.clip(np.einsum("ij,jk,ik->i", X, A, X), 0, 0.999)
    u = r / (1.0 - h)
    V = A @ (X.T @ (X * (u ** 2)[:, None])) @ A
    return b, np.sqrt(np.diag(V))


def logit_fit(X, y, iters=60):
    b = np.zeros(X.shape[1])
    for _ in range(iters):
        p = 1.0 / (1.0 + np.exp(-np.clip(X @ b, -30, 30)))
        w = np.clip(p * (1 - p), 1e-8, None)
        nb = b + np.linalg.pinv(X.T @ (X * w[:, None])) @ (X.T @ (y - p))
        if np.max(np.abs(nb - b)) < 1e-9:
            return nb
        b = nb
    return b


def poisson_robust(X, y, iters=80):
    b = np.zeros(X.shape[1])
    b[0] = np.log(max(y.mean(), 1e-6))
    for _ in range(iters):
        mu = np.exp(np.clip(X @ b, -30, 30))
        nb = b + np.linalg.pinv(X.T @ (X * mu[:, None])) @ (X.T @ (y - mu))
        if np.max(np.abs(nb - b)) < 1e-10:
            b = nb
            break
        b = nb
    mu = np.exp(np.clip(X @ b, -30, 30))
    A = np.linalg.pinv(X.T @ (X * mu[:, None]))
    V = A @ (X.T @ (X * ((y - mu) ** 2)[:, None])) @ A
    return b, np.sqrt(np.diag(V))


def gcomp(X, b, idx, link):
    Xc = X.copy()
    for j in idx.values():
        Xc[:, j] = 0.0
    f = (lambda M: M @ b) if link == "id" else (lambda M: 1 / (1 + np.exp(-np.clip(M @ b, -30, 30))))
    out = {REF: float(np.mean(f(Xc)))}
    for a, j in idx.items():
        Xg = Xc.copy()
        Xg[:, j] = 1.0
        out[a] = float(np.mean(f(Xg)))
    return out


def welch(a, b):
    va, vb = np.var(a, ddof=1) / len(a), np.var(b, ddof=1) / len(b)
    m, se = float(np.mean(a) - np.mean(b)), float(np.sqrt(va + vb))
    dfree = (va + vb) ** 2 / (va ** 2 / (len(a) - 1) + vb ** 2 / (len(b) - 1))
    t = stats.t.ppf(0.975, dfree)
    return {"diff": m, "lcl": m - t * se, "ucl": m + t * se, "se": se}


def fold(diff):
    return float(2.0 ** (-diff))


raw = load()
counts = {"rows_loaded": int(len(raw)),
          "result_negative": int((raw["result"] == "negative").sum()),
          "result_invalid": int((raw["result"] == "invalid").sum()),
          "result_positive": int((raw["result"] == "positive").sum())}
d = raw[raw["result"] == "positive"].copy()
counts["dropped_ct_missing"] = int(d["ct_result"].isna().sum())
d = d[d["ct_result"].notna()]
counts["dropped_ct_at_ceiling_45"] = int((d["ct_result"] >= 45).sum())
d = d[d["ct_result"] < 45]
counts["positive_quantifiable_tests"] = int(len(d))
d = d.sort_values(["pan_day", "subject_id"], kind="mergesort")
counts["dropped_repeat_positive_tests"] = int(len(d) - d["subject_id"].nunique())
d = prep(d.drop_duplicates("subject_id", keep="first").reset_index(drop=True))
n = len(d)
counts["analytic_n"] = int(n)
d["hi"] = (d["ct_result"] < HI_CUT).astype(float)
y = d["ct_result"].values.astype(float)
print("analysed", n, "specimens from", d["subject_id"].nunique(), "individuals")

desc = {}
for a in LABS:
    s = d[d["ageg"] == a]
    desc[a] = {"n": int(len(s)), "mean_ct": float(s["ct_result"].mean()),
               "sd_ct": float(s["ct_result"].std(ddof=1)), "median_ct": float(s["ct_result"].median()),
               "p25_ct": float(np.percentile(s["ct_result"], 25)),
               "p75_ct": float(np.percentile(s["ct_result"], 75)),
               "pct_drive_thru": float(s["drive_thru_ind"].mean()),
               "pct_orderset": float(s["orderset"].mean()),
               "pct_emergency_or_inpatient": float(s["setting"].isin(["emergency", "inpatient"]).mean()),
               "pct_male": float((s["gender"] == "male").mean()),
               "median_pan_day": float(s["pan_day"].median()),
               "n_hi_vl": int(s["hi"].sum()), "risk_hi_vl": float(s["hi"].mean())}

ref_ct = d.loc[d["ageg"] == REF, "ct_result"].values
crude = {a: welch(d.loc[d["ageg"] == a, "ct_result"].values, ref_ct) for a in LABS if a != REF}

X, nm = design(d)
idx = {a: nm.index("age_" + a) for a in LABS if a != REF}
b, se = ols(X, y, hc3=True)
adj = {a: {"diff": float(b[j]), "lcl": float(b[j] - Z * se[j]), "ucl": float(b[j] + Z * se[j]),
           "se": float(se[j])} for a, j in idx.items()}

keep = [nm.index(c) for c in nm if c.startswith(("drive", "orderset", "set_", "male", "blk_"))]
Xt = np.column_stack([np.ones(n), d["age"].values / 10.0, X[:, keep]])
bt, st = ols(Xt, y, hc3=True)
trend = {"diff_per_10y": float(bt[1]), "lcl": float(bt[1] - Z * st[1]), "ucl": float(bt[1] + Z * st[1])}

std_pt = gcomp(X, b, idx, "id")
bh = logit_fit(X, d["hi"].values)
risk_pt = gcomp(X, bh, idx, "logit")

rng = np.random.default_rng(SEED)
bs = {a: np.empty(N_BOOT) for a in idx}
brd = {a: np.empty(N_BOOT) for a in idx}
for k in range(N_BOOT):
    db = d.iloc[rng.integers(0, n, n)]
    Xb, _ = design(db)
    bb, _ = ols(Xb, db["ct_result"].values.astype(float))
    g = gcomp(Xb, bb, idx, "id")
    gr = gcomp(Xb, logit_fit(Xb, db["hi"].values), idx, "logit")
    for a in idx:
        bs[a][k] = g[a] - g[REF]
        brd[a][k] = gr[a] - gr[REF]
std_res = {a: {"diff": float(std_pt[a] - std_pt[REF]), "lcl": float(np.percentile(bs[a], 2.5)),
               "ucl": float(np.percentile(bs[a], 97.5))} for a in idx}
rd_res = {a: {"rd": float(risk_pt[a] - risk_pt[REF]), "lcl": float(np.percentile(brd[a], 2.5)),
              "ucl": float(np.percentile(brd[a], 97.5))} for a in idx}

bp, sp = poisson_robust(X, d["hi"].values)
rr = {a: {"rr": float(np.exp(bp[j])), "lcl": float(np.exp(bp[j] - Z * sp[j])),
          "ucl": float(np.exp(bp[j] + Z * sp[j]))} for a, j in idx.items()}

qr = QuantReg(y, X).fit(q=0.5)
ci = np.asarray(qr.conf_int())
medreg = {a: {"diff": float(qr.params[j]), "lcl": float(ci[j][0]), "ucl": float(ci[j][1])}
          for a, j in idx.items()}

strata = {}
for nmst, msk in (("drive_thru", d["drive_thru_ind"] == 1), ("on_site", d["drive_thru_ind"] == 0)):
    aa = d.loc[msk & (d["ageg"] == "0-4"), "ct_result"].values
    rr2 = d.loc[msk & (d["ageg"] == REF), "ct_result"].values
    w = welch(aa, rr2)
    w.update({"n_0_4": int(len(aa)), "n_18plus": int(len(rr2)),
              "mean_ct_0_4": float(np.mean(aa)), "mean_ct_18plus": float(np.mean(rr2))})
    strata[nmst] = w
Xi, ni = design(d, interact=True)
bi, si = ols(Xi, y, hc3=True)
ji = ni.index("age04_x_dt")
inter = {"diff": float(bi[ji]), "lcl": float(bi[ji] - Z * si[ji]), "ucl": float(bi[ji] + Z * si[ji])}

dall = prep(raw[(raw["result"] == "positive") & raw["ct_result"].notna() & (raw["ct_result"] < 45)])
Xa, na = design(dall)
ya = dall["ct_result"].values.astype(float)
ba, _ = ols(Xa, ya)
ra = ya - Xa @ ba
A = np.linalg.pinv(Xa.T @ Xa)
meat = np.zeros((Xa.shape[1], Xa.shape[1]))
for _, g in pd.DataFrame(Xa * ra[:, None]).groupby(dall["subject_id"].values):
    s = g.values.sum(axis=0)
    meat += np.outer(s, s)
Vc = A @ meat @ A
ja = na.index("age_0-4")
sens_all = {"n_tests": int(len(dall)), "n_subjects": int(dall["subject_id"].nunique()),
            "diff": float(ba[ja]), "lcl": float(ba[ja] - Z * np.sqrt(Vc[ja, ja])),
            "ucl": float(ba[ja] + Z * np.sqrt(Vc[ja, ja]))}

dp = d[d["age"] <= 100]
Xp, npm = design(dp)
bpp, spp = ols(Xp, dp["ct_result"].values.astype(float), hc3=True)
jp = npm.index("age_0-4")
sens_age = {"n": int(len(dp)), "dropped": int(n - len(dp)), "diff": float(bpp[jp]),
            "lcl": float(bpp[jp] - Z * spp[jp]), "ucl": float(bpp[jp] + Z * spp[jp])}

# internal validity of the de-identified age field: does age still predict positivity?
dv = prep(raw[raw["result"].isin(["positive", "negative"])].copy())
dv["pos"] = (dv["result"] == "positive").astype(float)
pos_by_age = {a: {"n_tests": int((dv["ageg"] == a).sum()),
                  "n_positive": int(dv.loc[dv["ageg"] == a, "pos"].sum()),
                  "positivity": float(dv.loc[dv["ageg"] == a, "pos"].mean())} for a in LABS}
Xv, nv = design(dv)
bv, sv = poisson_robust(Xv, dv["pos"].values)
jv = nv.index("age_0-4")
age_check = {"positivity_by_age_group": pos_by_age,
             "adjusted_rr_positive_0_4_vs_18plus": float(np.exp(bv[jv])),
             "lcl": float(np.exp(bv[jv] - Z * sv[jv])), "ucl": float(np.exp(bv[jv] + Z * sv[jv]))}

a04 = adj["0-4"]
gap = float(a04["diff"] - REFUTE)
bias = {"attenuation_needed_for_true_minus4p5_at_point": float(a04["diff"] / CLAIMED),
        "attenuation_needed_for_true_minus4p5_at_lcl": float(a04["lcl"] / CLAIMED),
        "nondifferential_attenuation_could_reconcile_lcl": bool(0.0 < a04["lcl"] / CLAIMED <= 1.0),
        "bias_required_to_reach_minus3_cycles": gap,
        "u_ct_effect_needed_if_prevalence_gap_0p5": float(gap / 0.5),
        "u_prevalence_gap_needed_if_ct_effect_5cycles": float(gap / 5.0)}

folds = {"adjusted_fold_higher_viral_load_0_4_vs_18plus": fold(a04["diff"]),
         "lcl": fold(a04["ucl"]), "ucl": fold(a04["lcl"]),
         "claimed_fold_in_literature": fold(CLAIMED),
         "log10_copies_difference_point": float(-a04["diff"] / 3.3),
         "log10_copies_difference_lcl": float(-a04["ucl"] / 3.3),
         "log10_copies_difference_ucl": float(-a04["lcl"] / 3.3)}

refuted = bool(a04["lcl"] > REFUTE)
supported = bool(a04["ucl"] <= REFUTE)
print("crude 0-4 vs 18+ =", round(crude["0-4"]["diff"], 3),
      "| adjusted =", round(a04["diff"], 3), (round(a04["lcl"], 3), round(a04["ucl"], 3)))

out = {"sample": counts, "n_analysed": int(n), "n_individuals": int(d["subject_id"].nunique()),
       "pan_day_min": int(d["pan_day"].min()), "pan_day_max": int(d["pan_day"].max()),
       "overall_mean_ct": float(np.mean(y)), "overall_sd_ct": float(np.std(y, ddof=1)),
       "overall_median_ct": float(np.median(y)),
       "descriptives_by_age_group": desc,
       "crude_mean_ct_difference_vs_18plus": crude,
       "adjusted_mean_ct_difference_vs_18plus_hc3": adj,
       "standardised_mean_ct_difference_vs_18plus_bootstrap": std_res,
       "adjusted_age_trend_per_10_years": trend,
       "median_regression_difference_vs_18plus": medreg,
       "high_viral_load_ct_lt_25_risk_ratio_vs_18plus": rr,
       "high_viral_load_ct_lt_25_risk_difference_vs_18plus": rd_res,
       "stratified_by_testing_stream_0_4_vs_18plus": strata,
       "interaction_age0_4_x_drive_thru": inter,
       "sensitivity_all_positive_tests_cluster_robust": sens_all,
       "sensitivity_exclude_age_over_100": sens_age,
       "age_variable_internal_validity_check": age_check,
       "bias_analysis": bias, "fold_change_translation": folds,
       "hypothesis_threshold_cycles": REFUTE, "claimed_literature_difference_cycles": CLAIMED,
       "hypothesis_refuted": refuted, "hypothesis_supported": supported,
       "n_bootstrap": int(N_BOOT), "seed": int(SEED)}
print("RESULT_JSON: " + json.dumps(out))
Listing. experiment_v1.py

4.Analysis

Attempt 2Done

Analysis complete: experiment succeeded; hypothesis refuted; 12 key numbers.

Hypothesis refutedExperiment succeeded

Results and analysis

The run completed without error. Of 15,524 RT-PCR tests, 865 were positive; 5 lacked a cycle threshold and 3 sat at the 45-cycle non-detection ceiling, leaving 857 quantifiable positives, and restriction to each person's first positive removed 71 repeat tests, giving 786 specimens from 786 individuals (pandemic days 10-107). Mean Ct was 28.98 cycles (SD 7.29). Crude mean Ct was 29.19 in children aged 0-4 (n=186) against 28.69 in adults aged 18 and over (n=315), a crude difference of +0.50 cycles (95% CI -0.89 to 1.89) -- the opposite sign to the hypothesis. Adjustment for testing stream, sex and calendar block moved the estimate to -0.72 cycles (95% CI -2.33 to 0.88), reproduced exactly by direct standardisation with bootstrap intervals (-0.72; 95% CI -2.29 to 0.80). Because the whole interval lies above -3, the hypothesis is refuted: the data are incompatible with a 3-cycle deficit, and a fortiori with the 4.5-cycle (roughly 23-fold) excess reported in 2020. Translated to viral load, the adjusted estimate is a 1.65-fold excess in the under-5s with a compatibility interval running from 0.54-fold to 5.02-fold. The adjusted risk ratio for a high-viral-load specimen (Ct<25) was 1.22 (95% CI 0.93 to 1.61), risk difference 7.9 percentage points (95% CI -2.7 to 18.8). The crude-to-adjusted sign change is a Simpson-type reversal driven by testing stream: 80% of adult positives came through the drive-through against 36% of under-5 positives, and within each stream the contrast is negative (drive-through -0.78, on-site -0.07). Median regression (+0.07 cycles), the per-10-year trend (+0.05; 95% CI -0.33 to 0.43) and the all-tests cluster-robust analysis (-0.20; 95% CI -1.64 to 1.24) agree that any age difference is small.

Key numbers

MetricValueInterpretation
Analytic sample786 first-positive specimens from 786 individuals (of 15,524 tests loaded; 865 positive, 857 quantifiable, 71 repeat tests removed)One record per person over pandemic days 10-107, so the estimates are free of within-person correlation.
Crude mean Ct difference, 0-4 vs 18++0.50 cycles (95% CI -0.89 to 1.89)Unadjusted, young children have marginally lower viral load than adults, not higher; the interval is compatible with no difference.
Adjusted mean Ct difference, 0-4 vs 18+ (HC3)-0.72 cycles (95% CI -2.33 to 0.88)The primary estimate. The entire interval lies above the -3 cycle refutation threshold, so the hypothesised 8-fold viral-load excess is excluded.
Standardised mean Ct difference, 0-4 vs 18+ (bootstrap, 2000 resamples)-0.72 cycles (95% CI -2.29 to 0.80)Direct standardisation over testing stream and calendar block reproduces the regression estimate, so the result is not an artefact of the model's functional form.
Viral-load translation of the adjusted estimate1.65-fold higher in 0-4 (95% CI 0.54 to 5.02), against 22.6-fold implied by the -4.5 cycle claimEven the most extreme value compatible with these data is a fifth of the difference originally reported.
Adjusted risk ratio for high viral load (Ct < 25), 0-4 vs 18+RR 1.22 (95% CI 0.93 to 1.61); risk difference 7.9 percentage points (95% CI -2.7 to 18.8)A modest and imprecise excess of high-viral-load specimens in the youngest; 39.2% of under-5 positives were below 25 cycles against 38.1% of adult positives before adjustment.
Distribution of testing stream by age79.7% of adult positives drive-through versus 36.0% of under-5 positives; 8.9% of adults versus 41.9% of under-5s from emergency or inpatient settingsAge and reason for testing are nearly collinear in a paediatric hospital, which is why the crude and adjusted estimates take opposite signs.
Stream-specific crude differences, 0-4 vs 18+Drive-through -0.78 cycles (95% CI -2.86 to 1.29); on-site -0.07 cycles (95% CI -2.40 to 2.25); interaction -1.48 cycles (95% CI -4.22 to 1.26)Both stratum-specific estimates are negative while the pooled crude estimate is positive: a Simpson-type reversal produced by confounding by testing indication.
Adjusted linear age trend+0.05 cycles per 10 years of age (95% CI -0.33 to 0.43)No monotone age gradient in viral load across the whole age range once setting and calendar time are held fixed.
Robustness checksMedian regression +0.07 cycles (95% CI -2.57 to 2.70); all 857 positive tests with subject-clustered SE -0.20 cycles (95% CI -1.64 to 1.24); excluding the single record with age over 100 years -0.68 cycles (95% CI -2.28 to 0.93)The conclusion does not depend on the mean as the summary, on the one-record-per-person restriction, or on implausible ages left by de-identification.
Internal validity of the de-identified age fieldTest positivity 3.8% (220/5,754) at 0-4 years rising to 8.1% (342/4,211) at 18+; adjusted RR 0.49 (95% CI 0.41 to 0.59) for 0-4 versus 18+Age still predicts positivity strongly and in the direction documented for 2020, so the permutation applied at de-identification did not destroy the age signal.
Quantitative bias analysisAn attenuation factor of 0.16 at the point estimate, or 0.52 at the lower confidence limit, would be required for the true difference to be -4.5 cycles; alternatively an unmeasured binary confounder differing by 50 percentage points in prevalence between the groups and shifting mean Ct by 4.55 cycles would be needed to move the estimate to -3Reconciling these data with the original claim would require the de-identification to have destroyed 84% of the age signal, or a confounder stronger than any measured covariate; both are implausible, though the lower confidence limit leaves the weaker reconciliation arithmetically open.

Caveats

  • Days since symptom onset and symptom status are not recorded. Because Ct is a single snapshot of a rising-then-falling trajectory, any age difference in how quickly people reach testing confounds the contrast, and testing stream is only a proxy for it. This is the largest single threat and it cannot be removed with these variables.
  • The sample is everyone tested at one paediatric hospital and the analysis conditions on a positive result. If both age and viral load influence the probability of being tested and of testing positive, conditioning on positivity can induce a collider association between them; no design feature here breaks that path.
  • Cycle threshold is not a viral load. It depends on assay, target gene, specimen adequacy and collection technique, and swab quality plausibly differs between a struggling toddler and a cooperating adult, so the measurement error may be differential by age in exactly the direction that matters.
  • The released records were de-identified by time-shifting and permutation. The internal-validity check shows the age field retains a strong association with positivity, but the analysis cannot rule out some attenuation of the age-Ct contrast, and the estimate should be read as a bound rather than an exact adjusted difference.
  • Precision is limited: 186 under-5 and 315 adult specimens give an interval about 1.6 cycles wide on each side of the point estimate. The study can exclude a 3-cycle deficit but cannot distinguish a difference of one cycle from none, and the high-viral-load risk ratio of 1.22 is compatible with anything between a 7% deficit and a 61% excess.
  • Age groups are compared across different calendar periods (median pandemic day 32 for under-5s, 71 for adults, 84.5 for 12-17 year olds). Calendar blocks are adjusted for, but with four blocks the control for epidemic phase is coarse and residual confounding by time remains possible.
  • Adults tested at this paediatric hospital are largely staff, caregivers and clients rather than a general adult patient population, so the adult reference group is not representative of adults in Philadelphia and the contrast may not transport to other settings.
  • The results are from a single institution over a single 98-day period in 2020, before the emergence of variants that changed viral-load distributions, so they speak to the original claim in its own era and not to later variants.
  • All estimates are associations conditional on presenting for testing. A causal reading would additionally require no unmeasured confounding by time since onset and severity given the measured covariates, no age-differential specimen-quality error, and no selection into the tested-and-positive sample depending jointly on age and viral load; none of these can be verified here.

5.Paper writing

Attempt 2Done

Manuscript drafted: “Testing Indication, Not Age: A Replication Attempt of the Reported SARS-CoV-2 Viral-Load Excess in Children Under 5 Years” (≈ 2988 words).

≈ 2988 words · AI-drafted manuscript · not peer-reviewed

Testing Indication, Not Age: A Replication Attempt of the Reported SARS-CoV-2 Viral-Load Excess in Children Under 5 Years

Abstract

A widely cited 2020 report of a 4.5-cycle lower reverse-transcription polymerase chain reaction (RT-PCR) cycle threshold (Ct) in children under 5 years than in adults, read as a 10- to 100-fold viral-load excess, shaped debate on reopening childcare and schools. We attempted replication in de-identified records of 15,524 severe acute respiratory syndrome coronavirus 2 (SARS-CoV-2) RT-PCR tests from the Children's Hospital of Philadelphia in 2020; each person's first quantifiable positive specimen gave 786 individuals. Exposure was age group, outcome Ct in cycles. Crude mean Ct was 0.50 cycles higher in children aged 0-4 years than in adults aged 18 years or more (95% confidence interval (CI): -0.89, 1.89); after adjustment for testing stream, sex and calendar block it was -0.72 cycles (95% CI: -2.33, 0.88), reproduced by direct standardisation (-0.72; 95% CI: -2.29, 0.80). The adjusted risk ratio for a high-viral-load specimen (Ct < 25) was 1.22 (95% CI: 0.93, 1.61). These data exclude a 3-cycle deficit in young children and, a fortiori, the excess originally reported; the crude-to-adjusted sign reversal is generated by testing indication.

Keywords: COVID-19; SARS-CoV-2; confounding factors, epidemiologic; cycle threshold; selection bias; viral load; child, preschool; replication studies

Introduction

When governments decided in 2020 whether to reopen childcare and schools, the only infectiousness proxy available at scale from routine laboratory systems was the RT-PCR cycle threshold, which falls by roughly 3.3 cycles for every tenfold rise in RNA copies.

Into that vacuum came a report from a Chicago paediatric hospital on 145 patients with mild-to-moderate coronavirus disease 2019 (COVID-19) sampled within a week of symptom onset (1). Median Ct was 6.5 in children under 5 years against 11.1 at 5-17 years and 11.0 in adults, a 4.5-cycle gap read as 10- to 100-fold more virus in the youngest. Larger studies did not reproduce it: over five thousand multicentre cases (2), a Geneva series restricted to the first five days after onset (3), community home-swab surveillance giving -0.7 cycles (95% CI: -2.2, 0.9) for symptomatic children versus adults (4), and 25,381 German cases placing the youngest at most 0.5 log10 units below older subjects (5).

The disagreement is epidemiologic. Ct is one snapshot of a trajectory that peaks within days and then decays, so days since infection is a dominant and rarely recorded confounder. Testing indication is nearly collinear with age inside a children's hospital, and testing programme shifts the viral-load distribution (6); conditioning on positivity can induce a collider association between age and viral load (7); and Ct depends on assay, specimen adequacy and technique (8). Our objective was to set the crude and stream-adjusted contrasts side by side in a second paediatric laboratory, with an interval narrow enough to exclude the original effect rather than merely fail to detect it.

Methods

Study Population

We analysed the covid_testing dataset of the R package medicaldata version 0.2.0, mirrored by the Rdatasets archive at https://vincentarelbundock.github.io/Rdatasets/csv/medicaldata/covid_testing.csv and retrieved 8 September 2026 (SHA-256 prefix fc7d7c522749144b) (9). These are real SARS-CoV-2 RT-PCR tests from the Children's Hospital of Philadelphia, Pennsylvania, donated by Amrom E. Obstfeld and released after de-identification, date shifting and value permutation; there is no source publication. The extract holds 15,524 tests over days 4-107 of the 2020 pandemic period, recording subject identifier, sex, pandemic day, result, age in years, Ct in cycles, drive-through and order-set indicators, and patient class.

Filters were applied in order: of 15,524 tests, 14,358 were negative and 301 invalid, leaving 865 positive; 5 had no Ct and 3 sat at the 45-cycle non-detection ceiling, leaving 857 quantifiable; keeping each subject's earliest positive removed 71 repeats, giving 786 specimens from 786 individuals over pandemic days 10-107.

The assumed causal structure, in words: age influences why a person is tested, the reason for testing sets how early in infection the specimen is taken, and time since infection determines Ct, so testing stream confounds the age-Ct association. Calendar time is a second confounder, since epidemic phase shifts the population Ct distribution (10). Positivity is a common effect of infection and viral load, so restricting to positives conditions on a collider adjustment cannot close.

Exposure Assessment

Exposure was age group at collection: 0-4, 5-11, 12-17 and 18 years or more, adults the reference and 0-4 versus 18 or more the primary contrast; a secondary model entered age continuously, per 10 years. Age is recorded in whole years, 0 for infants.

Outcome Ascertainment

The outcome was the cycle threshold of the positive test, continuous, lower values indicating more viral nucleic acid; a secondary dichotomous outcome, high viral load, was Ct below 25 cycles. The assay is not named, so Ct is interpretable only within this laboratory.

Covariates

Covariates were the drive-through indicator; the order-set indicator (standing order set versus individual order); patient class collapsed to emergency, inpatient, outpatient or observation, not applicable and not recorded; sex; and calendar time in four blocks (days 4-33, 34-63, 64-93, 94-107). All were complete; patient class is structurally absent for drive-through specimens, and that absence was carried as its own category, not imputed.

Statistical Analysis

Crude differences used Welch unequal-variance intervals, adjusted differences ordinary least squares with heteroscedasticity-consistent (HC3) standard errors. We also standardised directly, predicting Ct for every individual under each age group, averaging over the observed joint covariate distribution and taking percentile intervals from 2,000 nonparametric bootstrap resamples; median regression gave a distribution-robust check. For high viral load we fitted a Poisson model with log link and robust variance for risk ratios and standardised a logistic model for risk differences. Effect modification by testing stream was assessed by stratum-specific estimates and a product term. Two sensitivity analyses, reported in Table 5, relaxed the one-record-per-person restriction and dropped the single implausible age.

Because de-identification permuted values, we asked what attenuation factor ρ\rho in Δ^obs=ρ Δtrue\hat\Delta_{\text{obs}} = \rho\,\Delta_{\text{true}} would make the observed contrast compatible with a true −4.5-4.5 cycles, non-differential misclassification biasing toward the null (11), and estimated the age-positivity association among all 15,223 valid tests as a check that the age field retains information. For an unmeasured binary confounder the bias is (π1−π0) δ(\pi_{1}-\pi_{0})\,\delta; we solved for the values that would move the estimate to −3-3 cycles.

Analytic Specifications and Reproducibility

One Python script (numpy, pandas, scipy, statsmodels) produced every estimate; the only stochastic element is the bootstrap, seeded at 20200401. The hypothesis was pre-set to be refuted if the adjusted interval lay entirely above −3-3 cycles.

Results

Age and testing stream are strongly associated (Table 1): 79.7% of adult positives came through the drive-through against 36.0% of under-5 positives, while emergency or inpatient settings supplied 41.9% of under-5 and 8.9% of adult specimens.

Table 1. Characteristics of the 786 first-positive SARS-CoV-2 specimens, by age group, Children's Hospital of Philadelphia, 2020

Characteristic0-4 y5-11 y12-17 y≥18 y
No. of individuals186117168315
Mean Ct, cycles (SD)29.19 (8.05)28.92 (7.60)29.36 (6.91)28.69 (6.91)
Ct < 25 cycles, No. (%)73 (39.2)44 (37.6)57 (33.9)120 (38.1)
Drive-through collection, %36.049.645.279.7
Emergency or inpatient, %41.935.029.28.9
Male sex, %37.151.353.049.5
Median day of pandemic period32.053.084.571.0

Abbreviations: Ct, cycle threshold; SD, standard deviation. Percentages are within age group. Of 865 positive tests, 5 lacked a Ct value, 3 sat at the 45-cycle ceiling and 71 were repeats.

The crude comparison runs against the hypothesis (Table 2): mean Ct in the under-5s was 0.50 cycles higher than in adults, that is, viral load slightly lower. Adjustment reversed the sign to -0.72 cycles and standardisation gave the same point estimate; because the interval lies entirely above -3 cycles, the refutation criterion is met. On the viral-load scale that is 1.65 times more nucleic acid in the under-5s (0.54 to 5.02 times), against 22.6 times for the 4.5-cycle difference reported in 2020. No gradient appeared across the intermediate groups or in the continuous age term.

Table 2. Crude, adjusted and standardised differences in mean cycle threshold by age group, adults as reference (n = 786)

Age groupCrude (95% CI)Adjusted (95% CI)Standardised (95% CI)Median regression (95% CI)
0-4 y0.50 (-0.89, 1.89)-0.72 (-2.33, 0.88)-0.72 (-2.29, 0.80)0.07 (-2.57, 2.70)
5-11 y0.23 (-1.35, 1.82)0.06 (-1.66, 1.79)0.06 (-1.71, 1.65)-0.30 (-3.20, 2.60)
12-17 y0.67 (-0.63, 1.97)0.75 (-0.64, 2.15)0.75 (-0.59, 2.11)0.54 (-1.89, 2.96)
Per 10 y of age—0.05 (-0.33, 0.43)——

Abbreviations: CI, confidence interval. Values are cycles; negative means lower Ct, hence higher viral load. Adjusted estimates are ordinary least squares with HC3 standard errors, standardised estimates average those predictions over the observed covariate distribution (2,000 bootstrap resamples, seed 20200401); covariates are those listed in Methods. The last row is a separate continuous-age model.

Dichotomising at 25 cycles gave the same picture, with a slight excess in the youngest (Table 3).

Table 3. Adjusted association between age group and a high-viral-load specimen (Ct < 25 cycles), adults as reference

Age groupCt < 25 / total (%)Adjusted risk ratio (95% CI)Adjusted risk difference, percentage points (95% CI)
0-4 y73/186 (39.2)1.22 (0.93, 1.61)7.9 (-2.7, 18.8)
5-11 y44/117 (37.6)1.04 (0.77, 1.41)1.4 (-9.4, 13.2)
12-17 y57/168 (33.9)0.87 (0.67, 1.13)-4.8 (-14.1, 4.2)
≥18 y120/315 (38.1)1.00 (reference)0.0 (reference)

Abbreviations: CI, confidence interval; Ct, cycle threshold. Risk ratios are from a Poisson model with log link and robust variance, risk differences from standardising a logistic model (bootstrap intervals); both adjust for the Table 2 covariates.

Table 4 shows why the crude and adjusted estimates take opposite signs: both stratum-specific estimates are negative while the pooled crude one is positive, a Simpson-type reversal, adults having been tested mostly through the stream with the lower mean Ct.

Table 4. Difference in mean cycle threshold between children aged 0-4 years and adults, by testing stream

Stratum0-4 y, no. (mean Ct)≥18 y, no. (mean Ct)Difference (95% CI)
Drive-through collection67 (27.52)251 (28.30)-0.78 (-2.86, 1.29)
On-site collection119 (30.13)64 (30.20)-0.07 (-2.40, 2.25)
Product term, 0-4 × drive-through——-1.48 (-4.22, 1.26)

Abbreviations: CI, confidence interval; Ct, cycle threshold. Stratum differences are Welch estimates; the product term is from the fully adjusted HC3 model. The pooled crude difference is 0.50 cycles (Table 2).

Sensitivity and bias analyses appear in Table 5. Test positivity among all 15,223 valid tests rose from 3.8% in the under-5s to 8.1% in adults, so the age field retains real information after de-identification.

Table 5. Sensitivity and quantitative bias analyses for the 0-4 years versus adults contrast

AnalysisEstimate (95% CI)
Primary adjusted difference, 786 individuals-0.72 cycles (-2.33, 0.88)
All 857 quantifiable positives, SE clustered on 786 subjects-0.20 cycles (-1.64, 1.24)
Excluding 1 record aged > 100 y (n = 785)-0.68 cycles (-2.28, 0.93)
Test positivity, 0-4 vs ≥18 y, 15,223 valid testsRisk ratio 0.49 (0.41, 0.59)
Attenuation required for a true -4.5 cycles, at point estimate / lower limit0.16 / 0.52
Bias required to move the adjusted estimate to -3 cycles2.28 cycles
Unmeasured confounder reaching -3 cycles, at a prevalence gap of 50 / 45.5 points4.55 / 5 cycles

Abbreviations: CI, confidence interval; SE, standard error. Positivity counts were 220/5,754 (0-4), 128/2,833 (5-11), 175/2,425 (12-17) and 342/4,211 (≥18); the risk ratio is adjusted for the Table 2 covariates. Attenuation factors are the observed estimate divided by -4.5 cycles.

Discussion

In one paediatric hospital laboratory in 2020, children under 5 with a positive SARS-CoV-2 test did not carry materially more viral nucleic acid than adults. The adjusted difference of -0.72 cycles (95% CI: -2.33, 0.88) excludes the pre-set 3-cycle threshold and, by a wide margin, the 4.5-cycle difference behind the 10- to 100-fold claim (1); the largest excess these data support is about 5-fold, a fifth of what was reported.

It matches the closest published comparison, -0.7 cycles (95% CI: -2.2, 0.9) between symptomatic children and adults in community surveillance (4), and agrees with the multicentre null (2), the Geneva series restricted to early infection (3), and the largest series, which placed the youngest marginally lower in viral load, by at most 0.5 log10 units (5).

The most instructive feature is the sign reversal. Crude, the under-5s appear to carry slightly less virus; within each stream, slightly more. Four-fifths of adult positives came through the drive-through stream, which had the lower mean Ct, while most young children were tested on site. Any comparison of children with adults across a hospital's testing programmes that ignores programme estimates a mixture of the age and the indication contrast (6).

Strengths are the pre-specified refutation criterion, the agreement between regression and standardisation, one specimen per person and interval-based reporting; the weaknesses matter more. Confounding by time since infection is unaddressed: onset date and symptom status are absent and testing stream is only a coarse proxy, though the studies that controlled it by restriction also found no age difference (3, 5). Selection bias is structural: conditioning on positivity, a common effect of infection and viral load, leaves a collider path between age and Ct open (7). Information bias runs in the direction that matters (8): a swab from a struggling toddler is not the same measurement as one from a cooperating adult, and such error would raise Ct in the youngest, masking a true excess.

De-identification by permutation adds exposure error, which biases a dichotomous contrast toward the null (11), so the estimate is a lower bound on any true difference. Two things limit that reading: age still predicts positivity strongly (risk ratio 0.49; 95% CI: 0.41, 0.59), and reconciling -0.72 with -4.5 cycles would need an attenuation factor of 0.16 — 84% of the signal destroyed — or 0.52 at the lower confidence limit, implausible against that check though not excluded arithmetically. Precision is the remaining limitation: 186 under-5 and 315 adult specimens leave an interval 1.6 cycles either side of the estimate, excluding a 3-cycle difference but not a one-cycle one. The adult group is largely staff, caregivers and clients, so the contrast may not transport, and all results come from one institution over 98 days in 2020, before the variants that altered viral-load distributions.

These are associations conditional on presenting for testing and testing positive. Reading -0.72 cycles causally would require no unmeasured confounding by time since onset or severity, no age-differential specimen-quality error and no selection depending jointly on age and viral load; none of these can be verified here, and we make no causal claim. For public health the message is unchanged: infected young children shed virus of the same order as infected adults. For epidemiologic practice it is sharper: age contrasts from routine laboratory extracts are contrasts between testing programmes as much as between people, and crude and stream-specific estimates belong side by side whenever Ct is compared across groups tested for different reasons (10).

Abbreviations

CI, confidence interval; COVID-19, coronavirus disease 2019; Ct, cycle threshold; HC3, heteroscedasticity-consistent covariance estimator, third variant; RNA, ribonucleic acid; RT-PCR, reverse-transcription polymerase chain reaction; SARS-CoV-2, severe acute respiratory syndrome coronavirus 2; SD, standard deviation; SE, standard error.

References

  1. Heald-Sargent T, Muller WJ, Zheng X, et al. Age-related differences in nasopharyngeal SARS-CoV-2 levels in patients with mild to moderate COVID-19. JAMA Pediatr. 2020;174(9):902-903. https://pubmed.ncbi.nlm.nih.gov/32745201/
  2. Madera S, Crawford E, Langelier C, et al. Nasopharyngeal SARS-CoV-2 viral loads in young children do not differ significantly from those in older children and adults. Sci Rep. 2021;11(1):3044. https://pubmed.ncbi.nlm.nih.gov/33542262/
  3. Baggio S, L'Huillier AG, Yerly S, et al. SARS-CoV-2 viral load in the upper respiratory tract of children and adults with early acute COVID-19. Clin Infect Dis. 2021;73(1):148-150. https://pubmed.ncbi.nlm.nih.gov/32761228/
  4. Chung E, Chow EJ, Wilcox NC, et al. Comparison of symptoms and RNA levels in children and adults with SARS-CoV-2 infection in the community setting. JAMA Pediatr. 2021;175(10):e212025. https://pubmed.ncbi.nlm.nih.gov/34115094/
  5. Jones TC, Biele G, Mühlemann B, et al. Estimating infectiousness throughout SARS-CoV-2 infection course. Science. 2021;373(6551):eabi5273. https://pubmed.ncbi.nlm.nih.gov/34035154/
  6. Kociolek LK, Muller WJ, Yee R, et al. Comparison of upper respiratory viral load distributions in asymptomatic and symptomatic children diagnosed with SARS-CoV-2 infection in pediatric hospital testing programs. J Clin Microbiol. 2020;59(1):e02593-20. https://pubmed.ncbi.nlm.nih.gov/33093026/
  7. Griffith GJ, Morris TT, Tudball MJ, et al. Collider bias undermines our understanding of COVID-19 disease risk and severity. Nat Commun. 2020;11(1):5749. https://pubmed.ncbi.nlm.nih.gov/33184277/
  8. Rhoads D, Peaper DR, She RC, et al. College of American Pathologists (CAP) Microbiology Committee perspective: caution must be used in interpreting the cycle threshold (Ct) value. Clin Infect Dis. 2021;72(10):e685-e686. https://pubmed.ncbi.nlm.nih.gov/32785682/
  9. Higgins PDR. medicaldata: data package for medical datasets. R package version 0.2.0; 2021. Dataset covid_testing, donated by Amrom E. Obstfeld. https://cran.r-project.org/package=medicaldata
  10. Hay JA, Kennedy-Shaffer L, Kanjilal S, et al. Estimating epidemiologic dynamics from cross-sectional viral load distributions. Science. 2021;373(6552):eabh0635. https://pubmed.ncbi.nlm.nih.gov/34083451/
  11. Copeland KT, Checkoway H, McMichael AJ, et al. Bias due to misclassification in the estimation of relative risk. Am J Epidemiol. 1977;105(5):488-495. https://pubmed.ncbi.nlm.nih.gov/871121/

6.Review

Attempt 2Done

Automated review: Minor revision (novelty 3, rigor 4, clarity 4, reproducibility 4).

Minor revision
Novelty 3/5Rigor 4/5Clarity 4/5Reproducibility 4/5

A careful, honest replication attempt that reaches a clear negative answer and is faithful to the data it claims to analyse. Using 786 first-positive specimens from deidentified Children's Hospital of Philadelphia RT-PCR records, the adjusted difference in mean cycle threshold between children under 5 and adults is -0.72 cycles (95% CI -2.33 to 0.88), which excludes the pre-set -3 cycle threshold and, comfortably, the -4.5 cycle difference behind the widely cited 10- to 100-fold claim. The paper's most useful contribution is not the null itself but the demonstration that the crude and adjusted contrasts have opposite signs because testing stream is nearly collinear with age in a hospital laboratory extract; that message is well supported by the stratified analysis. Every number I checked against the executed script and the recorded provenance matched, the data are correctly described as real and deidentified, and the reporting follows this journal's conventions on measures of association and restraint in causal language. The remaining problems are presentational and interpretive rather than analytic: the descriptive distribution of the outcome is too thin for a skewed measure, the viral-load translation is untabulated, the misclassification argument is stated more firmly than a permutation of unspecified fields warrants, and selection bias is diagnosed but not quantified alongside the confounding analysis. None of these requires new computation, and all can be handled in revision.

Strengths

  • The manuscript matches the executed record exactly. The dataset (medicaldata::covid_testing via Rdatasets, deidentified Children's Hospital of Philadelphia RT-PCR records, retrieved 8 September 2026, SHA-256 prefix fc7d7c522749144b), the 15,524 loaded tests, the filter cascade (14,358 negative, 301 invalid, 865 positive, 5 without Ct, 3 at the 45-cycle ceiling, 857 quantifiable, 71 repeats removed, 786 individuals, pandemic days 10-107) and every tabulated estimate correspond to the script and its RESULT_JSON. The data are never described as simulated.
  • A refutation threshold (-3 cycles) was fixed in advance and the paper reports the result against it rather than against a null of zero, which is the right way to conduct a replication attempt and is unusual in this literature.
  • Confounding is handled transparently and the crude-to-adjusted sign reversal is displayed rather than hidden: Table 4 gives both stream-specific contrasts (-0.78 and -0.07 cycles) beside the positive pooled crude estimate, so the reader can see the Simpson-type reversal that the discussion attributes to testing indication (79.7% of adult positives drive-through versus 36.0% of under-5 positives).
  • Three independent estimators agree (HC3 regression -0.72, direct standardisation -0.72, median regression +0.07), and the secondary dichotomous outcome (RR 1.22; 95% CI 0.93 to 1.61; RD 7.9 percentage points, 95% CI -2.7 to 18.8) is reported on both the ratio and the difference scale, as this journal prefers.
  • The quantitative bias analysis is genuinely informative rather than decorative: the required attenuation factors (0.16 at the point estimate, 0.52 at the lower limit) and the unmeasured-confounder magnitudes (4.55 cycles at a 50-point prevalence gap) are stated, and the internal-validity check on the deidentified age field (positivity RR 0.49; 95% CI 0.41 to 0.59) gives an empirical bound on how much the permutation could have destroyed.
  • Venue conventions are respected: every estimate carries a 95% confidence interval, p-value language and the word 'significant' are absent from the text, causal language is withheld and the assumptions that a causal reading would require are stated explicitly, and abbreviations are defined at first use.
  • Reproducibility is well served: a single script, named libraries, a fixed bootstrap seed (20200401), the resolvable data URL and the file hash.

Weaknesses

  • Table 1 reports means and standard deviations only. Cycle-threshold distributions are skewed and the analysis leans on the mean, so the group medians and interquartile ranges that the run produced should be shown; without them the reader cannot judge whether the median-regression check in Table 2 is reassuring or merely uninformative.
  • The viral-load translation (1.65-fold; 95% CI 0.54 to 5.02, against the 22.6-fold implied by -4.5 cycles) is the number the discussion leans on hardest and appears only in running text, not in any table, and the conversion rule used to obtain it is not stated where the number is given.
  • The misclassification argument imports the classical result for a non-differential misclassified dichotomous exposure, but the exposure here is a four-level age variable, and the deidentification is described as value permutation without saying which fields were permuted. The direction-of-bias claim is therefore an assumption, not a theorem, and is presented too firmly.
  • Selection bias is named and correctly diagnosed as a collider problem but, unlike confounding, it is never quantified even approximately, so the reader has no sense of how large the induced association could be relative to the 1.6-cycle interval width.
  • The design is nowhere named. The abstract and Methods describe the sampling frame but never state that this is a cross-sectional analysis of routine laboratory records restricted to first positive specimens, which STROBE requires early and which matters for how the estimates are read.
  • The overall distribution of the outcome in the analytic sample (mean 28.98 cycles, SD 7.29) is not reported anywhere, so the group-specific means in Table 1 have no anchor.
  • Novelty is limited by design: this is a single-centre replication of a single-centre claim, and the adult reference group at a paediatric hospital is an unusual comparison population, a point the discussion concedes but the introduction does not prepare the reader for.

Required changes

  • Add the group-specific median cycle threshold with the 25th and 75th percentiles to Table 1 (the values the run produced: 28.99 (21.60, 36.95) at 0-4 years; 28.19 (22.18, 36.20) at 5-11; 28.57 (23.51, 36.10) at 12-17; 27.96 (22.75, 35.07) at 18 and over), and give the overall mean, standard deviation and median for the 786 specimens.
  • Move the viral-load translation into a table (or add it as a row of Table 5) and state the conversion used, so that 1.65-fold (95% CI 0.54 to 5.02) versus the 22.6-fold implied by -4.5 cycles is a tabulated result rather than a claim made only in prose.
  • Qualify the misclassification argument: state that the classical toward-the-null result applies to a non-differential misclassified dichotomous exposure, that the exposure here is polytomous, and that the direction of bias under the unspecified permutation is assumed rather than established. The lower-limit reconciliation (attenuation 0.52) should be presented as arithmetically open in the same sentence.
  • Name the design explicitly in the abstract and in the first sentence of Study Population (a cross-sectional analysis of routine RT-PCR records, restricted to each person's first quantifiable positive specimen), and state the STROBE reporting standard being followed.
  • Sharpen the selection-bias paragraph: say in what direction the collider path would move the age contrast if age and viral load both raise the probability of being tested and of testing positive, and state plainly that no bias analysis for this path was performed, in contrast to the confounding analysis that was.
  • In the introduction, prepare the reader for the composition of the adult comparison group at a paediatric hospital, rather than leaving it to the limitations.

Record

§Event timeline

  1. Run createdQuestion: “Do children under 5 years have higher SARS-CoV-2 upper-respiratory viral loads (lower RT-PCR cycle threshold values) than adults, once testing setting and calendar time are accounted for?” · output language: English · venue: Epidemiology & Public Health · American Journal of Epidemiology · models: agent:claude-opus-5
  2. Stage started · Literature reviewAttempt 1 · agent:claude-opus-5
  3. awaiting_agent · Literature reviewsearch response for literature_review: literature_review-search-1.response.json
  4. Resume requested
  5. Stage started · Literature reviewAttempt 2 · agent:claude-opus-5
  6. Search complete · Literature review18 sources · 11,613 characters of notes
  7. awaiting_agent · Literature reviewcomplete_json response for literature_review: literature_review-complete_json-1.response.json
  8. Resume requested
  9. Stage started · Literature reviewAttempt 3 · agent:claude-opus-5
  10. Search complete · Literature review18 sources · 11,613 characters of notes
  11. Stage completed · Literature review
  12. Stage started · IdeationAttempt 1 · agent:claude-opus-5
  13. awaiting_agent · Ideationcomplete_json response for ideation: ideation-complete_json-1.response.json
  14. Resume requested
  15. Stage started · IdeationAttempt 2 · agent:claude-opus-5
  16. Awaiting approval · Ideation
  17. Approved · IdeationIdea 1 selected
  18. Stage started · ExperimentationAttempt 1 · agent:claude-opus-5
  19. Dataset provisioned · Experimentationchop_covid_testing · 15,524 observations · 15 variables · sha256 fc7d7c522749
  20. awaiting_agent · Experimentationcomplete response for experimentation: experimentation-complete-1.response.txt
  21. Resume requested
  22. Stage started · ExperimentationAttempt 2 · agent:claude-opus-5
  23. Dataset provisioned · Experimentationchop_covid_testing · 15,524 observations · 15 variables · sha256 fc7d7c522749
  24. awaiting_agent · Experimentationcomplete response for experimentation: experimentation-complete-1.response.txt
  25. Resume requested
  26. Stage started · ExperimentationAttempt 3 · agent:claude-opus-5
  27. Dataset provisioned · Experimentationchop_covid_testing · 15,524 observations · 15 variables · sha256 fc7d7c522749
  28. Experiment round · ExperimentationRound 1: exit 0; result parsed (3.878s)
  29. Stage completed · Experimentation
  30. Stage started · AnalysisAttempt 1 · agent:claude-opus-5
  31. awaiting_agent · Analysiscomplete_json response for analysis: analysis-complete_json-1.response.json
  32. Resume requested
  33. Stage started · AnalysisAttempt 2 · agent:claude-opus-5
  34. Stage completed · Analysis
  35. Stage started · Paper writingAttempt 1 · agent:claude-opus-5
  36. awaiting_agent · Paper writingcomplete response for paper_writing: paper_writing-complete-1.response.txt
  37. Resume requested
  38. Stage started · Paper writingAttempt 2 · agent:claude-opus-5
  39. Stage completed · Paper writing
  40. Stage started · ReviewAttempt 1 · agent:claude-opus-5
  41. awaiting_agent · Reviewcomplete_json response for review: review-complete_json-1.response.json
  42. Resume requested
  43. Stage started · ReviewAttempt 2 · agent:claude-opus-5
  44. Awaiting approval · Review
  45. Approved · Review
  46. Run completereport=/private/tmp/claude-501/-Users-haodingresearch-Desktop-auto-research/579004ae-5819-417d-918c-9d9409997567/scratchpad/studies/epidemiology-en/runs/b1eefce32671/REPORT.md
  47. Resume requested
  48. Run completereport=/private/tmp/claude-501/-Users-haodingresearch-Desktop-auto-research/579004ae-5819-417d-918c-9d9409997567/scratchpad/studies/epidemiology-en/runs/b1eefce32671/REPORT.md