How to plot NetStim and biophysical cell activity

Anything that doesn't fit elsewhere.
Post Reply
refriend

How to plot NetStim and biophysical cell activity

Post by refriend »

I have created a small network of 2 NetStim and 2 simple biophysical (Default_Cell) neurons based on The Neuron book, Ch 12. The network has been incrementally tested and functions as expected.

My goal (and current dilemma) is to plot both the biophysical APs and NetStim Pulses. Eventually, I'd like to combine these plots onto one graph.

The graphing of biophysical APs was created using the gui and saved in session.ses. In order to plot the NetStims pulses I incorporated https://www.neuron.yale.edu/phpBB2/viewtopic.php?t=1037.

Prior to calling plotraster() my AP graph plots properly. Post-plotraster() the AP graph becomes 'marks'.

I have attached my init.hoc, netdefs.hoc, and session.ses code, though I believe my issues are confined to init.hoc. Specifically, I believe the line

Code: Select all

idvec.mark(g2, timevec, "|")
is causing the problem, but how do I differentiate between graphs to 'mark'?

Thank you,
Rich

init.hoc

Code: Select all

// Developed from The NEURON Book, Chapter 12. 

load_file("nrngui.hoc")						// loads the tools to access the model parameters through the GUI interface
//load_template("model_Default_Cells.hoc")			//This command is very slow under mswindows. Therefore it is often useful to explicitly load with the statement:
xopen("model_Default_Cells.hoc")	// Load neural model
xopen("netdefs.hoc") 							// cells, nclist, & netcon code
//load_file("makenet.hoc") 								// specifies network
//load_file("rig.hoc") 										// to adjust parameters and run simulation

//Network instantiation
  /* S0 */  cell_append(new S_NetStim(),	-51,	 120, 0)
	/* S1*/  cell_append(new S_NetStim(),	-51,	 120, 0)
  /* D2 */  cell_append(new Default_Cell(),	30,	 123, 0)
	/* D3 */  cell_append(new Default_Cell(),	30,	 123, 0)
  //connect cells.object($1) soma.v to cells.object($2) @ cells.object($2).synlist.object($3) w/ a weight = $4   & delay = $5
	/* S0 -> D2.E0 */  nc_append(0,   2, 0,  0.015,1) 
	/* S1 -> D2.E1 */  nc_append(1,   2, 1,  0.015,1)
	/* S1 -> D3.E0 */  nc_append(1,   3, 0,  0.015,1)
	/* S1 -> D3.E1 */  nc_append(1,   3, 1,  0.015,1)
	
	/* D2-> D3.I4 */  nc_append(2,   3, 3,  0.01,1)
//End Network instantiation
//Mark spikes in rastor plot
//  From https://www.neuron.yale.edu/phpBB2/viewtopic.php?t=1037

	objref timevec, idvec, recncs, tobj, nil
	timevec = new Vector()
	idvec = new Vector()
	recncs = new List()

	cells.object(2).soma tobj = new NetCon(&v(0.5), nil)
	tobj.record(timevec, idvec, 2) // so all the spike rasters lie above the x axis
	recncs.append(tobj)

	cells.object(3).soma tobj = new NetCon(&v(0.5), nil)
	tobj.record(timevec, idvec, 3) // so all the spike rasters lie above the x axis
	recncs.append(tobj)

	objref tobj // so we don't accidentally mess up the last NetCon
	objref g2
	proc plotraster() {
	  g2 = new Graph()
		g2.size(0,300,-6,6)
		g2.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
	  idvec.mark(g2, timevec, "|")
	}

	proc myrun() {
	  run()
	  plotraster()
	}
//End Mark spikes in rastor plot
xopen("session.ses")
tstop = 300					//Run the simulation for 300 timesteps (ms) 
secondorder=0	// This is a global variable which specifies the time integration method.
dt=1e10 //The integration interval for fadvance ().

myrun()

session.ses

Code: Select all

{load_file("nrngui.hoc")}
objectvar save_window_, rvp_
objectvar scene_vector_[5]
objectvar ocbox_, ocbox_list_, scene_, scene_list_
{ocbox_list_ = new List()  scene_list_ = new List()}
{pwman_place(0,0,0)}
{
xpanel("RunControl", 0)
v_init = -65
xvalue("Init","v_init", 1,"stdinit()", 1, 1 )
xbutton("Init & Run","run()")
xbutton("Stop","stoprun=1")
runStopAt = 5
xvalue("Continue til","runStopAt", 1,"{continuerun(runStopAt) stoprun=1}", 1, 1 )
runStopIn = 1
xvalue("Continue for","runStopIn", 1,"{continuerun(t + runStopIn) stoprun=1}", 1, 1 )
xbutton("Single Step","steprun()")
t = 1000
xvalue("t","t", 2 )
tstop = 1000
xvalue("Tstop","tstop", 1,"tstop_changed()", 0, 1 )
dt = 0.025
xvalue("dt","dt", 1,"setdt()", 0, 1 )
steps_per_ms = 40
xvalue("Points plotted/ms","steps_per_ms", 1,"setdt()", 0, 1 )
screen_update_invl = 0.05
xvalue("Scrn update invl","screen_update_invl", 1,"", 0, 1 )
realtime = 6.9
xvalue("Real Time","realtime", 0,"", 0, 1 )
xpanel(75,460)
}
{
save_window_ = new PlotShape(0)
save_window_.size(-13.75,1014.75,-437.257,591.755)
save_window_.variable("v")
scene_vector_[3] = save_window_
{save_window_.view(-13.75, -437.257, 1028.5, 1029.01, 79, 122, 200.7, 200.8)}
fast_flush_list.append(save_window_)
save_window_.save_name("fast_flush_list.")
}
{
save_window_ = new Graph(0)
save_window_.size(0,500,-80,40)
scene_vector_[4] = save_window_
{save_window_.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)}
graphList[0].append(save_window_)
save_window_.save_name("graphList[0].")
save_window_.addexpr("Default_Cell[1].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
}
objectvar scene_vector_[1]
{doNotify()}
netdefs.hoc

Code: Select all

//Network instantiation interface. The following elements were created via NetBuilder. They were commented out and left as a reminder of how to execute the commands. 	

objref cells, nclist, netcon
{cells = new List()  nclist = new List()}

func cell_append() {cells.append($o1)  $o1.position($2,$3,$4)
	return cells.count - 1
}

func nc_append() {//srcindex, tarcelindex, synindex
// netcon is created on the source and connected to destination. 
// the target maitains a list of its synapses
// a global nclist is maintained for all connections
  if ($3 >= 0) {
    netcon = cells.object($1).connect2target(cells.object($2).synlist.object($3))
    netcon.weight = $4   netcon.delay = $5
  }else{
    netcon = cells.object($1).connect2target(cells.object($2).pp)
    netcon.weight = $4   netcon.delay = $5
  }
  nclist.append(netcon)
  return nclist.count - 1
}
ted
Site Admin
Posts: 6384
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: How to plot NetStim and biophysical cell activity

Post by ted »

Sorry to reply so late, but somehow this got lost and I only now discovered it while reviewing the Forum's contents. So if you haven't already discovered the cause and cure for the problem (maybe while at the NEURON course?), let me say that I see nothing in the code you present that would cause it. If you provide model_Default_Cells.hoc, I'll be able to try to reproduce the symptom and maybe will be able to suggest a solution.
refriend

Re: How to plot NetStim and biophysical cell activity

Post by refriend »

I apologize for not posting a response earlier. For those reading this post and interested in the solution to my dilemma, the real issue ended up being an exercise in how not to plug and patch code.

I was shown my mistake at the NEURON course. (BTW, a quick plug for those reading this, the course is really well done and actually accommodated both the beginner and more experienced NEURON programmer. I give it two neurons up!) Now for the embarrassing simple truth to my problem.

I was experimenting / combining / modifying code from various sections of The NEURON Book and online tutorials. What this produced were graphs constructed from both .hoc code and a session. It turns out (and you will see this if you run the previously attached code) that the biophysical cell activity is recorded to Graph[0]. After the prescribed runtime, Graph[1], a 'marked' version of the biophysical activity, is drawn with the exact location and size parameters as Graph[0]. In other words, my original measurements were hiding in the original window, beneath the new 'marked' window all along. (Yes, embarrassing.)

But, now a new question for the experts... I am not finding the results I expected from NetCon.record. I know I am overlooking something basic. The big picture is that I only seem able to record time and id vectors for two cell objects at a time. I have verified this my executing an idvec.printf and timevec.printf. I now present the essential code (rig.hoc being the culprit).

Thank you!

mosinit.hoc

Code: Select all

// Developed from The NEURON Book, Chapter 12. 
load_file("nrngui.hoc")								// loads the the GUI interface
load_file("model_Default_Cells.hoc")	// Load neural model
load_file("netdefs.hoc") 							// cells, nclist, & netcon code
load_file("makenet.hoc") 							// specifies network
load_file("rig.hoc") 									// to adjust parameters and run simulation
load_file("session.ses")

tstop = 300		//Run the simulation for 300 timesteps (ms) 
secondorder=0	
dt=1e10 
makepanel() // Called from rig.hoc to monitor output.
run()
makenet.hoc

Code: Select all

//Network instantiation
  /*0 S0 */  cell_append(new S_NetStim(),	-51,	 120, 0)
	/*1 S1*/  cell_append(new S_NetStim(),	-51,	 120, 0)
  /*2 D2 */  cell_append(new Default_Cell(),	30,	 123, 0)
	/*3 D3 */  cell_append(new Default_Cell(),	30,	 123, 0)
	/*4 S4*/  cell_append(new S_NetStim(),	-51,	 120, 0)
	/*5 D5 */  cell_append(new Default_Cell(),	30,	 123, 0)
  //connect cells.object($1) soma.v to cells.object($2) @ cells.object($2).synlist.object($3) w/ a weight = $4   & delay = $5
	/* S0 -> D2.E0 */  nc_append(0,   2, 0,  0.015,1) 
	/* S1 -> D2.E1 */  nc_append(1,   2, 1,  0.015,1)
	/* S1 -> D3.E0 */  nc_append(1,   3, 0,  0.015,1)
	/* S1 -> D3.E1 */  nc_append(1,   3, 1,  0.015,1)
	
	/* D2-> D3.I4 */  nc_append(2,   3, 3,  0.01,1)
	/* S4 -> D5.E0 */  nc_append(0,   2, 0,  0.015,1) 
//End Network instantiation
*** rig.hoc ***

Code: Select all

// Developed from The NEURON Book
////////// user interface //////////
//load_file("runctl.ses") // RunControl and VariableTimeStep
// prepare to record and display spike trains
objref netcon, vec, spikes, nil, graster

//  From https://www.neuron.yale.edu/phpBB2/viewtopic.php?t=1037 
objref timevec // vector of events for one measured NETCON
objref idvec		// basically a vector of timevecs per NetCon[id]
objref recncs		// 
objref tobj, nil	// temp object and null object (used for null NETCON destination... recording terminal)

timevec = new Vector()
idvec = new Vector()
//recncs = new List()
// http://www.neuron.yale.edu/neuron/static/docs/help/neuron/neuron/classes/netcon.html#record

//* Biophysical Cells
cells.object(2).soma tobj = new NetCon(&v(0.5), nil) 
tobj.record(timevec, idvec, 2) // so all the spike rasters lie above the x axis
//recncs.append(tobj)
cells.object(3).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 3) // so all the spike rasters lie above the x axis
//recncs.append(tobj)
cells.object(5).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 5) // so all the spike rasters lie above the x axis
//recncs.append(tobj)

//* Artificial Cells
//cells.object(0) tobj = new NetCon(&v(0.5), nil)	
//tobj.record(timevec, idvec,0) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)
//cells.object(1) tobj = new NetCon(&v(0.5), nil)	
//tobj.record(timevec, idvec,1) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)

objref tobj // so we don't accidentally mess up the last NetCon

objref g1, g2
proc plotraster() {
	idvec.mark(g1, timevec, "|")
}

objref winMain
winMain = new VBox(2)	// 0: inset (gray), 1: outset (gray), 2: bright inset (light gray), 3: none (sea green)
proc makepanel() {
	winMain.intercept(1) // start winMain def
		xpanel("Model",1) // start xpanel Model
			xbutton("Quit", "quit()")
		xpanel()				// end xpanel Model

		g1 = new Graph()
		g1.size(0,500,0,6)
		
		g2 = new Graph()
		g2.addexpr("Default_Cell[1].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
	
		//g2.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
		//plotraster()
		

		xpanel("RunControl", 0)	// start xpanel RunControl
			v_init = -65
			xvalue("Init","v_init", 1,"stdinit()", 1, 1 )
			xbutton("Init & Run","run()")
			xbutton("Stop","stoprun=1")
			runStopAt = 5
			xvalue("Continue til","runStopAt", 1,"{continuerun(runStopAt) stoprun=1}", 1, 1 )
			runStopIn = 1
			xvalue("Continue for","runStopIn", 1,"{continuerun(t + runStopIn) stoprun=1}", 1, 1 )
			xbutton("Single Step","steprun()")
			t = 1000
			xvalue("t","t", 2 )

			xvalue("Tstop","tstop", 1,"tstop_changed()", 0, 1 )
			dt = 0.025
			xvalue("dt","dt", 1,"setdt()", 0, 1 )
			steps_per_ms = 40
			xvalue("Points plotted/ms","steps_per_ms", 1,"setdt()", 0, 1 )
			screen_update_invl = 0.05
			xvalue("Scrn update invl","screen_update_invl", 1,"", 0, 1 )
			realtime = 6.9
			xvalue("Real Time","realtime", 0,"", 0, 1 )
			
		xpanel()	// end xpanel RunControl
		
	winMain.intercept(0) // end winMain def	
	winMain.map("Run Control",0,0,-1,-1) // Draws VBox.map("label", left, top, width, height). width, height of -1,-1 uses  natural VBox size. 
	
}

proc recreate() {
	createnet($1)
	settau(tau)
	interval(low, high)
	weight(w)
	delay(del)
	preprasterplot()
}

proc run() {
	stdinit()
	continuerun(tstop)
	plotraster()
	//showraster() // show results at the end of each simulation
}
session.ses

Code: Select all

{load_file("nrngui.hoc")}
objectvar save_window_, rvp_
objectvar scene_vector_[5]
objectvar ocbox_, ocbox_list_, scene_, scene_list_
{ocbox_list_ = new List()  scene_list_ = new List()}
{pwman_place(0,0,0)}

{
save_window_ = new Graph(0)
save_window_.size(0,500,-80,40)
save_window_.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
graphList[0].append(save_window_)
save_window_.save_name("graphList[0].")
save_window_.addexpr("Default_Cell[0].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
save_window_.addexpr("Default_Cell[1].soma.v( 0.5 )", 4, 1, 0.8, 0.9, 2)

}
objectvar scene_vector_[1]
{doNotify()}
model_Default_Cells.hoc

Code: Select all

// Simple neuron model. All models are implementations of this model.
//Base methods are initially defined here and may be later extended in specific models.

begintemplate Default_Cell
	public is_art
	public init, topol, basic_shape, subsets, geom, biophys, geom_nseg, biophys_inhomo
	public synlist, x, y, z, position, connect2target

	public soma, axon, dendrite	
	public all, dendrites, axons

	objref synlist

	proc init() {
	  topol()
	  subsets()
	  geom()
	  biophys()
	  geom_nseg()
	  synlist = new List()
	  synapses()
	  x = y = z = 0 // only change via position
	}

	create soma, axon, dendrite[3]

	proc topol() { local i
	  for i = 0, 2 connect dendrite[i](0), soma(0)
	  connect axon(0), soma(1)
	  basic_shape()
	}
	proc basic_shape() {
	  soma {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(15, 0, 0, 1)}
	  dendrite {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(-74, 30, 0, 1)}
	  dendrite[1] {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(-89, 0, 0, 1)}
	  dendrite[2] {pt3dclear() pt3dadd(0, 0, 0, 1) pt3dadd(-74, -29, 0, 1)}
	  axon {pt3dclear() pt3dadd(15, 0, 0, 1) pt3dadd(55, 0, 0, 1)}
	}

	objref all, dendrites, axons
	proc subsets() { local i
	  objref all, dendrites, axons
	  all = new SectionList()
	    soma all.append()
	    axon all.append()
	    dendrite all.append()

	  dendrites = new SectionList()
			for i=0, 2 dendrite[i] dendrites.append()

	  axons = new SectionList()
	    axon axons.append()

	}
	proc geom() {
	  forsec all {  }
	  soma {  L = 30  diam = 30  }
	  axon {  L = 1000  diam = 1  }
	}
	external lambda_f
	proc geom_nseg() {
	  forsec all { nseg = int((L/(0.1*lambda_f(100))+.9)/2)*2 + 1  }
	}
	
	proc biophys() {
	  forsec all {
	    Ra = 160
	    cm = 1
	  }
	  soma {
	    insert hh
	      gnabar_hh = 0.12
	      gkbar_hh = 0.036
	      gl_hh = 0.0003
	      el_hh = -54.3
	  }
	  axon {
	    insert hh
	      gnabar_hh = 0.12
	      gkbar_hh = 0.036
	      gl_hh = 0.0003
	      el_hh = -54.3
	  }
	}
	proc biophys_inhomo(){}
	proc position() { local i
	  soma for i = 0, n3d()-1 { //n3d() returns the # of 3d locations stored in the accessed section.
	    pt3dchange(i, $1-x+x3d(i), $2-y+y3d(i), $3-z+z3d(i), diam3d(i))
	  }
	  x = $1  y = $2  z = $3
	}
	obfunc connect2target() { localobj nc //$o1 target point process, optional $o2 returned NetCon
	  soma nc = new NetCon(&v(1), $o1)
	  nc.threshold = 10
	  if (numarg() == 2) { $o2 = nc } // for backward compatibility
	  return nc
	}
	objref syn_
	proc synapses() {	
	  /* E0 */   for i=0, 2 dendrite[i] { 
			syn_ = new ExpSyn(0.2)
			synlist.append(syn_)
	    syn_.tau = 3
			}
	  /* Inhibitory */   soma {
			syn_ = new Exp2Syn(1)  
			synlist.append(syn_)
	    syn_.tau1 = 3
	    syn_.e = -67
			}
	}
	func is_art() { return 0 }

endtemplate Default_Cell

begintemplate S_NetStim
	public pp, connect2target, x, y, z, position, is_art
	objref pp
	proc init() {
	  pp = new NetStim()
	    pp.interval = 50
	    pp.number = 10000
	    pp.start = 5
	}
	func is_art() { return 1 }
	obfunc connect2target() { localobj nc
	  nc = new NetCon(pp, $o1)
	  if (numarg() == 2) { $o2 = nc }
	  return nc
	}
	proc position(){x=$1  y=$2  z=$3}
endtemplate S_NetStim

begintemplate C_IntFire1
	public pp, connect2target, x, y, z, position, is_art
	objref pp
	proc init() {
	  pp = new IntFire1()
	}
	func is_art() { return 1 }
	obfunc connect2target() { localobj nc
	  nc = new NetCon(pp, $o1)
	  if (numarg() == 2) { $o2 = nc }
	  return nc
	}
	proc position(){x=$1  y=$2  z=$3}
endtemplate C_IntFire1
Last edited by refriend on Thu Jul 31, 2008 5:23 pm, edited 2 times in total.
ted
Site Admin
Posts: 6384
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: How to plot NetStim and biophysical cell activity

Post by ted »

Thanks for the plug for the NEURON summer course!

Does your latest post reuse the netdefs.hoc that was included with the previous one?
refriend

Re: How to plot NetStim and biophysical cell activity

Post by refriend »

Yes. netdefs is reused. But I just noticed that I missed making Default_Cell(2) fire... so obviously that interfered with my debugging.

So, I added Default_Cell(2) to the graphs and enabled its proper firing. Please replace the previous files with the applicable files attached below.

Please observe that the three biological cells record just fine now. But note how their marks disappear once rig.hoc, lines 33-35 are uncommented to record from the artificial cells.

makenet.hoc

Code: Select all

//Network instantiation
  /*0 S0 */  cell_append(new S_NetStim(),	-51,	 120, 0)
	/*1 S1*/  cell_append(new S_NetStim(),	-51,	 120, 0)
  /*2 D2 */  cell_append(new Default_Cell(),	30,	 123, 0)
	/*3 D3 */  cell_append(new Default_Cell(),	30,	 123, 0)
	/*4 S4*/  cell_append(new S_NetStim(),	-51,	 120, 0)
	/*5 D5 */  cell_append(new Default_Cell(),	30,	 123, 0)
  //connect cells.object($1) soma.v to cells.object($2) @ cells.object($2).synlist.object($3) w/ a weight = $4   & delay = $5
	/* S0 -> D2.E0 */  nc_append(0,   2, 0,  0.015,1) 
	/* S1 -> D2.E1 */  nc_append(1,   2, 1,  0.015,1)
	/* S1 -> D3.E0 */  nc_append(1,   3, 0,  0.015,1)
	/* S1 -> D3.E1 */  nc_append(1,   3, 1,  0.015,1)
	
	/* D2-> D3.I4 */  nc_append(2,   3, 3,  0.01,1)
	/* S4 -> D5.E0 */  nc_append(4,   5, 0,  0.015,1) 
//End Network instantiation
rig.hoc

Code: Select all

// Developed from The NEURON Book
////////// user interface //////////
//load_file("runctl.ses") // RunControl and VariableTimeStep
// prepare to record and display spike trains
objref netcon, vec, spikes, nil, graster

//  From https://www.neuron.yale.edu/phpBB2/viewtopic.php?t=1037 
objref timevec // vector of events for one measured NETCON
objref idvec		// basically a vector of timevecs per NetCon[id]
objref recncs		// 
objref tobj, nil	// temp object and null object (used for null NETCON destination... recording terminal)

timevec = new Vector()
idvec = new Vector()
recncs = new List()
// http://www.neuron.yale.edu/neuron/static/docs/help/neuron/neuron/classes/netcon.html#record

//* Biophysical Cells
cells.object(2).soma tobj = new NetCon(&v(0.5), nil) 
tobj.record(timevec, idvec, 2) // so all the spike rasters lie above the x axis
recncs.append(tobj)
cells.object(3).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 3) // so all the spike rasters lie above the x axis
recncs.append(tobj)
cells.object(5).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 5) // so all the spike rasters lie above the x axis
recncs.append(tobj)

//* Artificial Cells
//cells.object(0) tobj = new NetCon(&v(0.5), nil)	
//tobj.record(timevec, idvec, 0) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)
//recncs.append(tobj)
cells.object(1) tobj = new NetCon(&v(0.5), nil)	
tobj.record(timevec, idvec, 1) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)
recncs.append(tobj)

objref tobj // so we don't accidentally mess up the last NetCon

objref g1, g2
proc plotraster() {
	idvec.mark(g1, timevec, "|")
}

objref winMain
winMain = new VBox(2)	// 0: inset (gray), 1: outset (gray), 2: bright inset (light gray), 3: none (sea green)
proc makepanel() {
	winMain.intercept(1) // start winMain def
		xpanel("Model",1) // start xpanel Model
			xbutton("Quit", "quit()")
		xpanel()				// end xpanel Model

		g1 = new Graph()
		g1.size(0,500,-3,5)
		
		g2 = new Graph()
		g2.addexpr("Default_Cell[1].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
	
		//g2.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
		//plotraster()
		

		xpanel("RunControl", 0)	// start xpanel RunControl
			v_init = -65
			xvalue("Init","v_init", 1,"stdinit()", 1, 1 )
			xbutton("Init & Run","run()")
			xbutton("Stop","stoprun=1")
			runStopAt = 5
			xvalue("Continue til","runStopAt", 1,"{continuerun(runStopAt) stoprun=1}", 1, 1 )
			runStopIn = 1
			xvalue("Continue for","runStopIn", 1,"{continuerun(t + runStopIn) stoprun=1}", 1, 1 )
			xbutton("Single Step","steprun()")
			t = 1000
			xvalue("t","t", 2 )

			xvalue("Tstop","tstop", 1,"tstop_changed()", 0, 1 )
			dt = 0.025
			xvalue("dt","dt", 1,"setdt()", 0, 1 )
			steps_per_ms = 40
			xvalue("Points plotted/ms","steps_per_ms", 1,"setdt()", 0, 1 )
			screen_update_invl = 0.05
			xvalue("Scrn update invl","screen_update_invl", 1,"", 0, 1 )
			realtime = 6.9
			xvalue("Real Time","realtime", 0,"", 0, 1 )
			
		xpanel()	// end xpanel RunControl
		
	winMain.intercept(0) // end winMain def	
	winMain.map("Run Control",0,0,-1,-1) // Draws VBox.map("label", left, top, width, height). width, height of -1,-1 uses  natural VBox size. 
	
}

proc recreate() {
	createnet($1)
	settau(tau)
	interval(low, high)
	weight(w)
	delay(del)
	preprasterplot()
}

proc run() {
	stdinit()
	continuerun(tstop)
	plotraster()
	//showraster() // show results at the end of each simulation
}

session.hoc

Code: Select all

{load_file("nrngui.hoc")}
objectvar save_window_, rvp_
objectvar scene_vector_[5]
objectvar ocbox_, ocbox_list_, scene_, scene_list_
{ocbox_list_ = new List()  scene_list_ = new List()}
{pwman_place(0,0,0)}

{
save_window_ = new Graph(0)
save_window_.size(0,500,-80,40)
save_window_.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
graphList[0].append(save_window_)
save_window_.save_name("graphList[0].")
save_window_.addexpr("Default_Cell[0].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
save_window_.addexpr("Default_Cell[1].soma.v( 0.5 )", 4, 1, 0.8, 0.9, 2)
save_window_.addexpr("Default_Cell[2].soma.v( 0.5 )", 5, 1, 0.8, 0.9, 2)

}
objectvar scene_vector_[1]
{doNotify()}
ted
Site Admin
Posts: 6384
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: How to plot NetStim and biophysical cell activity

Post by ted »

I only seem able to record time and id vectors for two cell objects at a time
Did you try with your revised code? I let the program execute for just 10 ms of model time, after which idvec contained the numbers 1 3 5. Of course I first had to execute
g1 = new Graph()
to avoid the error message
object type is nil instead of Graph
. . .
Vector[4].mark(NULLobject, Vector[3], "|")
(another minor bug for you to track down, but bug hunting is part of the fun).
refriend

Re: How to plot NetStim and biophysical cell activity

Post by refriend »

Sorry, but I am not getting your error.

Also, yes, 2 3 5 show up as desired. But when the artificial cells are activated (uncomment rig.hoc, lines 30-35), I only get marks for 1 3 5 (0 & 2 are missing).
ted
Site Admin
Posts: 6384
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: How to plot NetStim and biophysical cell activity

Post by ted »

refriend wrote:Sorry, but I am not getting your error.
Indeed, that was my error. I commented out too much stuff. Most user-defined run control code either interferes with debugging or is itself part of the problem, so I typically comment it out. I got sloppy this time, and one of the lines that was commented out was the one that calls makepanel().
Also, yes, 2 3 5 show up as desired. But when the artificial cells are activated (uncomment rig.hoc, lines 30-35), I only get marks for 1 3 5 (0 & 2 are missing).
You may think you're recording from the artificial spiking cells, but you're not. cells.object(1) is a NetStim, not a biophysical model cell, so
cells.object(1) tobj = new NetCon(&v(0.5), nil)
watches for spikes in the middle of the default section, which psection() reveals to be Default_Cell[0].soma. Consequently, tobj.record(timevec, idvec, 1) will make a 1 be appended to idvec every time a spike is detected in that section.

Now, Default_Cell[0] happens to be cells.o(2), so I would have expected that, every time t at which a spike is detected at Default_Cell[0].soma(0.5), both a 1 and a 2 would be appended to idvec, and the current value of t would be appended twice to timevec. I don't understand why that doesn't happen, but it didn't happen. Perhaps it's related to the fact that, no matter how many NetCons have a particular location as their "spike source", there is only one spike detector watching the monitored variable at that location.

But it's a good thing that both a 1 and a 2 weren't appended to idvec etc., because "failure to obtain an expected result" made you question your code instead of assuming that all was OK.

"So I'll just change that line to tobj = new NetCon(cells.o(1), nil)" you say.

Nope. Won't work. You'll just get an error message something like this:

Code: Select all

 if arg 1 is an object it must be a point process or NULLObject
 near line 7
 tobj = new NetCon(cells.o(1), nil)
                                   ^
        NetCon(..., NULLobject)
(guess how I know).

"Why?"

That's what I asked myself, until I looked back at the template that defines the S_NetStim class. cells.o(1) is an instance of the S_NetStim class, and instances of that object class are not NetStims themselves but instead are compound objects that _contain_ a public member pp that is the NetStim. The thing that generates spikes is not cells.o(1) but cells.o(1).pp, and the NetStim that monitors it for spikes must be created like so:
tobj = new NetCon(cells.o(1).pp, nil)
Do that, and you'll see that its spikes are indeed recorded.
refriend

Re: How to plot NetStim and biophysical cell activity

Post by refriend »

Perfect!

I was staring at the &v(0.5), and it looked so wrong. The fact that I (thought) I was getting info from the artificial point processes made me doubt myself.

Excellent. Thank you!

On a side note, I am working now on plotting marks in real-time. I assume this is possible by reevaluating the idvec and timevec Vectors on each iteration of the 'continuerun' loop. Am I on the right track or heading down a dead end? (Note: The final goal is to have Artificial & Biological APs marked on the the standard line graph for Biological APs.)

And on a 2nd BTW... For anyone reading... the 'working' rig.hoc (no longer needs session.ses to be loaded in mosinit.hoc).

Code: Select all

// Developed from The NEURON Book
////////// user interface //////////
//load_file("runctl.ses") // RunControl and VariableTimeStep
// prepare to record and display spike trains
objref netcon, vec, spikes, nil, graster
objref g1, g2, g3	// graphs and plots

//  From https://www.neuron.yale.edu/phpBB2/viewtopic.php?t=1037 
objref timevec 		// vector of events for one measured NETCON
objref idvec			// basically a vector of timevecs per NetCon[id]
objref recncs			// 
objref tobj, nil	// temp object and null object (used for null NETCON destination... recording terminal)
objref timevec2 	// vector of events for one measured NETCON
objref idvec2			// basically a vector of timevecs per NetCon[id]
objref recncs2		// 

timevec = new Vector()
idvec = new Vector()
recncs = new List()
timevec2 = new Vector()
idvec2 = new Vector()
recncs2 = new List()

// http://www.neuron.yale.edu/neuron/static/docs/help/neuron/neuron/classes/netcon.html#record
//* Biophysical Cells
cells.object(2).soma tobj = new NetCon(&v(0.5), nil) 
tobj.record(timevec, idvec, 2) // so all the spike rasters lie above the x axis
recncs.append(tobj)
cells.object(3).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 3) // so all the spike rasters lie above the x axis
recncs.append(tobj)
cells.object(5).soma tobj = new NetCon(&v(0.5), nil)
tobj.record(timevec, idvec, 5) // so all the spike rasters lie above the x axis
recncs.append(tobj)

//* Artificial Cells
tobj = new NetCon(cells.o(0).pp, nil)	
tobj.record(timevec2, idvec2, 0) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)
recncs.append(tobj)
tobj = new NetCon(cells.o(1).pp, nil)	
tobj.record(timevec2, idvec2, 1) // so all the spike rasters lie above the x axis (or) tobj.record(timevec, idvec, 1)
recncs.append(tobj)

objref tobj // so we don't accidentally mess up the last NetCon

proc plotraster() {
	idvec.mark(g1, timevec, "|")
	idvec2.mark(g2, timevec2, "|")
}

objref winMain, winMarks
winMain = new VBox(2)	// 0: inset (gray), 1: outset (gray), 2: bright inset (light gray), 3: none (sea green)
winMarks = new HBox(2)

proc makepanel() {
	winMain.intercept(1) // start winMain def
		xpanel("Model",1) // start xpanel Model
			xbutton("Quit", "quit()")
		xpanel()				// end xpanel Model

		winMarks.intercept(1) // start winMarks def
			g1 = new Graph()
			g1.size(0,tstop,-3,5)
			g1.label(0.4, 0.9, "Biological AP Events", 2, 1, 0, 0, 1)
		
			g2 = new Graph()
			g2.size(0,tstop,-3,5)
			g2.label(0.4, 0.9, "Artificial AP Events", 2, 1, 0, 0, 1)
		
		winMarks.intercept(0) // end winMarks def
		winMarks.map("Biological / Artificial AP Events",0,0,-1,-1)
		
		g3 = new Graph() // With a 0 argument the window is not mapped but can be sized and placed with the view function. 
		g3.size(0,tstop,-80,40)
		//g3.view(0, -80, 500, 120, 362, 25, 487.3, 289.9)
		g3.addexpr("Default_Cell[0].soma.v( 0.5 )", 3, 1, 0.8, 0.9, 2)
		g3.addexpr("Default_Cell[1].soma.v( 0.5 )", 4, 1, 0.8, 0.9, 2)
		g3.addexpr("Default_Cell[2].soma.v( 0.5 )", 5, 1, 0.8, 0.9, 2)
		graphList[0].append(g3) // Note: graphList[0] is for all objects that are to be updated at integer multiples of dt. graphList[1] is for graphs whose y values are to be plotted vs. t - 0.5*dt, and graphList[2] is for graphs whose y values are to be plotted vs. t + 0.5*dt. The reason for these strange time offsets is that, if you are using NEURON's "staggered Crank-Nicholson method" (secondorder == 2), ionic currents and states will be second order correct at t - 0.5*dt and t + 0.5*dt, respectively (membrane potential will be second order correct at t). If you are using the adaptive integrators (cvode), all variables are computed at the same t, and plots generated with graphList[1] and graphList[2] are identical to plots of the same variables that are generated with graphList[0]. 
		
		xpanel("RunControl", 0)	// start xpanel RunControl
			v_init = -65
			xvalue("Init","v_init", 1,"stdinit()", 1, 1 )
			xbutton("Init & Run","run()")
			xbutton("Stop","stoprun=1")
			runStopAt = 5
			xvalue("Continue til","runStopAt", 1,"{continuerun(runStopAt) stoprun=1}", 1, 1 )
			runStopIn = 1
			xvalue("Continue for","runStopIn", 1,"{continuerun(t + runStopIn) stoprun=1}", 1, 1 )
			xbutton("Single Step","steprun()")
			t = 1000
			xvalue("t","t", 2 )

			xvalue("Tstop","tstop", 1,"tstop_changed()", 0, 1 )
			dt = 0.025
			xvalue("dt","dt", 1,"setdt()", 0, 1 )
			steps_per_ms = 40
			xvalue("Points plotted/ms","steps_per_ms", 1,"setdt()", 0, 1 )
			screen_update_invl = 0.05
			xvalue("Scrn update invl","screen_update_invl", 1,"", 0, 1 )
			realtime = 6.9
			xvalue("Real Time","realtime", 0,"", 0, 1 )		
		xpanel()	// end xpanel RunControl
		
	winMain.intercept(0) // end winMain def	
	winMain.map("Run Control",0,0,-1,-1) // Draws VBox.map("label", left, top, width, height). width, height of -1,-1 uses  natural VBox size. 
}

proc recreate() {
	createnet($1)
	settau(tau)
	interval(low, high)
	weight(w)
	delay(del)
	preprasterplot()
}

proc run() {
	stdinit()
	continuerun(tstop)
	plotraster()
}

ted
Site Admin
Posts: 6384
Joined: Wed May 18, 2005 4:50 pm
Location: Yale University School of Medicine
Contact:

Re: How to plot NetStim and biophysical cell activity

Post by ted »

I am working now on plotting marks in real-time. I assume this is possible by reevaluating the idvec and timevec Vectors on each iteration of the 'continuerun' loop.
Not really. Your best bet would be to try to reuse the Network Builder's SpikePlot (see /nrn/lib/hoc/netbild/spkplot.hoc), perhaps with some modification so it can be used as a "standalone" tool (i.e. without having to be launched from a Network Builder). For an earlier version of SpikePlot reused in this manner, see http://www.neuron.yale.edu/course/net3/sync/. spkplot.hoc defines the SpikePlot1 class (note the "1" which is used to avoid collisions in name space); init.hoc illustrates usage.
refriend

Re: How to plot NetStim and biophysical cell activity

Post by refriend »

Thanks for your help! I'll give it a look.
Post Reply