//genesis - LFPfuncs.g /* Functions for calculating local field potentials, EEG, and ECoG potentials. Uses an efield2 object and can be used with hsolve. Will be included in the main script if calc_LFP = 1. The global string variable 'solvepath' is defined in the main script to give the name that is being used for the hsolve element, e.g. "solver". Output clock will be clock 1 (out_dt) function make_electrode(name, x, y, z, cellpath) sums over all pyr cells, is most often used to sum over all pyrmidal cells. */ /* When recording field potentials from many cells, it may be useful to record only synaptic currents rather than include transmembrane currents generated by action potential, leak, and capacitive currents. The global variable 'use_syn_currents' is used to allow this option. set in main script: int use_syn_currents = 1 // calculate the efield using only synchan currents Typical usage: make_electrode "Electrode_1" 0.0 0.0 0.001 {cellpath} // Lower Left: cell [0] make_electrode "Electrode_2" 0.00096 0.00064 0.001 {cellpath} // over pyr_4[792] To include all currents, including capacitive currents, one can use make_electrode without hsolve and use_syn_currents = 0. This will use the axial currents Im, which are equal to the total membrane and capacitive Cm*(dCvm/dt) currents. The hsolve does not include the capacitive currents in the calculation of Im. Alternatively, use hsolve and the function make_electrode_cells. This creates an efield_cells object that correctly calculates Im and the resulting field. It also places the Im value in the disabled object that was taken over by the solver, where it is accessible for use by efield or efield2 as if it were not hsolved. */ // This function uses efield2 to correctly set the distance to hsolved elements // It is to be executed by output_node function make_electrode(name, x, y, z) // sums over all cells in path str name // electrode name float x, y, z // electrode position if (calc_LFP == 0) return end if (!{exists /electrodes}) create neutral /electrodes end pushe /electrodes if ({exists {name}}) delete {name} end float scale // scale factor for currents if (use_syn_currents) scale = -0.32 // invert sign of trans-membrane currents else // Use Im to give axial currents scale = 0.32 // positive - axial currents are positive-in end create efield2 {name} setfield {name} x {x} y {y} z {z} setfield {name} scale {scale} pope useclock /electrodes/{name} 1 // clock at out_dt // In order to output the results, use function do_electrodes_out end // function make_electrode function make_electrode_messages(name, cellpath) // executed by worker nodes str name // electrode name str cellpath // path to cells producing the field float x, y, z // electrode position x = {getfield@{output_node} /electrodes/{name} x} y = {getfield@{output_node} /electrodes/{name} y} z = {getfield@{output_node} /electrodes/{name} z} float cx, cy, cz // channel position float distance str compt, chan, src int i for (i = 0; i < Ex_cells_per_slice; i = i + 1) src = {cellpath} @ "[" @ {i} @ "]" if({hflag} && {hsolve_chanmode > 1}) foreach compt ({el {src}/#[OBJECT=compartment]}) if (use_syn_currents) foreach chan ({el {compt}/#[OBJECT=synchan]}) cx = {getfield {chan} x} cy = {getfield {chan} y} cz= {getfield {chan} z} distance = {sqrt { {pow {{cx} - {x}} 2.0} + \ {pow {{cy} - {y}} 2.0} + \ {pow {{cz} - {z}} 2.0} }} if(debug_level > 1) echo {getfield {compt} name} {getfield {chan} name} \ "distance = " {distance} end raddmsg {src}/{solvepath} /electrodes/{name}@{output_node} \ CURRENT {findsolvefield {src}/{{solvepath}} {chan} Ik} \ {distance} end // foreach else // Use Im to give axial currents /* Assume that efield_cells has updated hsolved compt Im */ raddmsg {compt} /electrodes/{name}@{output_node} CURRENT Im 0.0 end end // loop over compts else // not hsolve - Ileak is not calculated foreach compt ({el {src}/#[OBJECT=compartment]}) if(use_syn_currents) foreach chan ({el {compt}/#[OBJECT=synchan]}) raddmsg {src}/{synpath} /electrodes/{name}@{output_node} Ik 0.0 end // foreach chan else raddmsg {compt} /electrodes/{name}@{output_node} CURRENT Im 0.0 end end // loop over compts end // if({hflag} && {hsolve_chanmode > 1}) end // loop over cells end /* A variation that calculates the Efield for only a specified synpath e.g. "apical3/AMPA_pyr", or {Ex_ex_synpath} */ function make_electrode_synpath(name, x, y, z) str name // electrode name str synpath // path to compartment/synchan float x, y, z // electrode position str cellpath // path to cells str chan // full path to the particular synchan float cx, cy, cz // channel position float distance if (calc_LFP == 0) return end if (!{exists /electrodes}) create neutral /electrodes end pushe /electrodes if ({exists {name}}) delete {name} end create efield2 {name} setfield {name} x {x} y {y} z {z} setfield {name} scale -0.32 // membrane currents should be 'negative-in' pope useclock /electrodes/{name} 1 // clock at out_dt call /electrodes/{name} RECALC // calculate the distances to the compartments // In order to output the results, use function do_electrodes_out end // function make_electrode_synpath function make_electrode_synpath_messages(name, cellpath, synpath) str name // electrode name str synpath // path to compartment/synchan float x, y, z // electrode position str cellpath // path to cells str chan // full path to the particular synchan x = {getfield@{output_node} /electrodes/{name} x} y = {getfield@{output_node} /electrodes/{name} y} z = {getfield@{output_node} /electrodes/{name} z} float cx, cy, cz // channel position float distance str src int i for (i = 0; i < {Ex_cells_per_slice}; i = i + 1) src = {cellpath} @ "[" @ {i} @ "]" if({hflag} && {hsolve_chanmode > 1}) // need to provide the distance to the electrode chan = {src} @ "/" @ {synpath} cx = {getfield {chan} x} cy = {getfield {chan} y} cz= {getfield {chan} z} distance = {sqrt { {pow {{cx} - {x}} 2.0} + \ {pow {{cy} - {y}} 2.0} + \ {pow {{cz} - {z}} 2.0} }} raddmsg {src}/{solvepath} /electrodes/{name}@{output_node} CURRENT \ {findsolvefield {src}/{solvepath} {synpath} Ik} {distance} else // not hsolve raddmsg {src}/{synpath} /electrodes/{name}@{output_node} CURRENT Ik 0.0 end // if({hflag} && {hsolve_chanmode > 1}) end // loop over cells end function make_electrode_cells(name, cellpath, x, y, z) str name // electrode name str cellpath // here cellpath is {cellpath}[] str worker_name // name used for worker electrodes /* Example: make_electrode_cells "Electrode_cells_Im" {cellpath}[] \ {(Ex_NX-1)*Ex_SEP_X/2.0} {39.5*Ex_SEP_Y} 0.001 // use efield_cells */ float x, y, z // electrode position if (calc_LFP == 0) return end if (i_am_worker_node) if (!{exists /electrodes}) create neutral /electrodes end worker_name = {name} @ "_" @ {mynode} pushe /electrodes if ({exists {worker_name}}) delete {worker_name} end create efield_cells {worker_name} setfield {worker_name} x {x} y {y} z {z} setfield {worker_name} cellpath {cellpath} setfield {worker_name} solvepath {solvepath} // global variable setfield {worker_name} scale 0.32 setfield {worker_name} debug_level 0 pope useclock /electrodes/{worker_name} 1 // clock at out_dt end // if (i_am_worker_node) if (i_am_output_node) if (!{exists /electrodes}) create neutral /electrodes end create calculator /electrodes/{name} useclock /electrodes/{name} 1 // clock at out_dt end end // function make_electrode_cells function make_electrode_cells_messages(name) str name, worker_name if (i_am_worker_node) worker_name = {name} @ "_" @ {mynode} raddmsg /electrodes/{worker_name} /electrodes/{name}@{output_node} SUM field end end function do_electrodes_out str name, path foreach path ({el /electrodes/#[OBJECT=efield],/electrodes/#[OBJECT=efield2]}) /* create an asc_file to output the LFP to a file {name} @ "_" @ {RUNID} @ ".txt". Here, the asc_file element will be /{name} and the electrode will be /electrodes/{name} */ name = {getpath {path} -tail} make_output {name} addmsg /electrodes/{name} {name} SAVE field end end function do_electrodes_cells_out str name, path foreach path ({el /electrodes/#[OBJECT=calculator]}) name = {getpath {path} -tail} make_output {name} addmsg /electrodes/{name} {name} SAVE output end end /********** graphics functions *********/ extern makegraphscale function make_LFPplot str graph_form = "/electrode_graphs" str name, path, title_str float x, y, z floatformat %0.4g // limit precision of displayed x, y, z create xform {graph_form} [280,0,400,800] pushe {graph_form} foreach path ({el /electrodes/#[OBJECT=efield_cells],/electrodes/#[OBJECT=efield],/electrodes/#[OBJECT=efield2]}) name = {getpath {path} -tail} x = {getfield {path} x}; y = {getfield {path} y}; z = {getfield {path} z} title_str = {name} @ " at " @ {x} @ " " @ {y} @ " " @ {z} // make the graph create xgraph {name} -hgeom 33% -title {title_str} setfield {name} XUnits sec YUnits V setfield {name} xmax {tmax} ymin -0.00030 ymax 0.000005 end // making electrode graphs floatformat %0.10g // restore default precision if (calc_EPSCsum) create xgraph EPSCsum -hgeom 25% -title "Summed Ex_ex Currents" setfield EPSCsum XUnits sec YUnits Amp setfield EPSCsum xmax {tmax} ymin 0 ymax 3e-6 end pope // e.g. makegraphscale {graph_form}/Electrode_3 foreach path ({el /electrodes/#[OBJECT=efield_cells],/electrodes/#[OBJECT=efield],/electrodes/#[OBJECT=efield2]}) name = {getpath {path} -tail} makegraphscale {graph_form}/{name} end if (calc_EPSCsum) makegraphscale {graph_form}/EPSCsum end useclock {graph_form} 2 xshow {graph_form} end extern colors function make_LFPplot_messages str name, path, col_name int col_num = 0 str graph_form = "/electrode_graphs" foreach path ({el /electrodes/#[OBJECT=efield_cells],/electrodes/#[OBJECT=efield],/electrodes/#[OBJECT=efield2]}) name = {getpath {path} -tail} col_name = {colors {col_num}} addmsg /electrodes/{name} {graph_form}/{name} \ PLOT field *{name} *{col_name} col_num = col_num + 1 end // loop over electrodes if (calc_EPSCsum) addmsg {data_source} {graph_form}/EPSCsum \ PLOT output *EPSC_sum *magenta end end