@yibeichan/claude-skills 1.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +98 -0
  3. package/cli.js +272 -0
  4. package/install.py +240 -0
  5. package/package.json +44 -0
  6. package/skills/bidsapp-nidm-standards/SKILL.md +202 -0
  7. package/skills/bidsapp-nidm-standards/references/babs_config.md +20 -0
  8. package/skills/bidsapp-nidm-standards/references/cli_arguments.md +76 -0
  9. package/skills/bidsapp-nidm-standards/references/container_patterns.md +53 -0
  10. package/skills/bidsapp-nidm-standards/references/nidm_integration.md +403 -0
  11. package/skills/bidsapp-nidm-standards/references/repo_structure.md +121 -0
  12. package/skills/bidsapp-nidm-standards/references/testing_patterns.md +82 -0
  13. package/skills/dicom2fmriprep/SKILL.md +377 -0
  14. package/skills/dicom2fmriprep/evals/evals.json +26 -0
  15. package/skills/dicom2fmriprep/references/babs-details.md +407 -0
  16. package/skills/dicom2fmriprep/references/fmriprep-details.md +250 -0
  17. package/skills/dicom2fmriprep/references/heudiconv-details.md +243 -0
  18. package/skills/fmri-ssm/SKILL.md +317 -0
  19. package/skills/fmri-ssm/references/code_templates.md +1570 -0
  20. package/skills/fmri-ssm/references/downstream_analysis.md +680 -0
  21. package/skills/fmri-ssm/references/group_inference.md +608 -0
  22. package/skills/fmri-ssm/references/hrf_modeling.md +447 -0
  23. package/skills/fmri-ssm/references/model_catalog.md +436 -0
  24. package/skills/fmri-ssm/references/paradigm_guide.md +406 -0
  25. package/skills/fmri-ssm/references/preprocessing.md +614 -0
  26. package/skills/fmri-ssm.zip +0 -0
  27. package/skills/neuroimaging-qc/SKILL.md +203 -0
  28. package/skills/neuroimaging-qc/references/eeg_qc.md +400 -0
  29. package/skills/neuroimaging-qc/references/fmri_qc.md +343 -0
  30. package/skills/neuroimaging-qc/references/fnirs_qc.md +430 -0
  31. package/skills/neuroimaging-qc/references/structural_qc.md +454 -0
  32. package/skills/neuroimaging-qc/scripts/parse_fmriprep_confounds.py +153 -0
  33. package/skills/neuroimaging-qc/scripts/parse_mriqc.py +114 -0
  34. package/skills/neuroimaging-qc/scripts/qc_report.py +295 -0
  35. package/skills/scientific-writer/SKILL.md +202 -0
  36. package/skills/scientific-writer/references/citation_styles.md +163 -0
  37. package/skills/scientific-writer/references/field_conventions.md +245 -0
  38. package/skills/scientific-writer/references/figures_tables.md +225 -0
  39. package/skills/scientific-writer/references/reporting_guidelines.md +225 -0
  40. package/skills.json +54 -0
@@ -0,0 +1,430 @@
1
+ # fNIRS QC Reference
2
+
3
+ Comprehensive guide for QC of functional near-infrared spectroscopy (fNIRS) data.
4
+
5
+ ## Table of Contents
6
+ 1. [Signal Quality Metrics](#signal-quality-metrics)
7
+ 2. [Channel-Level QC](#channel-level-qc)
8
+ 3. [Motion Artifact Detection](#motion-artifact-detection)
9
+ 4. [Subject-Level Exclusion](#subject-level-exclusion)
10
+ 5. [Population Considerations](#population-considerations)
11
+ 6. [Python Examples](#python-examples)
12
+
13
+ ## Signal Quality Metrics
14
+
15
+ ### Scalp Coupling Index (SCI)
16
+
17
+ **Definition**: Measure of optode-scalp coupling quality based on cardiac pulsation detection.
18
+
19
+ **Interpretation:**
20
+ - Range: 0-1 (higher = better coupling)
21
+ - Threshold: SCI > 0.7-0.8 typically acceptable
22
+ - Based on correlation between wavelengths at cardiac frequency
23
+
24
+ **Calculation principle:**
25
+ - Good coupling → visible cardiac pulsation in signal
26
+ - Poor coupling → no cardiac signal, likely hair/poor contact
27
+
28
+ ### Peak Spectral Power (PSP)
29
+
30
+ **Definition**: Power at cardiac frequency relative to total power.
31
+
32
+ **Interpretation:**
33
+ - Higher values indicate clear cardiac signal (good coupling)
34
+ - Low PSP suggests poor signal quality
35
+
36
+ ### Coefficient of Variation (CV)
37
+
38
+ **Definition**: Standard deviation / mean of raw signal intensity.
39
+
40
+ **Interpretation:**
41
+ - Low CV (<10%): Stable signal
42
+ - High CV (>10-15%): Variable signal, potential motion/coupling issues
43
+
44
+ ### Signal-to-Noise Ratio (SNR)
45
+
46
+ **Calculation:**
47
+ ```
48
+ SNR = mean(signal) / std(noise)
49
+ ```
50
+
51
+ **Interpretation:**
52
+ - Higher is better
53
+ - Compare across channels within subject
54
+
55
+ ## Channel-Level QC
56
+
57
+ ### Bad Channel Indicators
58
+
59
+ 1. **Saturated signal**: Intensity at detector limit
60
+ 2. **Zero/flat signal**: No light detected
61
+ 3. **Excessive noise**: High variance unrelated to task
62
+ 4. **Poor SCI**: SCI < 0.7
63
+ 5. **Negative values**: After optical density conversion (physically impossible)
64
+
65
+ ### Channel Rejection Criteria
66
+
67
+ | Metric | Reject Threshold | Notes |
68
+ |--------|-----------------|-------|
69
+ | SCI | < 0.7 | Coupling quality |
70
+ | CV | > 15% | Signal stability |
71
+ | Heart rate detectability | Not detected | Coupling validation |
72
+ | Negative OD values | Any | Data integrity |
73
+ | SNR | < sample mean - 2 SD | Relative quality |
74
+
75
+ ### Maximum Acceptable Channel Loss
76
+
77
+ **Guidelines:**
78
+ - <20% of channels: Acceptable for most analyses
79
+ - 20-40%: Consider with caution, limit spatial inferences
80
+ - >40%: May need to exclude subject or use reduced channel set
81
+
82
+ ## Motion Artifact Detection
83
+
84
+ ### Motion Artifact Characteristics
85
+
86
+ - **Spikes**: Rapid, large amplitude changes
87
+ - **Baseline shifts**: Step changes in signal level
88
+ - **Slow drifts**: Gradual changes from optode movement
89
+
90
+ ### Detection Methods
91
+
92
+ **1. Threshold-based:**
93
+ - Detect samples exceeding amplitude threshold
94
+ - Flag abrupt changes (derivative threshold)
95
+
96
+ **2. Moving window:**
97
+ - Calculate local statistics
98
+ - Flag windows with anomalous values
99
+
100
+ **3. Wavelet-based:**
101
+ - Decompose signal into frequency bands
102
+ - Identify motion-related components
103
+
104
+ ### Correction Strategies
105
+
106
+ **1. Rejection:**
107
+ - Remove contaminated time segments
108
+ - Simple but loses data
109
+
110
+ **2. Spline interpolation:**
111
+ - Interpolate over short artifacts
112
+ - Preserves data length
113
+
114
+ **3. Wavelet filtering:**
115
+ - Remove motion-related wavelet components
116
+ - Preserves more data
117
+
118
+ **4. Principal Component Analysis (PCA):**
119
+ - Remove motion-related components
120
+ - Global artifact removal
121
+
122
+ **5. Targeted PCA / tPCA:**
123
+ - More targeted motion artifact removal
124
+
125
+ ### Homer3 Motion Correction Functions
126
+
127
+ | Function | Description | Use Case |
128
+ |----------|-------------|----------|
129
+ | `hmrR_MotionArtifact` | Detect motion artifacts | Initial detection |
130
+ | `hmrR_MotionCorrectSpline` | Spline interpolation | Short artifacts |
131
+ | `hmrR_MotionCorrectWavelet` | Wavelet filtering | Broader correction |
132
+ | `hmrR_MotionCorrectPCArecurse` | Recursive PCA | Persistent artifacts |
133
+
134
+ ## Subject-Level Exclusion
135
+
136
+ ### Exclusion Criteria
137
+
138
+ **Quantitative:**
139
+ - >40% channels rejected
140
+ - >50% of data contaminated by motion
141
+ - Insufficient task trials after artifact rejection
142
+ - Technical failures (optode disconnection, recording errors)
143
+
144
+ **Qualitative:**
145
+ - Unable to achieve adequate optode placement (thick/dark hair)
146
+ - Persistent artifacts not correctable
147
+ - Subject non-compliance
148
+
149
+ ### QC Checklist
150
+
151
+ ```
152
+ □ Raw signal inspection (all channels)
153
+ □ Scalp coupling index check
154
+ □ Motion artifact detection
155
+ □ Channel pruning (bad channels removed)
156
+ □ Motion correction applied
157
+ □ Final signal quality assessment
158
+ □ Task-related segments verified
159
+ □ Hemodynamic response plausibility check
160
+ ```
161
+
162
+ ## Population Considerations
163
+
164
+ ### Infants
165
+
166
+ **Unique considerations:**
167
+ - Different optode configurations (smaller head)
168
+ - More motion expected
169
+ - Hair less of an issue (less/finer hair)
170
+ - Different hemodynamic response characteristics
171
+
172
+ **Adjusted criteria:**
173
+ - More lenient motion thresholds
174
+ - Shorter usable segments acceptable
175
+ - Visual inspection critical
176
+
177
+ ### Clinical Populations
178
+
179
+ **Considerations:**
180
+ - Altered hemodynamics (stroke, vascular disease)
181
+ - Medication effects
182
+ - Potential structural abnormalities affecting light propagation
183
+ - May have compliance challenges
184
+
185
+ ## Python Examples (MNE-NIRS)
186
+
187
+ ### Basic Signal Quality Check
188
+
189
+ ```python
190
+ import mne
191
+ import mne_nirs
192
+ import numpy as np
193
+
194
+ def check_fnirs_quality(raw):
195
+ """
196
+ Basic fNIRS signal quality assessment.
197
+ """
198
+ # Get data
199
+ data = raw.get_data()
200
+
201
+ qc_results = {
202
+ 'n_channels': len(raw.ch_names),
203
+ 'duration_sec': raw.times[-1],
204
+ 'sfreq': raw.info['sfreq'],
205
+ }
206
+
207
+ # Calculate per-channel statistics
208
+ channel_stats = []
209
+ for i, ch_name in enumerate(raw.ch_names):
210
+ ch_data = data[i, :]
211
+ stats = {
212
+ 'channel': ch_name,
213
+ 'mean': np.mean(ch_data),
214
+ 'std': np.std(ch_data),
215
+ 'cv': np.std(ch_data) / np.abs(np.mean(ch_data)) * 100,
216
+ 'min': np.min(ch_data),
217
+ 'max': np.max(ch_data),
218
+ }
219
+ channel_stats.append(stats)
220
+
221
+ qc_results['channel_stats'] = channel_stats
222
+
223
+ return qc_results
224
+
225
+
226
+ def calculate_sci(raw, cardiac_freq_range=(0.5, 2.5)):
227
+ """
228
+ Calculate Scalp Coupling Index for fNIRS channels.
229
+
230
+ SCI based on correlation between wavelengths at cardiac frequency.
231
+ """
232
+ from scipy import signal
233
+
234
+ # This is a simplified SCI calculation
235
+ # Full implementation would pair wavelengths by source-detector
236
+
237
+ sfreq = raw.info['sfreq']
238
+ data = raw.get_data()
239
+
240
+ sci_values = []
241
+
242
+ # For each channel, calculate cardiac power ratio
243
+ for i in range(data.shape[0]):
244
+ ch_data = data[i, :]
245
+
246
+ # Calculate PSD
247
+ freqs, psd = signal.welch(ch_data, fs=sfreq, nperseg=int(4*sfreq))
248
+
249
+ # Find cardiac band
250
+ cardiac_mask = (freqs >= cardiac_freq_range[0]) & (freqs <= cardiac_freq_range[1])
251
+
252
+ if np.any(cardiac_mask):
253
+ cardiac_power = np.max(psd[cardiac_mask])
254
+ total_power = np.sum(psd)
255
+ psp = cardiac_power / total_power
256
+ else:
257
+ psp = 0
258
+
259
+ # SCI approximation (would need paired wavelengths for true SCI)
260
+ sci_values.append(psp)
261
+
262
+ return np.array(sci_values)
263
+ ```
264
+
265
+ ### Motion Artifact Detection
266
+
267
+ ```python
268
+ def detect_motion_artifacts(raw, threshold_std=3.0, window_sec=1.0):
269
+ """
270
+ Detect motion artifacts using threshold-based method.
271
+ """
272
+ data = raw.get_data()
273
+ sfreq = raw.info['sfreq']
274
+ n_samples = data.shape[1]
275
+ window_samples = int(window_sec * sfreq)
276
+
277
+ # Calculate global signal variance
278
+ global_std = np.std(data)
279
+ threshold = threshold_std * global_std
280
+
281
+ # Detect artifacts (samples where derivative exceeds threshold)
282
+ diff_data = np.diff(data, axis=1)
283
+ artifacts = np.zeros(n_samples, dtype=bool)
284
+
285
+ for i in range(data.shape[0]):
286
+ ch_artifacts = np.abs(diff_data[i, :]) > threshold
287
+ # Expand to include surrounding samples
288
+ for j in np.where(ch_artifacts)[0]:
289
+ start = max(0, j - window_samples)
290
+ end = min(n_samples, j + window_samples)
291
+ artifacts[start:end] = True
292
+
293
+ artifact_pct = 100 * np.sum(artifacts) / n_samples
294
+
295
+ return artifacts, artifact_pct
296
+
297
+
298
+ def prune_bad_channels(raw, sci_threshold=0.7, cv_threshold=15):
299
+ """
300
+ Identify and mark bad channels based on quality metrics.
301
+ """
302
+ qc = check_fnirs_quality(raw)
303
+ sci = calculate_sci(raw)
304
+
305
+ bad_channels = []
306
+
307
+ for i, stats in enumerate(qc['channel_stats']):
308
+ ch_name = stats['channel']
309
+
310
+ # Check CV
311
+ if stats['cv'] > cv_threshold:
312
+ bad_channels.append(ch_name)
313
+ continue
314
+
315
+ # Check SCI
316
+ if sci[i] < sci_threshold:
317
+ bad_channels.append(ch_name)
318
+ continue
319
+
320
+ # Check for negative values (if optical density)
321
+ if stats['min'] < 0:
322
+ bad_channels.append(ch_name)
323
+
324
+ return bad_channels
325
+ ```
326
+
327
+ ### Complete QC Pipeline
328
+
329
+ ```python
330
+ def fnirs_qc_pipeline(raw_path, output_dir=None):
331
+ """
332
+ Complete fNIRS QC pipeline.
333
+ """
334
+ import os
335
+
336
+ # Load data
337
+ raw = mne.io.read_raw_snirf(raw_path, preload=True)
338
+
339
+ # Basic quality check
340
+ qc_results = check_fnirs_quality(raw)
341
+
342
+ # Calculate SCI
343
+ sci_values = calculate_sci(raw)
344
+ qc_results['sci_mean'] = np.mean(sci_values)
345
+ qc_results['sci_min'] = np.min(sci_values)
346
+ qc_results['n_low_sci'] = np.sum(sci_values < 0.7)
347
+
348
+ # Detect motion artifacts
349
+ artifacts, artifact_pct = detect_motion_artifacts(raw)
350
+ qc_results['artifact_pct'] = artifact_pct
351
+
352
+ # Identify bad channels
353
+ bad_channels = prune_bad_channels(raw)
354
+ qc_results['n_bad_channels'] = len(bad_channels)
355
+ qc_results['bad_channels'] = bad_channels
356
+ qc_results['bad_channel_pct'] = 100 * len(bad_channels) / qc_results['n_channels']
357
+
358
+ # Determine inclusion
359
+ include = True
360
+ reasons = []
361
+
362
+ if qc_results['bad_channel_pct'] > 40:
363
+ include = False
364
+ reasons.append(f"Bad channels: {qc_results['bad_channel_pct']:.1f}% > 40%")
365
+
366
+ if qc_results['artifact_pct'] > 50:
367
+ include = False
368
+ reasons.append(f"Motion artifacts: {qc_results['artifact_pct']:.1f}% > 50%")
369
+
370
+ qc_results['include'] = include
371
+ qc_results['exclusion_reasons'] = reasons
372
+
373
+ return qc_results
374
+ ```
375
+
376
+ ### QC Report Generation
377
+
378
+ ```python
379
+ def generate_fnirs_report(qc_results, output_path):
380
+ """Generate fNIRS QC report."""
381
+
382
+ report = f"""
383
+ fNIRS Quality Control Report
384
+ ============================
385
+
386
+ Recording Information
387
+ ---------------------
388
+ Channels: {qc_results['n_channels']}
389
+ Duration: {qc_results['duration_sec']:.1f} seconds
390
+ Sampling rate: {qc_results['sfreq']} Hz
391
+
392
+ Signal Quality
393
+ --------------
394
+ Mean SCI: {qc_results.get('sci_mean', 'N/A'):.3f}
395
+ Min SCI: {qc_results.get('sci_min', 'N/A'):.3f}
396
+ Channels with low SCI: {qc_results.get('n_low_sci', 'N/A')}
397
+
398
+ Channel Quality
399
+ ---------------
400
+ Bad channels: {qc_results['n_bad_channels']} ({qc_results['bad_channel_pct']:.1f}%)
401
+ Bad channel names: {', '.join(qc_results['bad_channels']) if qc_results['bad_channels'] else 'None'}
402
+
403
+ Motion Artifacts
404
+ ----------------
405
+ Data affected by motion: {qc_results['artifact_pct']:.1f}%
406
+
407
+ Inclusion Decision
408
+ ------------------
409
+ Include: {'Yes' if qc_results['include'] else 'No'}
410
+ """
411
+
412
+ if not qc_results['include']:
413
+ report += f"Exclusion reasons:\n"
414
+ for reason in qc_results['exclusion_reasons']:
415
+ report += f" - {reason}\n"
416
+
417
+ if output_path:
418
+ with open(output_path, 'w') as f:
419
+ f.write(report)
420
+
421
+ return report
422
+ ```
423
+
424
+ ## Key References
425
+
426
+ - Pollonini L et al. (2014). Auditory cortex activation to natural speech and simulated cochlear implant speech measured with functional near-infrared spectroscopy. Hearing Research 309:84-93. (SCI metric)
427
+ - Hocke LM et al. (2018). Automated Processing of fNIRS Data—A Visual Guide to the Pitfalls and Consequences. Algorithms 11(5):67.
428
+ - Brigadoi S et al. (2014). Motion artifacts in functional near-infrared spectroscopy: A comparison of motion correction techniques applied to real cognitive data. NeuroImage 85:181-191.
429
+ - Yücel MA et al. (2021). Best practices for fNIRS publications. Neurophotonics 8(1):012101.
430
+ - Santosa H et al. (2018). The NIRS Brain AnalyzIR Toolbox. Algorithms 11(5):73.