Skip to content

Commit b66178c

Browse files
jeremymanningclaude
andcommitted
Update FRFR tutorial with improved layout and all features
- Reorganize to 2 rows × 3 columns for Figure 1 (PFR, Lag-CRP, SPC) - Separate Figure 2 for memory fingerprints (early vs late) - Use crack() to split into early (lists 0-7) and late (lists 8-15) - Display all 7 features in fingerprint analysis 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent ef1c330 commit b66178c

1 file changed

Lines changed: 131 additions & 66 deletions

File tree

examples/plot_frfr_data.py

Lines changed: 131 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,9 @@
2626
and lists 9-16 are considered "late" lists.
2727
2828
We'll analyze recall performance using:
29-
1. Serial Position Curve (SPC) - recall probability by encoding position
30-
2. Probability of First Recall (PFR) - probability of recalling each position first
31-
3. Lag-CRP - conditional recall probability by temporal lag
29+
1. Probability of First Recall (PFR) - probability of recalling each position first
30+
2. Lag-CRP - conditional recall probability by temporal lag
31+
3. Serial Position Curve (SPC) - recall probability by encoding position
3232
4. Memory Fingerprint - clustering by multiple features
3333
3434
Reference:
@@ -73,70 +73,135 @@
7373
for cond, count in sorted(condition_counts.items()):
7474
print(f" {cond}: {count}")
7575

76-
# Build per-subject listgroups: early (lists 0-7) vs late (lists 8-15)
77-
# Each subject has their own listgroup since we want to compare early vs late
78-
# within each condition
79-
listgroup = []
80-
for subj_idx in range(egg.n_subjects):
81-
subj_listgroup = []
82-
for list_idx in range(egg.n_lists):
83-
if list_idx < 8:
84-
subj_listgroup.append('early')
85-
else:
86-
subj_listgroup.append('late')
87-
listgroup.append(subj_listgroup)
88-
89-
# Create a listgroup for averaging all lists together (for fingerprint)
90-
listgroup_average = ['average'] * egg.n_lists
91-
92-
# Create figure with 2x2 subplots
93-
fig, axes = plt.subplots(2, 2, figsize=(14, 12))
94-
95-
# 1. Serial Position Curve - by condition, colored by early/late
96-
print("\nAnalyzing Serial Position Curves...")
97-
spc = egg.analyze('spc', listgroup=listgroup)
98-
spc.plot(ax=axes[0, 0], subjgroup=subjgroup, plot_type='subject', legend=True)
99-
axes[0, 0].set_title('Serial Position Curve by Condition (Early vs Late)')
100-
axes[0, 0].set_xlabel('Serial Position')
101-
axes[0, 0].set_ylabel('Recall Probability')
102-
axes[0, 0].set_ylim([0, 1])
103-
# Move legend outside plot
104-
axes[0, 0].legend(loc='upper right', fontsize=7, ncol=2)
105-
106-
# 2. Probability of First Recall - by condition, early/late
107-
print("Analyzing Probability of First Recall...")
108-
pfr = egg.analyze('pfr', listgroup=listgroup)
109-
pfr.plot(ax=axes[0, 1], subjgroup=subjgroup, plot_type='subject', legend=False)
110-
axes[0, 1].set_title('Probability of First Recall by Condition')
111-
axes[0, 1].set_xlabel('Serial Position')
112-
axes[0, 1].set_ylabel('Probability')
113-
axes[0, 1].set_ylim([0, 0.25])
114-
115-
# 3. Lag-CRP - by condition, early/late
116-
print("Analyzing Lag-CRP...")
117-
lagcrp = egg.analyze('lagcrp', listgroup=listgroup)
118-
lagcrp.plot(ax=axes[1, 0], subjgroup=subjgroup, plot_type='subject', legend=False)
119-
axes[1, 0].set_title('Lag-CRP by Condition')
120-
axes[1, 0].set_xlabel('Lag')
121-
axes[1, 0].set_ylabel('Conditional Recall Probability')
122-
axes[1, 0].set_xlim([-10, 10])
123-
axes[1, 0].axvline(x=0, color='gray', linestyle='--', alpha=0.5)
124-
125-
# 4. Memory Fingerprint - by available features
126-
# Note: color and location are list-type features that require special handling
127-
print("Analyzing Memory Fingerprints...")
128-
fingerprint_features = ['category', 'size', 'wordLength', 'firstLetter', 'temporal']
129-
fingerprint = egg.analyze('fingerprint', features=fingerprint_features,
130-
listgroup=listgroup_average)
131-
fingerprint.plot(ax=axes[1, 1], subjgroup=subjgroup, plot_type='subject',
132-
title='Memory Fingerprint by Condition', ylim=[0, 1])
133-
axes[1, 1].set_xlabel('Feature')
134-
axes[1, 1].set_ylabel('Clustering Score')
135-
# No legend here since we already have one in SPC plot
76+
# Split egg into early (lists 0-7) and late (lists 8-15) lists
77+
print("\nSplitting data into early and late lists...")
78+
egg_early = egg.crack(lists=list(range(8)))
79+
egg_late = egg.crack(lists=list(range(8, 16)))
80+
81+
print(f"Early lists egg: {egg_early.n_subjects} subjects, {egg_early.n_lists} lists")
82+
print(f"Late lists egg: {egg_late.n_subjects} subjects, {egg_late.n_lists} lists")
83+
84+
# Create listgroup for averaging across lists within each split
85+
listgroup_early = ['average'] * egg_early.n_lists
86+
listgroup_late = ['average'] * egg_late.n_lists
87+
88+
# ============================================================================
89+
# Figure 1: PFR, Lag-CRP, SPC for Early (top) and Late (bottom) lists
90+
# ============================================================================
91+
print("\n" + "=" * 60)
92+
print("Creating Figure 1: PFR, Lag-CRP, SPC by condition")
93+
print("=" * 60)
94+
95+
fig1, axes1 = plt.subplots(2, 3, figsize=(18, 10))
96+
97+
# --- Top row: Early lists ---
98+
print("\nAnalyzing early lists...")
99+
100+
# PFR - Early
101+
print(" Computing PFR (early)...")
102+
pfr_early = egg_early.analyze('pfr', listgroup=listgroup_early)
103+
pfr_early.plot(ax=axes1[0, 0], subjgroup=subjgroup, plot_type='subject', legend=True)
104+
axes1[0, 0].set_title('Probability of First Recall (Early Lists)')
105+
axes1[0, 0].set_xlabel('Serial Position')
106+
axes1[0, 0].set_ylabel('Probability')
107+
axes1[0, 0].set_ylim([0, 0.3])
108+
axes1[0, 0].legend(loc='upper right', fontsize=6, ncol=2)
109+
110+
# Lag-CRP - Early
111+
print(" Computing Lag-CRP (early)...")
112+
lagcrp_early = egg_early.analyze('lagcrp', listgroup=listgroup_early)
113+
lagcrp_early.plot(ax=axes1[0, 1], subjgroup=subjgroup, plot_type='subject', legend=False)
114+
axes1[0, 1].set_title('Lag-CRP (Early Lists)')
115+
axes1[0, 1].set_xlabel('Lag')
116+
axes1[0, 1].set_ylabel('Conditional Recall Probability')
117+
axes1[0, 1].set_xlim([-10, 10])
118+
axes1[0, 1].axvline(x=0, color='gray', linestyle='--', alpha=0.5)
119+
120+
# SPC - Early
121+
print(" Computing SPC (early)...")
122+
spc_early = egg_early.analyze('spc', listgroup=listgroup_early)
123+
spc_early.plot(ax=axes1[0, 2], subjgroup=subjgroup, plot_type='subject', legend=False)
124+
axes1[0, 2].set_title('Serial Position Curve (Early Lists)')
125+
axes1[0, 2].set_xlabel('Serial Position')
126+
axes1[0, 2].set_ylabel('Recall Probability')
127+
axes1[0, 2].set_ylim([0, 1])
128+
129+
# --- Bottom row: Late lists ---
130+
print("\nAnalyzing late lists...")
131+
132+
# PFR - Late
133+
print(" Computing PFR (late)...")
134+
pfr_late = egg_late.analyze('pfr', listgroup=listgroup_late)
135+
pfr_late.plot(ax=axes1[1, 0], subjgroup=subjgroup, plot_type='subject', legend=False)
136+
axes1[1, 0].set_title('Probability of First Recall (Late Lists)')
137+
axes1[1, 0].set_xlabel('Serial Position')
138+
axes1[1, 0].set_ylabel('Probability')
139+
axes1[1, 0].set_ylim([0, 0.3])
140+
141+
# Lag-CRP - Late
142+
print(" Computing Lag-CRP (late)...")
143+
lagcrp_late = egg_late.analyze('lagcrp', listgroup=listgroup_late)
144+
lagcrp_late.plot(ax=axes1[1, 1], subjgroup=subjgroup, plot_type='subject', legend=False)
145+
axes1[1, 1].set_title('Lag-CRP (Late Lists)')
146+
axes1[1, 1].set_xlabel('Lag')
147+
axes1[1, 1].set_ylabel('Conditional Recall Probability')
148+
axes1[1, 1].set_xlim([-10, 10])
149+
axes1[1, 1].axvline(x=0, color='gray', linestyle='--', alpha=0.5)
150+
151+
# SPC - Late
152+
print(" Computing SPC (late)...")
153+
spc_late = egg_late.analyze('spc', listgroup=listgroup_late)
154+
spc_late.plot(ax=axes1[1, 2], subjgroup=subjgroup, plot_type='subject', legend=False)
155+
axes1[1, 2].set_title('Serial Position Curve (Late Lists)')
156+
axes1[1, 2].set_xlabel('Serial Position')
157+
axes1[1, 2].set_ylabel('Recall Probability')
158+
axes1[1, 2].set_ylim([0, 1])
136159

137160
plt.tight_layout()
138-
plt.suptitle('Feature-Rich Free Recall (FRFR) Dataset Analysis', y=1.02, fontsize=14)
139-
plt.savefig('frfr_analysis.png', dpi=150, bbox_inches='tight')
161+
fig1.suptitle('FRFR Dataset: Recall Analyses by Condition (Early vs Late Lists)',
162+
y=1.02, fontsize=14)
163+
plt.savefig('frfr_recall_analysis.png', dpi=150, bbox_inches='tight')
164+
print("\nSaved Figure 1 to frfr_recall_analysis.png")
165+
166+
# ============================================================================
167+
# Figure 2: Memory Fingerprints for Early (left) and Late (right) lists
168+
# ============================================================================
169+
print("\n" + "=" * 60)
170+
print("Creating Figure 2: Memory Fingerprints by condition")
171+
print("=" * 60)
172+
173+
fig2, axes2 = plt.subplots(1, 2, figsize=(14, 6))
174+
175+
# Features for fingerprint analysis
176+
fingerprint_features = ['category', 'size', 'color', 'location',
177+
'wordLength', 'firstLetter', 'temporal']
178+
179+
# Fingerprint - Early lists
180+
print("\nComputing fingerprints (early lists)...")
181+
fp_early = egg_early.analyze('fingerprint', features=fingerprint_features,
182+
listgroup=listgroup_early)
183+
fp_early.plot(ax=axes2[0], subjgroup=subjgroup, plot_type='subject',
184+
title='Memory Fingerprint (Early Lists)', ylim=[0, 1])
185+
axes2[0].set_xlabel('Feature')
186+
axes2[0].set_ylabel('Clustering Score')
187+
axes2[0].legend(loc='upper right', fontsize=7, ncol=2)
188+
189+
# Fingerprint - Late lists
190+
print("Computing fingerprints (late lists)...")
191+
fp_late = egg_late.analyze('fingerprint', features=fingerprint_features,
192+
listgroup=listgroup_late)
193+
fp_late.plot(ax=axes2[1], subjgroup=subjgroup, plot_type='subject',
194+
title='Memory Fingerprint (Late Lists)', ylim=[0, 1])
195+
axes2[1].set_xlabel('Feature')
196+
axes2[1].set_ylabel('Clustering Score')
197+
# No legend on second plot since first has it
198+
199+
plt.tight_layout()
200+
fig2.suptitle('FRFR Dataset: Memory Fingerprints by Condition (Early vs Late Lists)',
201+
y=1.02, fontsize=14)
202+
plt.savefig('frfr_fingerprint_analysis.png', dpi=150, bbox_inches='tight')
203+
print("Saved Figure 2 to frfr_fingerprint_analysis.png")
204+
140205
plt.show()
141206

142-
print("\nAnalysis complete! Saved plot to frfr_analysis.png")
207+
print("\nAnalysis complete!")

0 commit comments

Comments
 (0)