1
- #init
1
+ """
2
+ .. _ex-momi2023-part2:
3
+
4
+ ========================================================
5
+ Replicating Momi et al. (2023): TMS-evoked Responses
6
+ ========================================================
7
+
8
+ This script replicates the findings of the paper :footcite:`MomiEtAl2023`:
9
+
10
+ Momi, D., Wang, Z., Griffiths, J.D. (2023).
11
+ "TMS-evoked responses are driven by recurrent large-scale network dynamics."
12
+ # eLife, [doi: 10.7554/eLife.83232](https://elifesciences.org/articles/83232)
13
+
14
+ This code loads up a previously-fit whobpyt model, varies a specific model parameter (the inhibitory time constant; b), and simulates TEPs to visualize what effect this model parameter has on the output.
15
+
16
+
17
+ """
18
+
19
+ # sphinx_gallery_thumbnail_number = 1
20
+ #
21
+ # %%
22
+ # Setup
23
+ # --------------------------------------------------
24
+ # Importage:
25
+
26
+ # os stuff
27
+ import os
28
+ import sys
29
+ sys .path .append ('..' )
30
+
31
+
32
+ # whobpyt stuff
33
+ import whobpyt
34
+ from whobpyt .datatypes import Parameter as par , Timeseries
35
+ from whobpyt .models .jansen_rit import JansenRitModel ,JansenRitParams
36
+ from whobpyt .run import ModelFitting
37
+ from whobpyt .optimization .custom_cost_JR import CostsJR
38
+
39
+ # python stuff
40
+ import numpy as np
41
+ import pandas as pd
42
+ import scipy .io
43
+ import gdown
44
+ import pickle
45
+ import warnings
46
+ warnings .filterwarnings ('ignore' )
47
+
48
+ #neuroimaging packages
49
+ import mne
50
+
51
+ # viz stuff
52
+ import matplotlib .pyplot as plt
53
+
54
+ # %%
55
+ # Download and load necessary data for the example
56
+ download_data = True
57
+ url = 'https://drive.google.com/drive/folders/1dpyyfJl9wjTrWVo5lqOmB8HRhD3irjNj?usp=drive_link'
58
+ if download_data : gdown .download_folder (url , quiet = True )
59
+ data_dir = os .path .abspath ('eg__replicate_Momi2023_data' )
60
+
61
+ # # %%
62
+ # # load in a previously completed model fitting results object
63
+ # full_run_fname = os.path.join(data_dir, 'Subject_1_low_voltage_fittingresults_stim_exp.pkl')
64
+ # F = pickle.load(open(full_run_fname, 'rb'))
65
+ # F.evaluate(u = u, empRec = data_mean, TPperWindow = batch_size, base_window_num = 20)
66
+
67
+ # define relevant variables for whobpyt fititng/simuations
68
+
69
+ # %%
70
+ # Load EEG data from a file
71
+ file_name = os .path .join (data_dir , 'Subject_1_low_voltage.fif' )
72
+ epoched = mne .read_epochs (file_name , verbose = False );
73
+ evoked = epoched .average ()
74
+
75
+
76
+ # %%
77
+ # define options for JR model
78
+ eeg_data = evoked .data .copy ()
79
+ time_start = np .where (evoked .times == - 0.1 )[0 ][0 ]
80
+ time_end = np .where (evoked .times == 0.3 )[0 ][0 ]
81
+ eeg_data = eeg_data [:,time_start :time_end ]/ np .abs (eeg_data ).max ()* 4
82
+ node_size = F .model .node_size
83
+ output_size = eeg_data .shape [0 ]
84
+ batch_size = 20
85
+ step_size = 0.0001
86
+ num_epochs = 20 #2 # num_epochs = 20
87
+ tr = 0.001
88
+ state_size = 6
89
+ base_batch_num = 20
90
+ time_dim = 400
91
+ state_size = 6
92
+ base_batch_num = 20
93
+ hidden_size = int (tr / step_size )
94
+
95
+
96
+ # %%
97
+ # prepare data structure of the model
98
+ data_mean = Timeseries (eeg_data , num_epochs , batch_size )
99
+
100
+ # stimulation info
101
+ u = np .zeros ((node_size ,hidden_size ,time_dim ))
102
+ u [:,:,80 :120 ]= 1000
103
+
104
+
105
+ # %%
106
+ # Visualizng the original fit
107
+ ts_args = dict (xlim = [- 0.1 ,0.3 ])
108
+ ch , peak_locs1 = evoked .get_peak (ch_type = 'eeg' , tmin = - 0.05 , tmax = 0.01 )
109
+ ch , peak_locs2 = evoked .get_peak (ch_type = 'eeg' , tmin = 0.01 , tmax = 0.02 )
110
+ ch , peak_locs3 = evoked .get_peak (ch_type = 'eeg' , tmin = 0.03 , tmax = 0.05 )
111
+ ch , peak_locs4 = evoked .get_peak (ch_type = 'eeg' , tmin = 0.07 , tmax = 0.15 )
112
+ ch , peak_locs5 = evoked .get_peak (ch_type = 'eeg' , tmin = 0.15 , tmax = 0.20 )
113
+ times = [peak_locs1 , peak_locs2 , peak_locs3 , peak_locs4 , peak_locs5 ]
114
+
115
+ simulated_EEG_st = evoked .copy ()
116
+ simulated_EEG_st .data [:,time_start :time_end ] = F .lastRec ['eeg' ].npTS ()
117
+ times = [peak_locs1 , peak_locs2 , peak_locs3 , peak_locs4 , peak_locs5 ]
118
+ simulated_joint_st = simulated_EEG_st .plot_joint (ts_args = ts_args , times = times )
119
+
120
+ # %%
121
+ # now we want to vary paramters and simulate again.
122
+
123
+ # looking at original value of b
124
+ print (F .model .params .b .val )
125
+
126
+ # defining a range of b to vary and simulate
127
+ b_range = np .linspace (45 , 55 , 4 )
128
+
129
+
130
+ # %%
131
+ # Defining a range for the b paramter to explore
132
+ b_range = np .linspace (45 , 55 , 5 )
133
+ # testing all ranges:
134
+ sims_dict = {}
135
+ for n , new_b in enumerate (b_range ):
136
+ # changing parameter in model
137
+ F .model .params .b = par (new_b , new_b , 1 , True )
138
+
139
+ # evaluate the model
140
+ F .evaluate (u = u , empRec = data_mean , TPperWindow = batch_size , base_window_num = 20 )
141
+
142
+ # plotting and saving new simulations
143
+ simulated_EEG_st .data [:,time_start :time_end ] = F .lastRec ['eeg' ].npTS ()
144
+ simulated_joint_st = simulated_EEG_st .plot_joint (ts_args = ts_args , times = times , title = f'b param = { new_b } ' )
145
+ sims_dict [str (new_b )] = simulated_EEG_st .copy ().crop (tmin = 0 , tmax = 0.2 )
146
+
147
+ # %%
148
+ # comparing conditions
149
+ fig , ax = plt .subplots (figsize = (12 ,4 ))
150
+ mne .viz .plot_compare_evokeds (sims_dict , picks = 'eeg' , combine = 'gfp' , axes = ax , cmap = 'viridis' ,);
151
+ fig .show ()
152
+
153
+ # %%
154
+ # Results Description
155
+ # ---------------------------------------------------
156
+ #
157
+ #
158
+ # Here we replicate the results of Momi et al. 2023 (Fig. 5D). As the inhibitory synaptic time constant b increases,
159
+ # we observe an increase in the amplitude of the first, early, and local TEP components; and a decrease of the second,
160
+ # late, and global TEP components.
0 commit comments