Skip to content

Commit fcf581d

Browse files
committed
docs: Add comprehensive repository documentation
- Add detailed technical documentation for hierarchical psychometric function model - Include mathematical framework with LaTeX formulas for model specification - Document complete data simulation workflow using BRMS demo - Provide instructions for reproducing all key figures (Figures 1-6) - Add comprehensive Shiny app deployment and usage guide - Include file structure overview and dependency requirements - Add citation information and contact details This documentation makes the repository fully self-contained and accessible for researchers wanting to apply hierarchical Bayesian methods to interoceptive tasks or reproduce the paper's results.
1 parent c2ac0f7 commit fcf581d

File tree

1 file changed

+318
-1
lines changed

1 file changed

+318
-1
lines changed

README.md

Lines changed: 318 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,318 @@
1-
# Hierarchical-Interoception
1+
# Hierarchical-Interoception
2+
3+
This repository contains the complete analysis pipeline for hierarchical psychometric function modeling applied to interoceptive tasks. The project implements Bayesian hierarchical models for analyzing Heart Rate Discrimination Task (HRDT) and Respiratory Resistance Sensitivity Task (RRST) data, with comprehensive power analysis capabilities and interactive visualization tools.
4+
5+
## Table of Contents
6+
7+
1. [Technical Details of the Hierarchical Model](#technical-details-of-the-hierarchical-model)
8+
2. [Data Simulation Workflow](#data-simulation-workflow)
9+
3. [Reproducing Key Figures](#reproducing-key-figures)
10+
4. [Shiny App Deployment and Usage](#shiny-app-deployment-and-usage)
11+
12+
## Technical Details of the Hierarchical Model
13+
14+
### Model Formulation
15+
16+
The hierarchical model implements a psychometric function with three key parameters:
17+
18+
1. **Threshold (α)**: The stimulus intensity at which the probability of correct response is 0.5
19+
2. **Slope (β)**: The steepness of the psychometric function, indicating sensitivity
20+
3. **Lapse rate (λ)**: The asymptotic error rate for extreme stimulus intensities
21+
22+
### Mathematical Framework
23+
24+
The psychometric function is defined as:
25+
26+
$$P(response) = \lambda + (1 - 2\lambda) \cdot \left(0.5 + 0.5 \cdot \text{erf}\left(\frac{\beta \cdot (x - \alpha)}{\sqrt{2}}\right)\right)$$
27+
28+
Where:
29+
- $x$ is the stimulus intensity
30+
- $\alpha$ is the threshold parameter
31+
- $\beta$ is the slope parameter (constrained to be positive)
32+
- $\lambda$ is the lapse rate (constrained to [0, 0.5])
33+
- $\text{erf}$ is the error function
34+
35+
### Hierarchical Structure
36+
37+
The model implements a three-level hierarchy:
38+
39+
1. **Group-level parameters**: Population means and variances for each parameter
40+
2. **Subject-level parameters**: Individual deviations from group means
41+
3. **Trial-level observations**: Binary responses to stimulus presentations
42+
43+
### Stan Implementation
44+
45+
The model is implemented in Stan with the following key components:
46+
47+
```stan
48+
// Group-level parameters
49+
vector[N] gm; // Group means for all parameters
50+
vector<lower = 0>[N] tau_u; // Between-participant scales
51+
matrix[N, S] z_expo; // Participant deviations
52+
53+
// Transformed parameters
54+
vector[S] alpha_int = (gm[1] + (tau_u[1] * z_expo[1,]))';
55+
vector[S] beta_int = (gm[2] + (tau_u[2] * z_expo[2,]))';
56+
vector[S] lapse = (inv_logit(gm[3] + (tau_u[3] * z_expo[3,])) / 2)';
57+
```
58+
59+
### Prior Specifications
60+
61+
The model uses empirically informed priors derived from previous studies:
62+
63+
- **Threshold (α)**: Normal(-8.67, 0.52×10) for intercept, Normal(0, 11.23) for treatment effect
64+
- **Slope (β)**: Normal(-2.3, 0.02×10) for intercept, Normal(0, 0.34) for treatment effect
65+
- **Lapse rate (λ)**: Normal(-4.32, 0.29)
66+
67+
### Model Comparison
68+
69+
The repository supports both Gaussian and Gumbel cumulative distribution functions:
70+
71+
- **Gaussian**: Uses the error function (erf) for the cumulative normal
72+
- **Gumbel**: Uses the exponential function for the cumulative Gumbel
73+
74+
Model comparison is performed using leave-one-out cross-validation (LOO-CV) with moment matching.
75+
76+
## Data Simulation Workflow
77+
78+
### Using the BRMS Demo
79+
80+
The `apps & wrappers/BRMS demo.Rmd` provides a complete workflow for data simulation and analysis:
81+
82+
1. **Data Simulation**: Generate synthetic data with known parameters
83+
2. **Model Specification**: Define the hierarchical psychometric function
84+
3. **Model Fitting**: Fit using BRMS with Stan backend
85+
4. **Diagnostics**: Check convergence and sampling quality
86+
5. **Inference**: Extract posterior distributions and credible intervals
87+
88+
### Simulation Parameters
89+
90+
```r
91+
# Design parameters
92+
n_subj_HRDT <- 50
93+
n_rep_HRDT <- 30
94+
x_seq_HRDT <- rep(seq(-40, 40, 5), n_rep_HRDT)
95+
96+
# Group-level parameters
97+
mu_alpha_HRDT <- -8.6
98+
sd_alpha_HRDT <- 11.6
99+
mu_beta_HRDT <- -2.3
100+
sd_beta_HRDT <- 0.3
101+
mu_lambda_HRDT <- -4.2
102+
sd_lambda_HRDT <- 2
103+
```
104+
105+
### Model Specification in BRMS
106+
107+
```r
108+
bff_HRDT = bf(
109+
y|trials(n) ~ (inv_logit(lambda) / 2 +
110+
(1-inv_logit(lambda)) *
111+
(0.5 + 0.5 * erf(exp(beta)*(x-alpha)/(sqrt(2))))),
112+
alpha ~ condition + (condition | subj),
113+
beta ~ condition + (condition | subj),
114+
lambda ~ (1 | subj),
115+
nl = TRUE,
116+
family = binomial(link = "identity")
117+
)
118+
```
119+
120+
### Running the Analysis
121+
122+
```r
123+
fit_eip_HRDT <- brm(
124+
bff_HRDT,
125+
data = sim_data_HRDT,
126+
chains = 4,
127+
cores = 4,
128+
seed = seed,
129+
backend = "cmdstan",
130+
warmup = 2000,
131+
iter = 4000,
132+
control = list(
133+
adapt_delta = 0.9,
134+
max_treedepth = 10
135+
),
136+
prior = empirically_informed_priors_HRDT
137+
)
138+
```
139+
140+
## Reproducing Key Figures
141+
142+
### Figure 1: Psychometric Function Forms
143+
144+
**File**: `figures_scripts/Figure1.Rmd`
145+
146+
This figure compares different psychometric function formulations:
147+
148+
```r
149+
PFs <- tibble(x = seq(-6, 11, .001)) %>%
150+
mutate(
151+
Gaussian = pnorm(x - 2),
152+
Gumbel = 1 - exp(-10^(0.4 * (x - 2.4)))
153+
) %>%
154+
pivot_longer(cols = !x) %>%
155+
rename(Formulation = name)
156+
```
157+
158+
**To reproduce**:
159+
```r
160+
source("figures_scripts/Figure1.Rmd")
161+
```
162+
163+
### Figure 3: Model Recovery
164+
165+
**File**: `figures_scripts/Figure3.Rmd`
166+
167+
This figure shows model recovery performance across different generative models:
168+
169+
```r
170+
# Load model recovery results
171+
load(here::here("results", "model_and_parameter_recovery.RData"))
172+
model_recovery <- results
173+
174+
# Calculate recovery statistics
175+
mod_comp <- tibble(
176+
winning_model = rep(NaN, 400),
177+
generative_model = rep(NaN, 400),
178+
any_pareto_k = rep(NaN, 400),
179+
significant = rep(NaN, 400),
180+
meanrhat = rep(NaN, 400),
181+
sum_div = rep(NaN, 400)
182+
)
183+
```
184+
185+
**To reproduce**:
186+
```r
187+
source("figures_scripts/Figure3.Rmd")
188+
```
189+
190+
### Additional Figures
191+
192+
- **Figure 4**: Parameter recovery plots (`figures_scripts/Figure4.Rmd`)
193+
- **Figure 5**: Power analysis results (`figures_scripts/Figure5.Rmd`)
194+
- **Figure 6**: Hierarchical vs. simple t-test comparison (`figures_scripts/Figure6.Rmd`)
195+
196+
## Shiny App Deployment and Usage
197+
198+
### App Overview
199+
200+
The Shiny app (`apps & wrappers/shiny app.R`) provides an interactive interface for exploring power analysis results with three main panels:
201+
202+
1. **Power Grid**: Visualize power contours across different sample sizes
203+
2. **Effect Size vs. Power**: Examine power as a function of effect size
204+
3. **Manual Input**: Get specific power estimates for custom parameters
205+
206+
### Deployment
207+
208+
#### Local Deployment
209+
210+
1. **Install Dependencies**:
211+
```r
212+
install.packages(c("shiny", "tidyverse", "flextable", "posterior"))
213+
```
214+
215+
2. **Run the App**:
216+
```r
217+
shiny::runApp("apps & wrappers/shiny app.R")
218+
```
219+
220+
#### Server Deployment
221+
222+
1. **Prepare for Deployment**:
223+
```r
224+
# Ensure all data files are accessible
225+
# Check that results/power analysis/Extracted/all_draws.csv exists
226+
```
227+
228+
2. **Deploy to Shiny Server**:
229+
```bash
230+
# Copy files to server
231+
scp -r "apps & wrappers/" user@server:/path/to/shiny/apps/
232+
scp -r results/ user@server:/path/to/shiny/data/
233+
```
234+
235+
### App Usage
236+
237+
#### Power Grid Panel
238+
239+
1. **Select Parameter**: Choose between "Threshold" or "Slope"
240+
2. **Set Effect Size**: Specify the desired effect size (0.0 to 1.0)
241+
3. **Adjust Sample Ranges**: Use sliders to set subject and trial ranges
242+
4. **Choose Power Level**: Select desired power (0.80, 0.90, or 0.95)
243+
5. **Interpret Results**: Contour lines show combinations achieving target power
244+
245+
#### Effect Size vs. Power Panel
246+
247+
1. **Set Sample Size**: Specify number of subjects and trials
248+
2. **View Power Curve**: See how power changes with effect size
249+
3. **Identify Minimum Effect**: Find the smallest detectable effect size
250+
251+
#### Manual Input Panel
252+
253+
1. **Enter Parameters**: Specify exact sample sizes and effect size
254+
2. **Submit Query**: Get precise power estimates
255+
3. **View Results**: See power for hierarchical, simple t-test, and uncertainty propagation methods
256+
257+
### Data Requirements
258+
259+
The app requires the following data files:
260+
- `results/power analysis/Extracted/all_draws.csv`: Power analysis results
261+
- `results/power analysis/Extracted/all_data.csv`: Summary statistics
262+
263+
### Customization
264+
265+
To modify the app for different analyses:
266+
267+
1. **Update Data Source**: Modify the `all_data` loading in the server function
268+
2. **Add New Parameters**: Extend the parameter selection options
269+
3. **Customize Plots**: Modify the ggplot aesthetics and themes
270+
4. **Add New Panels**: Create additional tabPanels for new functionality
271+
272+
## File Structure
273+
274+
```
275+
Hierarchical-Interoception/
276+
├── Analysis/ # Main analysis scripts
277+
├── apps & wrappers/ # BRMS demo and Shiny app
278+
├── Data/ # Raw data files
279+
├── figures/ # Generated figures
280+
├── figures_scripts/ # Figure generation scripts
281+
├── results/ # Analysis results and power analysis
282+
├── scripts/ # Utility functions and main scripts
283+
├── simulated_data/ # Simulated datasets
284+
└── stanmodels/ # Stan model definitions
285+
```
286+
287+
## Dependencies
288+
289+
### Required R Packages
290+
```r
291+
install.packages(c(
292+
"cmdstanr", "tidyverse", "posterior", "bayesplot",
293+
"tidybayes", "rstan", "brms", "pracma", "shiny",
294+
"flextable", "loo", "furrr"
295+
))
296+
```
297+
298+
### Stan Installation
299+
```r
300+
# Install cmdstanr
301+
install.packages("cmdstanr", repos = c("https://mc-stan.org/r-packages/", getOption("repos")))
302+
303+
# Check cmdstan installation
304+
cmdstanr::check_cmdstan_toolchain()
305+
cmdstanr::install_cmdstan()
306+
```
307+
308+
## Citation
309+
310+
If you use this code in your research, please cite:
311+
312+
```
313+
Courtin, A.S., & Fischer Ehmsen, J. (2025). Hierarchical Bayesian modeling of interoceptive psychometric functions. [Paper DOI to be added]
314+
```
315+
316+
## Contact
317+
318+
For questions or issues with this repository, please contact the authors or open an issue on the repository page.

0 commit comments

Comments
 (0)