Study
255 students · 6 survey waves · 87% retention · Sep 2022 – Oct 2023
Social networks, alcohol use, and norm perceptions in a UK residence hall.
A narrative study book is available at shangshanggu.com/sand. This tab provides the compact technical reference.
My Contribution
SAND is the product of my PhD research at the University of Sheffield (2021–2025). I designed the study, built the data-collection infrastructure from bare university VMs, recruited and retained 255 participants across six longitudinal waves, conducted all analysis, and wrote the thesis. Every component documented here—the REDCap architecture, the identity-separation protocol, the recruitment operations, the reproducible analysis pipeline, and this open-science release—is my own work as a sole researcher, supervised but not co-developed.
1. Overview
SAND followed 255 first-year students (from 375 invited) in one UK residence hall across six survey waves. Repeated alcohol-use measures and sociocentric important-peer nominations answered three questions:
- How does drinking change after students move into halls?
- How do perceived norms (what students think peers drink and approve of) relate to personal consumption?
- Do students befriend similar drinkers (social selection), or do friends' drinking habits converge over time (social influence)?
Chapter 4 prepares the data. Chapters 5–6 use network autocorrelation models for norm misperception. Chapter 7 uses a stochastic actor-oriented model to separate selection from influence.
2. Study Design
| Feature | SAND |
|---|---|
| Setting | One university-managed residence hall in a UK city |
| Invited population | 375 first-year residents |
| Enrolled sample | 255 students |
| Survey waves | 6 waves, September 2022 – October 2023 |
| Network nominations | Up to 10 important-peer nominations per participant from Wave 2 |
| Behaviour outcome | AUDIT-C score (range 0–12) |
| Consequence measures | BYAACQ alcohol-consequence items |
| Norm constructs | Descriptive and injunctive norm perceptions at global and peer levels |
| Main models | Network Autocorrelation Models (NAM) and Stochastic Actor-Oriented Models (SAOM) |
| SAOM waves | Waves 2, 4, 5, 6 with baseline covariates from Wave 1 |
| Data collection | REDCap on a university-hosted Linux/Apache/MySQL stack |
| Identity separation | Baseline and follow-up REDCap projects with role-based access separation |
2.1 Wave Map
| Wave | Timing | Downstream use |
|---|---|---|
| Wave 1 | Sep 2022 (baseline) | Baseline covariates, pre-university alcohol measures, Chapter 4 |
| Wave 2 | Oct 2022 | First network measurement; Ch 5/6 Time 1; Ch 7 SAOM start |
| Wave 3 | Nov 2022 | Longitudinal preparation and QA |
| Wave 4 | Dec 2022 | Ch 7 SAOM |
| Wave 5 | Mar 2023 | Ch 5/6 Time 2; Ch 7 SAOM |
| Wave 6 | Oct 2023 | Ch 5/6 Time 3; Ch 7 SAOM end |
Chapters 5 and 6 use three analysis timepoints (Time 1/2/3 = Waves 2/5/6). Chapter 7 uses four network observations (Waves 2/4/5/6) with Wave 1 baseline covariates.
2.2 Network Boundary
The network boundary is the residence hall cohort. Each participant could nominate up to 10 people who had been important to them in the past month, regardless of liking. Nominations are directed: A nominating B does not imply reciprocity. Legacy code sometimes uses “friend” as shorthand for nominated important peers.
Network measurement began at Wave 2, one month after arrival. The first weeks of tie formation are unobserved.
2.3 Timeline
2.4 Participant Flow
| Wave | Timing | NAM N | Jaccard | Mean AUDIT-C | SD |
|---|---|---|---|---|---|
| W1 (baseline) | Sep 2022 | 255 | — | 4.9 | 2.8 |
| W2 | Oct 2022 | 218 | — | 7.4 | 3.0 |
| W3 | Nov 2022 | — | — | 6.7 | 3.0 |
| W4 | Dec 2022 | — | 0.67 | 6.5 | 3.1 |
| W5 | Mar 2023 | 213 | 0.81 | 6.4 | 3.1 |
| W6 | Oct 2023 | 215 | 0.66 | 6.7 | 2.9 |
NAM N is the analysis sample after listwise deletion for the descriptive norm models (Chapter 5). Jaccard indices measure wave-to-wave network stability; all exceed RSiena’s 0.30 threshold. Overall retention across the study was 87%.
2.5 Data Collection Infrastructure
Data were collected via REDCap hosted on a university-managed Linux/Apache/MySQL/SSL stack. Two linked REDCap projects separated contact data from survey responses. The identity manager resolved names to pseudonymous IDs; the researcher exported only coded, de-identified data. The staged export (list_by_wave.RData) is the single input to the analysis pipeline.
See the Infra tab for the full server stack, two-project model, identity separation workflow, recruitment operations, incentive automation, and REDCap API export configuration.
3. Key Findings
3.1 Drinking Trends and Demographics (Chapter 4)
In this sample, mean AUDIT-C rose from 4.9 (pre-university baseline) to 7.4 one month after arrival. At the October peak, 80% reported monthly binge drinking and 60% weekly. Scores declined over the academic year but did not return to baseline.
3.2 Descriptive Norm Misperception (Chapter 5)
In all waves, participants overestimated typical-resident drinking by 1.5–1.7 AUDIT-C points. NAM estimates showed a shift in which referent predicted personal consumption:
| Time Period | Global Misperception β | Peer Misperception β | Interpretation |
|---|---|---|---|
| Time 1 (Oct) | 0.541 (p<0.001) | 0.045 (n.s.) | Community norms dominate |
| Time 2 (Mar) | 0.547 (p<0.001) | 0.124 (p<0.05) | Peer influence emerges |
| Time 3 (Oct) | 0.246 (p<0.01) | 0.192 (p<0.01) | Both matter; peer gaining |
At Time 1, global misperception was the stronger predictor. By Time 3, peer-level misperception reached comparable magnitude, consistent with a referent shift as friendship clusters stabilised.
3.3 Injunctive Norms (Chapter 6)
Participants overestimated peer approval of risky drinking across all three scenarios. However, neither global nor peer injunctive misperception predicted consumption in any of the nine NAM models (3 scenarios × 3 time periods).
| Scenario | Time | Global Misp. β | Peer Misp. β | Status |
|---|---|---|---|---|
| Not drinking | T1 | −0.001 (n.s.) | 0.005 (n.s.) | Neither significant |
| T2 | −0.015 (n.s.) | 0.004 (n.s.) | Neither significant | |
| T3 | 0.006 (n.s.) | −0.020 (n.s.) | Neither significant | |
| Binge drinking | T1 | −0.004 (n.s.) | −0.019 (n.s.) | Neither significant |
| T2 | −0.012 (n.s.) | 0.006 (n.s.) | Neither significant | |
| T3 | −0.005 (n.s.) | 0.007 (n.s.) | Neither significant | |
| Passing out | T1 | 0.003 (n.s.) | 0.013 (n.s.) | Neither significant |
| T2 | 0.025 (n.s.) | −0.005 (n.s.) | Neither significant | |
| T3 | −0.020 (n.s.) | −0.003 (n.s.) | Neither significant |
All 63 coefficient checks (7 terms × 3 scenarios × 3 time periods) reproduce thesis values to 3 decimal places. Previous drinking (AUDIT-C at t−1) and ethnicity consistently predict consumption; injunctive misperception does not.
3.4 Social Selection & Influence (Chapter 7)
The SAOM models network tie change and behaviour change jointly, separating two processes:
Social selection (similar drinkers become friends?): AUDIT-C similarity (β=−0.08, p=0.88), ego (β=−0.04, p=0.18), and alter (β=0.03, p=0.35) were all non-significant. The model found no evidence that drinking similarity predicted tie formation.
Social influence (friends become similar drinkers?): The average similarity effect was significant (β=1.88, p<0.01), yielding an odds ratio of 1.17 (95% CI: 1.05–1.31). Under the model, students were 17% more likely to shift their drinking one unit toward their friends’ average than to hold steady.
| Effect | β | SE | p | Interpretation |
|---|---|---|---|---|
| Average similarity (influence) | 1.88 | 0.68 | <0.01 | Drinking convergence among friends |
| AUDIT-C similarity (selection) | −0.08 | 0.53 | 0.88 | n.s.; no selection on drinking |
| Reciprocity | 2.70 | 0.31 | <0.001 | Mutual ties favoured |
| Transitive triplets | 0.78 | 0.12 | <0.001 | Triadic closure |
| Flatmate proximity | 0.76 | 0.23 | <0.001 | Flat co-residence predicts ties |
| Blockmate proximity | 0.80 | 0.22 | <0.001 | Block co-residence predicts ties |
| Density | −2.91 | 0.52 | <0.001 | Sparse network |
On thesis data: convergence max ratio ≤ 0.10; Jaccard indices 0.67, 0.81, 0.66. Proxy-data convergence is not yet verified.
4. Data Dictionary
Collapsed. Repeated friend-slot variables (slots 1–10) shown as patterns. make DATA_MODE=proxy portfolio generates the expanded version.
4.1 Identifiers
| Variable | Type | Description | Waves |
|---|---|---|---|
redcap_survey_identifier | integer | Pseudonymous participant key for within-study linkage | 1–6 |
redcap_event_name | character | REDCap event label (wave1_arm_1 to wave6_arm_1) | 1–6 |
4.2 Demographics & Residence
| Variable | Type | Encoding | Description | Waves |
|---|---|---|---|---|
age | numeric | Years | Participant age at survey | 1–6 |
sex | integer | 0/1 | Sex covariate (0=female, 1=male) | 1–6 |
ethnicity | integer | Collapsed categorical | Ethnicity category | 1–6 |
majority_status | integer | 0/1 | Composite majority-status covariate for Ch 7 | 1–6 |
residence_cluster | integer | — | Proxy residence grouping; real data uses block/flat fields | 1–6 |
4.3 Alcohol Use & Consequences
| Variable | Type | Range | Description | Waves |
|---|---|---|---|---|
q1 | numeric | 0–4 | AUDIT-C item 1: drinking frequency | 1–6 |
q2 | numeric | 0–4 | AUDIT-C item 2: typical drinks per occasion | 1–6 |
q3 | numeric | 0–4 | AUDIT-C item 3: heavy episodic drinking frequency | 1–6 |
audit_score | numeric | 0–12 | AUDIT-C composite: q1 + q2 + q3 | 1–6 |
byaacq_6 | numeric | 0–6 | BYAACQ-derived passing-out field for Ch 6 blackout outcome | 1–6 |
4.4 Important-Peer Nominations
| Variable | Type | Description | Waves |
|---|---|---|---|
friend_number | numeric | Number of important-peer nominations made (0–10) | 2–6 |
which_friendid | integer | Nomination slot index (1–10) | 2–6 |
nomination | integer | Pseudonymous ID of nominated peer | 2–6 |
4.5 Norm Perceptions
| Pattern | Type | Description | Waves |
|---|---|---|---|
inno[1-3]_self | numeric | Own approval of: (1) not drinking, (2) binge, (3) passing out | 1–6 |
deno[1,3,4]_friend_0 | integer | Perceived drinking behaviour of a typical resident | 2–6 |
inno[1-3]_friend_0 | integer | Perceived approval by a typical resident | 2–6 |
deno[1,3,4]_friend_[1-10] | integer | Perceived drinking behaviour of nominated peer (slots 1–10) | 2–6 |
inno[1-3]_friend_[1-10] | integer | Perceived approval by nominated peer (slots 1–10) | 2–6 |
4.6 Derived Measures
| Family | Formula |
|---|---|
actual_*_peer | Mean of the corresponding measure across nominated important peers |
deno*_peer | Aggregated perceived important-peer descriptive norm |
inno*_peer | Aggregated perceived important-peer injunctive norm |
misperception_*_peer | Perceived peer value minus actual peer mean |
audit_score | q1 + q2 + q3 |
5. Known Limitations
| Limitation | Impact |
|---|---|
| Behaviour GoF is poor (p<0.001) | Bimodal AUDIT-C distribution violates SAOM’s continuous-behaviour assumption |
| Missing first-week data | Network measurement began one month after arrival; early formation period is unobserved |
| Single-hall design | One residence hall in a UK university town; UK binge rates (80%) far exceed US cohorts (~28%) |
| 68% response rate | Missing network data could bias tie-formation estimates |
| Self-reported alcohol data | Social desirability and recall error |
| No study preregistration | Retrospective reproducibility release, not a preregistration |
6. Acknowledgements & Contact
This research was funded by a Wellcome Trust Research and Training Support Grant (224 850/Z/21/Z) through the PHEDS Doctoral Training Centre at the University of Sheffield. The funder had no role in study design, data collection, analysis, or the decision to publish.
Supervisors:
- Professor Robin Purshouse, School of Electrical and Electronic Engineering, University of Sheffield
- Professor John Holmes, School of Medicine and Population Health, University of Sheffield
- Professor Paul Norman, Department of Psychology, University of Sheffield
Contact
Shangshang Gu
shangshanggu@gmail.com
Infrastructure
REDCap · MySQL · Apache/SSL · Postfix · cron · API export
The data-collection stack behind the six-wave longitudinal study.
1. Server Stack
The lead researcher built the stack from bare university VMs. The university had no centrally managed REDCap instance. Two dedicated VMs formed a split web/database architecture on the university network:
| Layer | Component | Detail |
|---|---|---|
| Web server VM | Ubuntu / Apache 2 / PHP (7.4–8.1) / SSL | 2 vCPUs, 4 GB RAM, 32 GB SSD. Port 443 open to participants. SSL certificates issued by IT Security with auto-renewal. |
| Database server VM | Ubuntu / MySQL 8.0 | Same spec. Port 3306 open only from the web server. Dedicated redcap MySQL user with scoped privileges on the study database. |
| Application | REDCap v12.5.5 → v13.10.0 | Installed from the REDCap Community distribution. Six versions deployed across the study period (v12.5.5, v12.5.8, v12.5.9, v13.5.1, v13.9.3, v13.10.0). |
| Mail relay | Postfix (internet with smarthost) | Delivers scheduled survey invitations, reminders, and incentive codes. |
| Scheduler | REDCap cron job | Sends reminders on schedule, triggers survey invitations, expires inactive links. |
| Authentication | Table-based, 30-min auto-logout | Autocomplete disabled on login. Clickjacking prevention enabled. User-created projects disabled for non-admin accounts. |
Setup tasks. MySQL installation and secure configuration (mysql_secure_installation, dedicated user, remote bind, privilege scoping), Apache virtual-host and SSL certificate installation, PHP module setup (php-mysql, php-curl, php-gd, php-zip, php-mbstring, php-xml), REDCap database table creation via SQL, Postfix email relay, cron job, and a custom email-validation rule restricting registration to the university domain.
Security configuration. REDCap Control Centre: Send-It disabled, draft-mode auto-approval set to Never, non-admin users cannot create projects or modify events, survey response editing disabled, repeatable instruments locked.
Retained evidence. A complete database backup and server configuration archive were preserved at the end of the study. Python scripts parse the backup offline, enabling reproducible evidence extraction without a running database instance.
SSL and transport security
TLS 1.3 only (all older protocols disabled). OCSP stapling enabled. HttpOnly and Secure flags enforced on all cookies. Directory indexing disabled. Certificates issued by university IT Security with auto-renewal.
Scheduled tasks
A minute-frequency cron job drives REDCap’s automated survey invitations, reminders, and link expiry.
Database isolation
Separate web and database VMs connected over the university internal network. The application used a dedicated, scoped MySQL user with minimum-privilege access to a single study database. A de-identification salt was configured for REDCap’s internal hashing.
Network isolation
The database VM had no public-facing ports. MySQL accepted connections only from the web server, enforced by both bind-address configuration and host-level firewall rules. The application database user held minimum-privilege access (no schema modification, no administrative rights). SSH access was restricted to the university network. HTTP traffic was forced to HTTPS via redirect.
REDCap Control Centre hardening
Key security settings: non-admin users cannot create projects, draft-mode changes require admin approval, file-sharing (Send-It) disabled, API enabled for controlled data export, survey links shortened via REDCap’s built-in shortener.
2. Two-Project Model
The study used two linked REDCap projects with role-based access separation:
| Component | Purpose | Access |
|---|---|---|
| Baseline project | Consent, demographics, pre-university alcohol measures, contact details, email validation | Identity manager + researcher |
| Follow-up projects | Waves 2–6 surveys: AUDIT-C, peer nominations (coded by ID), descriptive and injunctive norm perceptions, alcohol consequences | Researcher (export only, de-identified) |
| Identity manager key | Maps record IDs, pseudonymous six-digit codes, email addresses, and nomination roster positions | Identity manager only |
After baseline collection, the researcher exported all responses and erased the baseline project data from REDCap. The follow-up project was rebuilt from exported instrument ZIP files, preserving survey design without carrying forward participant records.
The PIS portal served as the consent gateway (1 form, 17 fields). The baseline project collected data across 28 instruments covering consent, alcohol measures, email validation, incentive distribution, referral management, and identification-key operations. The follow-up project collected five waves of data (waves 2–6) across 8 instruments including friend-nomination forms with 10 per-friend survey pages.
3. Identity Separation
The core design problem: participants must see names to nominate peers, but the analyst must not access those names.
The identity manager generated six-digit random identifiers in Excel (RANDBETWEEN) and loaded the resulting roster into the follow-up project, linking names to pseudonymous IDs.
When participants nominated up to 10 important peers by name (via dropdown), REDCap’s @HIDDEN-SURVEY and @HIDDEN-FORM action tags separated what participants saw from what the system recorded:
| Action tag | Effect |
|---|---|
@HIDDEN-FORM | Name-selection fields visible to participants during the survey, hidden from the researcher in data views and reports |
@HIDDEN-SURVEY | Calculated ID fields hidden from participants, recorded in the database for export |
A calculated field converted each name selection to its coded ID. The researcher could export de-identified data only: no free text, no dates, no identifier fields, no access to reports or the design interface after initial setup.
No team member simultaneously held export access and the identity key.
Identity-key fields (suffixed _ik) are systematically hidden from the survey view and marked read-only, confirming the separation is enforced at the field level, not merely by convention.
Calculated fields for pseudonymised linkage
The follow-up project contains 21 calculated fields in the friend_nomination instrument. Ten fields convert name-dropdown selections to numeric IDs. A further 10 detect duplicate nominations using conditional logic, with an aggregating error-check flag. A friend_number field counts valid nominations per respondent.
4. Recruitment Operations
Recruitment ran in two phases with daily response tracking.
| Phase | Period | Method | Outcome |
|---|---|---|---|
| A: Public invitation | 20 Sep – 7 Oct 2022 | Three Residence Life emails to 375 residents. 400 A5 + 100 A4 posters. One in-person session. Public REDCap link with university email domain validation. | ~160 completed records by the initial deadline. |
| B: Refer-a-friend | 8–14 Oct 2022 | Respondent-driven sampling. Each existing participant received a unique referral code. Referrers earned £10 per new participant; referred participants received an extra £5 bonus. | Additional enrolments bringing the total to 255. |
Follow-up waves (2–6) used unique non-forwardable survey links emailed via REDCap’s participant list. Up to three reminder emails per wave.
An anonymous enquiry portal stayed open throughout data collection. Participants could raise concerns without identifying themselves.
The follow-up project contains five longitudinal events (one per wave), each linking the same core instruments: alcohol use, friend nomination, per-friend perception pages, and incentive delivery. Combined with the baseline project (single event), the study covers six longitudinal time-points.
5. Incentive Automation
£10 Amazon eGift Card per completed survey. From Wave 2 onward, codes were delivered automatically at survey completion via the REDCap randomisation module:
- Amazon eGift Card codes pre-loaded into the REDCap randomisation table
- On submission, REDCap assigned the next available code and emailed it to the participant
- No manual matching of names to completion status required
Additional incentives: £10 bonus for completing all six waves, £500 prize draw at study end, £10 per successful referral for the referrer, £5 bonus for each referred participant.
6. Database Schema
The archived REDCap database preserves the full relational schema:
| Metric | Count |
|---|---|
| Tables | 220 |
| Foreign-key constraints | 538 |
| Non-unique indexes | 519 |
| Unique indexes | 104 |
| Configuration entries | 342 |
External modules installed
| Module | Version | Purpose |
|---|---|---|
giftcard_reward | v2.0.1 | Automated Amazon eGift Card distribution at survey completion |
auto_populate_fields | v2.6.0 | Pre-fill fields from prior events or calculated sources |
record_autonumber | v1.0.5 | Sequential record numbering for enrolment tracking |
unique_actiontag | v2.0.2 | Enforce uniqueness constraints on field values (e.g., email addresses) |
shazam | v1.3.10 | Custom HTML/CSS/JS injection for instrument display |
7. Field-Level Engineering
The follow-up project demonstrates the complexity of sociometric data collection at the field level:
| Metric | Baseline | Follow-up |
|---|---|---|
| Total fields | 231 | 239 |
| Branching-logic rules | 56 | 151 |
| Required fields | 61 | 123 |
| Fields with validation | 5 | 62 |
| PHI-marked fields | 19 | 12 |
| Calculated fields | 4 | 24 |
Validation types (follow-up project)
| Type | Count | Use |
|---|---|---|
number | 36 | Numeric range enforcement on scale items |
int | 15 | Integer-only fields (counts, IDs) |
autocomplete | 10 | Peer-nomination dropdown search |
float | 1 | Decimal values |
The baseline project adds 5 validated fields: 2 alpha_only (name fields), 1 email, 1 float, 1 int.
Branching logic: sociometric nomination cascade
The follow-up project’s 151 branching rules implement a cascading survey design where each nominated friend generates a personalised block of perception questions:
The logic follows a three-layer pattern:
# Layer 1: Show descriptive-norm question only if friend N was nominated
# and is not a duplicate (error check passed)
deno1_friend_3: [friend3]<>"" and [error3]=0
# Layer 2: Show frequency question only if friend was nominated
# AND respondent rated them as drinking "sometimes" or more
deno2_friend_3: [friend3]<>"" and [error3]=0 and [deno1_friend_3]>1
# Layer 3: Cross-wave confirmation — show friend only if they
# appeared in the previous wave's nomination list
friend3_confirm: [previous-event-name][friend3:value]>1
This pattern repeats for friends 1–10 across four norm dimensions (descriptive frequency, descriptive quantity, injunctive approval, injunctive quantity), yielding the 151 branching rules. Fields with [previous-event-name] references demonstrate REDCap’s longitudinal piping: values carry forward from wave to wave without re-entry.
Duplicate-nomination detection
# Calculated field: flag if friend5 duplicates any earlier nomination
error5 = if(([friend5]<>"" and ([friend5]=[friend4] or
[friend5]=[friend3] or [friend5]=[friend2] or [friend5]=[friend1])),1,0)
# Aggregate: total number of flagged duplicates
error_check = [error2]+[error3]+[error4]+[error5]+[error6]+
[error7]+[error8]+[error9]+[error10]
If error_check > 0, the respondent is prompted to correct their nomination. This is automated data-quality enforcement at the instrument level.
8. Export Boundary
The researcher exported follow-up data via REDCap’s API. De-identification settings stripped free-text fields, date/time fields, and identifier fields before delivery.
The staged export (list_by_wave.RData) is the single input to the reproduction pipeline. Everything upstream belongs to the data-collection infrastructure; everything downstream belongs to the analysis pipeline documented in the Pipeline tab.
9. Design Decisions
Each choice below resolves a tension specific to sociometric data collection.
| Decision | Rationale | Implementation |
|---|---|---|
| Separate identifiers from responses | Participants must see names to nominate; analyst must not access names. | @HIDDEN-SURVEY / @HIDDEN-FORM action tags + calculated fields. Export set to de-identified only. |
| Unique non-forwardable links | Public links would allow duplicate or non-resident submissions. | REDCap participant list with individual survey links tied to validated email addresses. |
| Identity manager role | Someone must verify residence and assign IDs but must not see responses. | Identity manager: design access + identity key. Researcher: export-only, de-identified. No overlap. |
| Erase baseline data after export | Minimise window where names and responses coexist on the server. | Export to encrypted local file, delete from REDCap. Follow-up built from instrument ZIPs. |
| Automated incentive distribution | Manual voucher assignment is slow and creates a privacy risk. | REDCap randomisation module with a 400-row allocation table per project. No manual step. |
| Staged export boundary | Analysis pipeline must not depend on live REDCap access or raw contact data. | list_by_wave.RData is the single handoff file. |
10. Role-Based Access Control
User rights were configured so that no team member simultaneously held export access and identity-key access. Named roles enforced the separation:
| Project | Role | Capability |
|---|---|---|
| Baseline | Admin | Design + rights management |
| Project Manager | Operational management, no design access | |
| Validation Officer | Data validation only | |
| Identification Code Manager | Identity-key operations only | |
| Follow-up | Admin | Design + rights management |
| Project Manager | Operational management, no design access | |
| Identification Code Manager | Identity-key operations only | |
| Amazon Code Manager | Gift-card code distribution only |
Five distinct role definitions were created across the two projects: Project Manager, Validation Officer, Super User, Identification Code Manager, and Amazon Code Manager. The identity manager had no export access; the researcher had no access to the identity-key instruments.
11. Audit Trail
REDCap logs every action to numbered redcap_log_event tables. The study’s audit trail covers survey submissions, record operations, user logins, role changes, and configuration updates across the full data-collection period (August 2022–September 2024). This trail is preserved in the archived backup and is available for institutional review.
12. Backup & Evidence Verification
A complete database backup and application archive were extracted from the production servers at the end of the study. The backup preserves the relational schema, project metadata, instrument definitions, and operational configuration needed to verify claims made in this documentation.
Automated evidence extraction
Python scripts parse the database backup offline as a text stream, extracting project structure, instrument definitions, action-tag usage, calculated fields, role definitions, event configuration, and survey settings. No running database instance is required. A single pass completes in under 2 seconds. Numeric claims in this tab were verified against these scripts.
python3 extract_projects.py # project inventory
python3 extract_evidence.py # instrument and role extraction
python3 generate_data_dictionaries.py # portable data dictionaries
13. Reproduction Guide
A researcher with no prior REDCap experience can recreate the study infrastructure from the portable files in presentation/portable/. These files contain only project structure (instruments, fields, logic, action tags) and zero participant data.
Portable artefacts
| File | Size | Contents |
|---|---|---|
pis_portal_data_dictionary.csv | 21 KB | 17 fields, 1 instrument (PIS + consent) |
baseline_data_dictionary.csv | 90 KB | 231 fields, 28 instruments |
followup_data_dictionary.csv | 218 KB | 239 fields, 8 instruments, 151 branching rules, 24 calculated fields |
followup_events.csv | 1 KB | 5 longitudinal events (wave2–wave6) with form assignments |
Generated by python3 presentation/generate_data_dictionaries.py, which parses the database backup without requiring MySQL.
Prerequisites
- REDCap licence — register at projectredcap.org and download the source. REDCap is free for non-commercial use but requires institutional agreement.
- Docker — any machine with Docker Desktop or Docker Engine. No other software required.
Step 1: Start a local REDCap instance
A Docker Compose config is provided in presentation/redcap-docker/:
cd presentation/redcap-docker/redcap-docker/
# Place REDCap source so that data/redcap/index.php exists
cp -r /path/to/redcap-source/* data/redcap/
docker compose up -d
# Wait ~30s for MySQL, then open http://localhost:8080
The container runs Apache + PHP + MySQL in an isolated network. No data leaves the machine. No email is sent.
Step 2: Create the baseline project
- Log in (the DZD container creates a
site_adminon first boot) - New Project → name it “TFS Baseline” → Classic project
- Project Setup → Data Dictionary → Upload
baseline_data_dictionary.csv - REDCap recreates all 28 instruments, 231 fields, 56 branching rules, 61 required-field constraints, 34
@DEFAULTtags, 14@HIDDEN-SURVEYtags, and 37@READONLYtags from the CSV alone
Step 3: Create the follow-up project
- New Project → name it “TFS Follow-up” → Longitudinal project
- Project Setup → Define My Events → create five events matching
followup_events.csv:wave2 day_offset=1 wave3 day_offset=2 wave4 day_offset=3 wave5 day_offset=4 wave6 day_offset=5 - Data Dictionary → Upload
followup_data_dictionary.csv - Designate Instruments for My Events → assign forms per the
formscolumn infollowup_events.csv
This recreates the full sociometric instrument with 239 fields, 151 branching rules, cascading friend-nomination logic, duplicate-detection calculated fields, and all action tags.
Step 4: Verify
| Check | Expected | How to verify |
|---|---|---|
| Baseline instrument count | 28 | Online Designer → count instruments listed |
| Baseline field count | 231 | Data Dictionary → row count |
@HIDDEN-SURVEY in baseline | 14 fields | Data Dictionary → filter Field Annotation column |
| Follow-up instrument count | 8 | Online Designer |
| Follow-up field count | 239 | Data Dictionary → row count |
| Longitudinal events | 5 (wave2–wave6) | Define My Events page |
| Branching rules | 151 | Data Dictionary → count non-empty Branching Logic cells |
| Calculated fields | 24 | Data Dictionary → filter Field Type = “calc” |
Step 5: Explore the survey design
Navigate the Online Designer to see the instruments as they appeared to participants and researchers:
- friend_nomination (64 fields) — dropdown selection of up to 10 peers, with
friendid1–friendid10calculated fields converting names to pseudonymous IDs - friend1 (96 fields) — per-friend perception questions with three-layer branching cascade (show question → show follow-up → cross-wave confirmation)
- alcohol_use (45 fields) — AUDIT-C screening with
[q1]>1skip logic gating the B-YAACQ consequences section - consent_form (41 fields, baseline) — 17 radio-button consent items, text fields for names and signatures,
@TODAYtimestamp
What the portable files do not contain
- Participant data (records, responses, timestamps)
- User accounts, roles, or access rights (set up manually per Section 10)
- Randomisation allocations (Amazon eGift Card codes; load separately)
- Survey configuration (titles, email templates, auto-continue settings)
- External modules (install
giftcard_reward,auto_populate_fields,unique_actiontag,shazam,record_autonumberfrom the REDCap module repository)
These limitations are deliberate: participant data is confidential, and operational settings depend on the deployment context.
14. Infrastructure Limitations
| Limitation | Impact |
|---|---|
| Roster-based nomination | Participants nominated from a searchable dropdown (REDCap autocomplete). Suitable at this cohort size; larger populations might benefit from additional search or filtering to manage the roster. |
| Excel-based identity-key generation | Identity manager generated six-digit codes in Excel (RANDBETWEEN) and loaded the roster into REDCap. This was accessible for non-technical identity managers. API-based linkage would reduce manual steps at larger scale. |
| No automated failover | Standard university VM snapshots only. Not required for this single-cohort study and would have been solvable within the architecture if needed. |
| REDCap version migration | Upgrades (12.5.5 → 13.5.1 → 13.9.3) required manual testing. No automated regression suite for survey behaviour. |
Pipeline
Chapters 4–7. Make-orchestrated, config-driven.
Paths, toggles, and seeds live inreproduced/config/thesis.yml.
1. Architecture
| Layer | Technology |
|---|---|
| Language | R 4.3.2 (analysis), Python 3.11 (tooling, verification) |
| Orchestration | GNU Make with config-driven targets |
| Configuration | Single YAML file: reproduced/config/thesis.yml |
| Environment | Conda (system packages) + renv (R library lock) |
| R dependency lock | renv.lock with 90 packages including RSiena 1.4.7 |
| SAOM estimation | RSiena 1.4.7 (exact pinned from CRAN Archive) |
| Container | Dockerfile (optional, for CI and clean-room runs) |
| Privacy scanning | R-based portfolio privacy guard + Python release-builder secret scanner |
| Testing | testthat (R), pytest (Python) |
2. Directory Structure
SAND/
├── Makefile Top-level proxy to reproduced/Makefile
├── Dockerfile Optional container build
├── LICENSE MIT (code) + CC BY 4.0 (docs)
├── CITATION.cff Citation metadata
├── README.md Entry point with findings and quick start
├── DATA_AVAILABILITY.md What is public, protected, and synthetic
├── SECURITY.md Credential and vulnerability reporting
├── CONTRIBUTING.md Contribution workflow
├── CHANGELOG.md Release history
│
├── docs/
│ ├── reference.html This file
│ └── readme-assets/ SVG figures for README
│
└── reproduced/ The reproduction workspace
├── Makefile Build contract (all targets)
├── .Rprofile renv activation and library precedence
├── renv.lock 90-package R dependency lock
├── environment.yml Conda environment specification
├── REPRODUCIBLE_PIPELINE.md Canonical build contract
├── README.md Pipeline entry point
│
├── config/
│ ├── thesis.yml Single source of truth
│ └── scenarios/
│ └── saom_models.yml SAOM model specifications
│
├── data/
│ ├── raw/ Protected real data (staged locally, never committed)
│ │ └── README.md
│ ├── proxy/ Synthetic structure-compatible data
│ │ └── list_by_wave_schema.csv
│ └── vendor/
│ └── rsiena/ Pinned RSiena 1.4.7 source tarball
│
├── analyses/
│ ├── chapter4_data_collection/scripts/
│ ├── chapter5_descriptive_norms/scripts/
│ ├── chapter6_injunctive_norms/scripts/
│ ├── chapter7_saom/scripts/
│ └── chapter8_interventions/scripts/
│
├── scripts/
│ ├── 00_setup/ Environment, proxy generation, verification, release
│ ├── portfolio/ Data dictionary, privacy guard, dashboard
│ ├── visualisation/ Network explorers, microstep animation
│ └── utils/ YAML loader, helpers
│
├── tests/
│ ├── test_verify_outputs.py Verifier unit tests
│ ├── test_build_public_release.py Release-builder tests
│ └── portfolio/testthat/ R portfolio test suite
│
├── docs/
│ ├── README.md Documentation hub
│ ├── references/ Stable background: crosswalk, config guide, etc.
│ ├── portfolio/ Public-facing study book, case study, findings
│ ├── roadmaps/ Canonical execution plan
│ ├── status/ Release audit and verification records
│ └── decisions/ Architectural decision records
│
├── outputs/ Generated (gitignored)
│ ├── chapter4/ ... chapter7/
│ └── portfolio/
│
└── R/ Shared R utilities
3. Configuration
Scripts read paths and toggles from reproduced/config/thesis.yml. Hardcoded paths in analysis code are bugs.
3.1 Key Config Paths
| Key | Purpose |
|---|---|
data.mode | real (default) or proxy |
data.proxy_dir | Proxy data directory |
project.paths.raw_data_dir | Protected real data staging area |
chapters.*.enabled | Per-chapter toggle (Ch 8 is false by default) |
chapters.chapter5_descriptive_norms.nam.seed | NAM reproducibility seed |
rsiena.package_version | Pinned RSiena version (1.4.7) |
rsiena.estimation.seed | SAOM RNG seed (2022) |
rsiena.estimation.n3 | Phase 3 iterations (10000) |
rsiena.use_cached_results | false forces re-estimation |
4. Data Modes
| Mode | Source | Purpose | Public? |
|---|---|---|---|
| Real | reproduced/data/raw/ | Reproduce thesis analyses from protected REDCap exports | No |
| Proxy | reproduced/data/proxy/ | Exercise the pipeline with synthetic, structure-compatible data | Yes |
Priority: SAND_DATA_MODE env var overrides data.mode in thesis.yml.
Proxy data share the schema but contain no participant information. They are synthetic, not anonymised.
4.1 Proxy Data Generator
The script scripts/00_setup/create_realistic_proxy_data.R produces a deterministic synthetic dataset. Fixed seed: 20250921.
| Parameter | Value |
|---|---|
| Students | 255 |
| Waves | 6 (matching study design) |
| Network density | Calibrated to observed nomination volumes |
| AUDIT-C distribution | Wave-specific means and SDs from thesis Table 4.x |
| Residence structure | 12 blocks, 72 flats, ~3.5 students per flat |
| Flatmate dyads | 666 |
| Blockmate dyads | 5,166 |
| Nomination slots | Up to 10 per participant per wave |
The generator produces list_by_wave.RData, participants.csv, outcomes.csv, a schema file, and a JSON generation report. Network ties, alcohol scores, and norm perceptions follow study-level design parameters; they do not transform, perturb, or anonymise real participant data.
5. Quick Start
5.1 Proxy Mode (no real data required)
make env # bootstrap Conda + renv + RSiena 1.4.7
make verify-proxy-quick # regenerate proxy data, run Chapters 4-6
# Full path including Chapter 7 (~2 hours):
make verify-proxy
5.2 Real Data Mode
make env
# Stage required files:
# reproduced/data/raw/list_by_wave.RData (required)
# reproduced/data/raw/participants.csv (optional)
# reproduced/data/raw/outcomes.csv (optional)
make verify-real # Chapters 4-7 plus empirical benchmarks
6. Chapter Walkthrough
6.1 Chapter 4: Data Preparation & QA
Method: Data extraction from REDCap exports, participation coverage, quality-assurance checks, imputation, network array construction.
Scripts (executed sequentially by make chapter4)
01_data_preparation_norms.R— Loadlist_by_wave.RData. Reshape wave-level survey responses into a longitudinal panel. Compute peer-level actual and perceived norms, derive misperception measures, apply LOCF imputation where configured.02_qa_checks_norms.R— Participation counts per wave, nomination volume diagnostics, out-of-range value detection, Jaccard stability indices.03_export_norms_longitudinal.R— Write the analysis-ready longitudinal dataset (norms_longitudinal.rds) and chapter manifest.04_export_chapter5_bridge.R— Build directed network adjacency arrays aligned to SAOM waves. Exportnetwork_arrays.rdsfor Chapters 5–7.
Outputs
↓
6.2 Chapter 5: Descriptive Norms (NAM)
Method: Network Autocorrelation Models (sna::lnam()) across 3 time periods, quantifying how global and peer-level descriptive norm misperception relates to personal consumption.
Scripts
01_prepare_chapter5_data.R— Subset longitudinal data to Time 1/2/3 (Waves 2/5/6). Build NAM-compatible weight matrices from the network arrays.02_estimate_nam_models.R— Fit NAM for each time period with the configured seed. Extract coefficients, standard errors, p-values.03_generate_nam_figures.R— Coefficient comparison plots across time periods.04_validate_nam_results.R— Compare estimated coefficients against thesis benchmarks. Proxy mode: warnings. Real-data mode: requires match within tolerance.05_compare_nam_results.R— Side-by-side table: current vs. thesis vs. legacy October 2024 fits.
Outputs
↓
6.3 Chapter 6: Injunctive Norms (NAM)
Method: NAM across 3 approval scenarios (abstaining, binge drinking, passing out), testing whether injunctive norm misperception predicts consumption.
Scripts
01_prepare_approval_longitudinal.R— Build wave-level approval datasets for each scenario from the Chapter 4 manifest. Compute injunctive misperception measures.02_analyze_injunctive_norms.R— Descriptive statistics and trend summaries for injunctive norm perceptions.03_plot_injunctive_trends.R— Approval trajectory plots over time, stratified by scenario.04_estimate_injunctive_nam_models.R— Fit NAM for each approval scenario. Extract coefficients and diagnostics.05_validate_injunctive_results.R— Benchmark validation. Proxy mode: warnings for expected differences.
Outputs
↓
6.4 Chapter 7: Social Selection & Influence (SAOM)
Method: Stochastic Actor-Oriented Model (RSiena 1.4.7) jointly modelling network tie change and behaviour change across Waves 2, 4, 5, 6. Separates social selection from social influence.
Scripts
00_build_network_arrays_base.R— Build SAOM-compatible network arrays and behaviour vectors from Chapter 4 outputs. Align to thesis waves (2/4/5/6), build block and flat dyadic covariates from residence fields, extract baseline majority-status and sex covariates from Wave 1.01_prepare_saom_inputs.R— Assemble the RSiena data object (sienaDataCreate): dependent network, dependent behaviour, constant/varying covariates, dyadic proximity covariates.02_run_saom_model.R— Runsiena07()with configured seed, n3, phase settings, Dolby correction. Write fitted object and text output. ~2h runtime.03_generate_saom_tables_figures.R— Extract coefficient tables, goodness-of-fit diagnostics, summary figures from the fitted model.04_validate_saom_results.R— Check convergence ratio (target ≤0.10), Jaccard indices, benchmark coefficients. Flag degenerate covariate effects.
Estimation parameters
| Parameter | Value | Purpose |
|---|---|---|
| RNG seed | 2022 | Reproducibility across runs |
| Phase 3 iterations (n3) | 10000 | Convergence diagnostics precision |
| Subphases (nsub) | 4 | Phase 2 refinement steps |
| Initial gain (firstg) | 0.1 | Step size in Phase 1 |
| Gain reduction (reduceg) | 0.5 | Step decay per subphase |
| Dolby correction | true | Reduces variance in Phase 3 |
| Max iterations | 8 | Re-estimation attempts before stopping |
Outputs
Runtime: ~2 hours on Apple M4 (10 cores). The fast CI gate covers Chapters 4–6 only; Chapter 7 is a separate manual or scheduled job.
6.5 Chapter 8: Interventions (Experimental)
Method: Counterfactual SAOM scenario simulations. Disabled by default (chapters.chapter8_interventions.enabled: false).
01_load_manifest_and_baseline.R— Loads the Chapter 7 fitted model as the baseline for intervention scenarios.03_summarize_interventions.R— Aggregates simulation results across scenario batches.
Status: Scaffolding exists. Not part of the verified release. 462 scenarios × 3 chained periods.
7. Thesis-to-Code Crosswalk
Mapping from thesis chapter claims to the scripts and output files that produce them.
| Thesis claim / output | Script | Output file | Validation |
|---|---|---|---|
| Ch 4: Participation, retention, Jaccard indices | chapter4/.../02_qa_checks_norms.R | chapter4/logs/chapter4_qa_assertions.json | QA assertions checked automatically |
| Ch 4: Longitudinal norms panel | chapter4/.../03_export_norms_longitudinal.R | chapter4/data/norms_longitudinal.rds | Manifest with SHA-256 hashes |
| Ch 4: Network adjacency arrays | chapter4/.../04_export_chapter5_bridge.R | chapter4/data/network_arrays.rds | Manifest hash; consumed by Ch 5–7 |
| Ch 5: NAM coefficient tables (3 time periods) | chapter5/.../02_estimate_nam_models.R | chapter5/tables/nam_summary.csv | 3dp match to thesis (real mode) |
| Ch 5: Coefficient comparison plots | chapter5/.../03_generate_nam_figures.R | chapter5/figures/nam_coefficients.png | — |
| Ch 5: Thesis benchmark validation | chapter5/.../04_validate_nam_results.R | chapter5/logs/nam_validation.json | JSON targets in quan_results.md |
| Ch 6: Injunctive NAM tables (3 scenarios × 3 time periods) | chapter6/.../04_estimate_injunctive_nam_models.R | chapter6/tables/injunctive_nam_coefficients.csv | 63 coefficient checks, 3dp match |
| Ch 7: SAOM selection/influence estimates | chapter7/.../02_run_saom_model.R | chapter7/cache/base_fit.RData, saom_base.txt | Convergence ratio ≤ 0.10; Jaccard ≥ 0.30 |
| Ch 7: GoF and convergence diagnostics | chapter7/.../03_generate_saom_tables_figures.R | chapter7/figures/, chapter7/logs/saom_diagnostics.json | Machine-readable convergence report |
Abbreviated paths: chapter4/.../ means analyses/chapter4_data_collection/scripts/. All outputs land in reproduced/outputs/.
8. Verification
Proxy runs test execution and artefact structure; empirical differences are warnings, not failures. Real-data runs enforce chapter benchmarks.
| Target | What it does |
|---|---|
make verify-proxy-quick | Regenerate proxy data, run Chapters 4–6, verify 15 structural checks |
make verify-proxy | Full proxy path including Chapter 7 SAOM estimation (~2h) |
make verify-real | Protected data: Chapters 4–7 with empirical benchmarks and convergence checks |
make verify | Dispatches to the appropriate target for the current data mode |
9. Setup & Tooling Scripts
Under reproduced/scripts/, outside the chapter analysis directories.
00_setup/ — Environment and release
install_r_packages.R— Restore the renv library fromrenv.lockinto the project-local directory.install_rsiena.R— Download, compile, install exact RSiena 1.4.7 from the CRAN Archive tarball. Validate the installed version.create_realistic_proxy_data.R— Deterministic synthetic data generator. 255 students × 6 waves with network ties, alcohol scores, norm perceptions, residence structure. Seed:20250921.validate_config.py— Checkthesis.ymlfor required keys, valid types, path existence.verify_outputs.py— Mode-aware output verifier. Proxy: structural checks, empirical-difference warnings. Real: benchmark enforcement.build_public_release.py— Build a history-free release candidate. Scan for secrets, local paths, protected data paths, oversized files.generate_data_hashes.py— Compute SHA-256 hashes for staged data files.docker_smoke_test.R— Minimal R test for Docker container verification.
portfolio/ — Public documentation generators
generate_data_dictionary.R— Generate a Markdown data dictionary from the proxy schema.generate_repro_manifest.R— Produce a reproducibility manifest: tracked scripts, configs, checksums.generate_validation_dashboard.R— HTML dashboard: proxy vs. empirical results per chapter.check_privacy.R— Scan generated Markdown/HTML for participant identifiers, real network data, missing synthetic labels.
visualisation/ — Network outputs
05_interactive_networks.R— Standalone HTML network explorers (one per SAOM wave) via visNetwork. Provenance labels and synthetic/real-data markers embedded in the output.04_animate_microsteps.R— Optional SAOM microstep animation. RequiresnetworkDynamic/ndtv.plot_network_panel.R/plot_network_stability.R— Static network and Jaccard stability plots.
10. Make Targets
| Target | Purpose |
|---|---|
make env | Bootstrap Conda environment + renv library + RSiena 1.4.7 |
make validate-config | Check thesis.yml for required keys and valid values |
make proxy-data | Generate synthetic proxy inputs |
make chapter4 … make chapter7 | Run individual chapters |
make all | Run Chapters 4–7 sequentially |
make check | Configuration validation, R syntax check, Python tests, portfolio suite |
make portfolio | Generate data dictionary, manifest, dashboard, network pages |
make portfolio-test | Run the R portfolio test suite |
make privacy-check | Scan Markdown/HTML outputs for privacy violations |
make rsiena | Install exact RSiena 1.4.7 into project library |
make visualise | Generate interactive network explorers |
make docker-build | Build the Docker image |
make clean | Remove generated outputs |
11. Common Failure Modes
| Symptom | Cause | Fix |
|---|---|---|
make chapter4 fails with missing inputs | Real data not staged | Stage exports into reproduced/data/raw/, or use make proxy-data + DATA_MODE=proxy |
| SAOM convergence issues or long runtimes | Inherent to RSiena estimation | See docs/references/chapter7_saom_restart.md |
| RSiena version mismatch | Global R library has a newer version | Run make rsiena to install exact 1.4.7 into project library |
| Conda environment fails to solve | Channel or package availability change | Check environment.yml against current conda-forge |
| renv restore fails | CRAN mirror or package version unavailable | Run make env-renv and check status with renv::status() |
Release
Release status and contract. Scope, provenance, data restrictions, environment, validation, and limitations must all be inspectable.
1. Verification Status
Verified on 14 July 2026 · macOS 15.6 (arm64) · Apple M4 · R 4.3.2 · RSiena 1.4.7
| Check | Result | Detail |
|---|---|---|
| Secret/credential scan | Pass | No protected paths, known secret forms, local absolute paths, or unsafe symlinks |
| Conda environment solve | Pass | environment.yml resolves from declared channels on macOS arm64 |
| Locked R library restore | Pass | renv.lock restored into clean project library |
| Python test suite | Pass | 11 tests: release-builder, verifier behaviour |
| R portfolio/integration suite | Pass | Dictionary, limits, explorer, integration, privacy, manifest, dashboard |
| Fast proxy pipeline (Ch 4–6) | Pass | 15 structural checks, 0 failures, 2 expected proxy-vs-empirical warnings |
| Portfolio generation & privacy | Pass | Dictionary, manifest, dashboard, 5 labelled network pages; privacy scans pass |
| Full Chapter 7 (corrected proxy) | Open | First proxy run completed but did not converge (ratio=1.10); corrected proxy data produced but rerun not completed |
| Docker image | Open | Dockerfile exists; daemon was unavailable during verification |
| Hosted CI | Open | Workflows prepared but not run in a published repository |
2. Environment
2.1 Conda
Defined in reproduced/environment.yml. Key pins:
| Package | Version |
|---|---|
| R | 4.3.2 |
| Python | 3.11 |
| igraph | 1.5.1 |
| tidyverse | 2.0.0 |
| visNetwork | 2.1.4 |
| renv | 1.0.7 |
| pandoc | 3.1.12 |
2.2 renv
reproduced/renv.lock locks 90 R packages with concrete version pins and hashes. The lock was regenerated from the maintained Chapters 4–7 source tree.
2.3 RSiena
Pinned to exact version 1.4.7 from the CRAN Archive. The installer downloads the source tarball to data/vendor/rsiena/, compiles it, and installs to the project-local .Rlib/ directory. A regression check confirms the activated version matches. The global R library may contain a newer RSiena; the project .Rprofile ensures the local 1.4.7 takes precedence.
2.4 Docker
Dockerfile builds a self-contained image. Not yet verified in the current release cycle.
3. Data Availability
Public: Analysis code, configuration, environment definitions, documentation, schema inventory, synthetic proxy-data generator.
Protected: Participant data. Longitudinal alcohol-use, demographic, residential, and network information. Pseudonymisation does not remove disclosure risk from a bounded social graph with repeated measurements. Not distributed.
Synthetic proxy: Generated by make proxy-data. Uses study-level design parameters to exercise the pipeline. Does not transform, perturb, or anonymise participant rows. Not suitable for substantive inference.
Aggregate results: README figures and tables were cross-checked against thesis Chapters 4–7 on 13 July 2026 (source cross-check, not a fresh protected-data run).
Access: No public access procedure. Future requests must follow institutional governance.
4. Release Contract
Included: Chapters 4–7 pipeline, real/proxy data modes, synthetic data generator, schema documentation, environment locks, thesis-to-code crosswalk, tests, validation reports, citation/contribution/security/data-availability documents, confirmed licence, release manifest.
Excluded: participant data, credentials, private Git history, project-management files, agent instructions, personal notes, unvalidated Chapter 8 claims.
4.1 Current Gates
| Gate | Status |
|---|---|
| Remove local secret configuration from tracked tree | Done |
Replace ambiguous make verify with explicit proxy/real checks | Done |
| CI generates proxy inputs explicitly | Done |
| Replace placeholder dependency lock; add renv activation | Done |
| Reconcile README, config, chapter status for Ch 4–7 | Done |
| Embed provenance in generated network HTML; privacy guard rejects unlabelled pages | Done |
| Audit candidate for secrets, protected paths, private notes, local paths | Done |
| Build history-free release candidate | Done |
| Run Chapters 4–6 from clean checkout | Done |
| Complete Chapter 7 from corrected proxy data | Open |
| Confirm code and documentation licence | Done |
| Test links, citation metadata, installation commands | Open |
| CI/Docker verification | Open |
| Tag and archive | Open |
4.2 Interpretation Rule
A proxy run proves the software executes on synthetic inputs. It does not prove proxy estimates match thesis results. A real-data run proves agreement with recorded empirical benchmarks, subject to stated tolerances. Release documentation keeps these claims separate.
5. License & Citation
Code: MIT License © 2025 Shangshang Gu
Documentation & diagrams: CC BY 4.0
Data: Not distributed. Synthetic proxy data are covered by the MIT License.
See LICENSE for full text and CITATION.cff for machine-readable citation metadata.
6. Reproduction Fidelity
On the thesis data, Chapters 5 and 6 reproduce every coefficient to 3 decimal places. Three code fixes were required to achieve exact match:
| # | Fix | Detail |
|---|---|---|
| 1 | Zero-friend peer coding | Participants with friend_number == 0 receive peer_misperception = 0. Participants whose friends all have missing data keep NaN (dropped as incomplete). |
| 2 | Imputation mean source | The mean for single-NA imputation is computed from the flagged subset only, matching the legacy filter(further_imputation==1) pipeline. |
| 3 | Adjacency normalisation | Uses diag(1/colSums) %*% adj (legacy normalisation), not standard row-normalisation. |
These fixes produce thesis-matching sample sizes (218/213/215 for Time 1/2/3) and exact agreement at 3dp.
6.1 Recorded Validation Targets
| Chapter | Scope | Checks | Status (real data) |
|---|---|---|---|
| Ch 5 (Descriptive NAM) | Global and peer misperception β at T1, T2, T3 | 6 coefficients | All match to 3dp |
| Ch 6 (Injunctive NAM) | 7 terms × 3 scenarios × 3 time periods | 63 coefficients | All match to 3dp |
| Ch 7 (SAOM) | Convergence ratio, Jaccard indices, key effects | Convergence ≤ 0.10; Jaccards 0.67, 0.81, 0.66 | Converged on thesis data |
Machine-readable targets are stored in reproduced/docs/references/quan_results.md and consumed by each chapter’s validation script. Proxy runs cannot reproduce these values because synthetic inputs have different distributions; the verifier issues warnings rather than failures.
7. Verification Check Inventory
The verifier (scripts/00_setup/verify_outputs.py) runs 15 checks for a Chapters 4–6 proxy path, more when Chapter 7 is included.
| Check ID | What it tests | Fail behaviour |
|---|---|---|
data.proxy_bundle | list_by_wave.RData exists in proxy dir | Fail |
data.proxy_marker | Proxy marker file present | Fail |
chapter4.prepared_data | prepared_data_sets.RData exists (> 0 bytes) | Fail |
chapter4.manifest | Data manifest is valid JSON | Fail |
chapter4.qa | QA assertions file exists and is valid JSON | Fail |
chapter4.data_mode | QA records the expected data mode (proxy/real) | Fail |
chapter4.qa_status | All Chapter 4 QA assertions passed | Fail |
chapter5.summary | NAM summary CSV exists | Fail |
chapter5.summary_schema | CSV has required columns and > 0 rows | Fail |
chapter5.benchmarks | Validation JSON exists | Fail |
chapter5.benchmark_status | Coefficient check results (proxy: warn if different; real: fail) | Warn (proxy) / Fail (real) |
chapter6.coefficients | Injunctive NAM coefficients CSV exists | Fail |
chapter6.benchmarks | Validation JSON exists | Fail |
chapter6.data_mode | Validation records the expected data mode | Fail |
chapter6.benchmark_status | Coefficient check results | Warn (proxy) / Fail (real) |
Chapter 7 adds checks for network arrays, input manifest, run log, dyadic covariates (non-degenerate), fitted model file, and convergence ratio. Real-data runs also verify coefficient benchmarks.
8. Determinism & Platform Drift
Chapters 4–6 are deterministic for fixed inputs and configuration. Chapter 7 (SAOM) may show cross-platform numeric drift from BLAS/LAPACK and compiler differences, even with fixed seeds.
| Parameter | Value |
|---|---|
| NAM seed | 20250921 |
| SAOM RNG seed | 2022 |
| SAOM Phase 3 iterations | 10000 |
| RSiena version | 1.4.7 (exact CRAN Archive pin) |
Roadmap
What has been completed and what comes next. Updated July 2026.
1. Completed
| Item | Status | Detail |
|---|---|---|
| REDCap/MySQL server stack | Done | Built two-server architecture from bare university VMs: Apache/SSL web server + dedicated MySQL database VM with scoped access and network isolation. |
| Two-project identity separation | Done | Implemented baseline + follow-up REDCap projects with role-based access separation, @HIDDEN-SURVEY/@HIDDEN-FORM action tags, and calculated fields for pseudonymised linkage. |
| Six-wave data collection | Done | Recruited 255 of 375 invited residents, achieved 87% retention across six waves (Sep 2022–Oct 2023), with automated incentive distribution and up to three reminders per wave. |
| R/Make analysis pipeline | Done | Config-driven pipeline covering Chapters 4–7: data preparation, network autocorrelation models, injunctive norm models, and stochastic actor-oriented models. |
| Proxy data generator | Done | Deterministic synthetic data generator producing 255 students × 6 waves with network ties, AUDIT-C scores, norm perceptions, and residence structure. |
| Environment locks | Done | Conda environment + renv.lock (90 packages) + RSiena 1.4.7 pinned from CRAN Archive. Clean solve and restore verified. |
| Chapters 4–6 proxy verification | Done | 15 structural checks, 0 failures, 2 expected proxy-vs-empirical warnings. Reproducible from a clean checkout. |
| Portfolio and privacy generation | Done | Data dictionary, reproducibility manifest, validation dashboard, 5 labelled network pages with embedded SYNTHETIC PROXY DATA provenance. Privacy scans pass. |
| Secret and credential scan | Done | Release candidate scanned for protected paths, known secret patterns, local absolute paths, and unsafe symlinks. No findings. |
| History-free release candidate | Done | Built clean export without private Git history. Private commits do not carry into the public repository. |
| Thesis coefficient reproduction | Done | Chapters 5–6 reproduce every coefficient to 3 decimal places on real data (69 checks). Three code fixes required for exact match documented in Release tab. |
| Infrastructure evidence extraction | Done | Database backup and server configuration archived. Python scripts parse the backup directly without requiring a running database. |
| Portable data dictionaries | Done | Generated REDCap-importable CSVs from the database backup: PIS portal (17 fields), baseline (231 fields, 28 instruments), follow-up (239 fields, 8 instruments, 151 branching rules). |
| Licence and citation | Done | MIT (code) + CC BY 4.0 (documentation). CITATION.cff with machine-readable metadata. |
2. Next
| Item | Status | Detail |
|---|---|---|
| Chapter 7 (SAOM) code | In progress | Analysis complete. Organising and updating pipeline code for public release. |
| Chapter 8 (Interventions) code | In progress | Analysis complete. 462 counterfactual scenarios × 3 chained periods. Organising pipeline code. |
| Thesis compilation | In progress | Chapters written. Integrating make thesis target into the reproducible pipeline. |
| Data access procedure | In progress | Formal data-sharing agreements and institutional governance under development. |
| DOI and archived release | In progress | Version tag and archived release bundle in preparation. |
| Cross-platform reproducibility | Open | All verification performed on macOS arm64. Linux and x86_64 behaviour is untested. |