<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Olfaction Model Demo
This notebook illustrates how to run a Neurokernel-based model of part of the fruit fly's antennal lobe.
Background
The early olfactory system in Drosophila consists of two antennal lobes,
one on each side of the fly brain. Each of these LPUs contain 49 glomeruli that
differ in functionality, size, shape, and relative position.  Each glomerulus
receives axons from about 50 olfactory receptor neurons (ORNs) on each of the
fly's two antennae that express the same odorant receptor. The axons of each ORN
connect to the dendrites of 3 to 5 projection neurons (PNs) in the glomeruli.
In addition to the PNs - which transmit olfactory information to the higher
regions of the brain - the antennal lobes contain local neurons (LNs) whose
connections are restricted to the lobes; inter-glomerular connectivity therefore
subsumes synaptic connections between ORNs and PNs, ORNs and LNs, LNs and PNs, and feedback
from PNs to LNs. The entire early olfactory system in Drosophila
contains approximately 4000 neurons.
The current model of the each antennal lobe comprises 49 glomerular channels
with full intraglomerular connectivity in both hemispheres of the fly brain. The
entire model comprises 2800 neurons, or 70% of the fly's entire antennal
lobe. All neurons in the system are modeled using the Leaky Integrate-and-Fire
(LIF) model and all synaptic currents elicited by spikes are modeled using alpha functions.
Parameters for 24 of the glomerular channels are based upon currently available
ORN type data (Hallem et al., 2006); all other channels are configured with
artificial parameters.
A script that generates a GEXF file containing the antennal lobe model configuration is included in the examples/olfaction/data subdirectory of the Neurokernel source code. 
Executing the Model
Assuming that the Neurokernel source has been cloned to ~/neurokernel, we first generate an input signal of duration 1.0 seconds and construct the LPU configuration
Step1:  Next, we identify the indices of the olfactory sensory neurons (OSNs) and projection neurons (PNs) associated with a specific glomerulus; in this case, we focus on glomerulus DA1
Step2:  We now execute the model
Step3:  Next, we display the input odorant concentration profile and the spikes produced by the 25 OSNs and 3 PNs associated with glomerulus DA1 in the model
<ASSISTANT_TASK:>
Python Code:
%cd -q ~/neurokernel/examples/olfaction/data
%run gen_olf_input.py
%run create_olf_gexf.py
Explanation: Olfaction Model Demo
This notebook illustrates how to run a Neurokernel-based model of part of the fruit fly's antennal lobe.
Background
The early olfactory system in Drosophila consists of two antennal lobes,
one on each side of the fly brain. Each of these LPUs contain 49 glomeruli that
differ in functionality, size, shape, and relative position.  Each glomerulus
receives axons from about 50 olfactory receptor neurons (ORNs) on each of the
fly's two antennae that express the same odorant receptor. The axons of each ORN
connect to the dendrites of 3 to 5 projection neurons (PNs) in the glomeruli.
In addition to the PNs - which transmit olfactory information to the higher
regions of the brain - the antennal lobes contain local neurons (LNs) whose
connections are restricted to the lobes; inter-glomerular connectivity therefore
subsumes synaptic connections between ORNs and PNs, ORNs and LNs, LNs and PNs, and feedback
from PNs to LNs. The entire early olfactory system in Drosophila
contains approximately 4000 neurons.
The current model of the each antennal lobe comprises 49 glomerular channels
with full intraglomerular connectivity in both hemispheres of the fly brain. The
entire model comprises 2800 neurons, or 70% of the fly's entire antennal
lobe. All neurons in the system are modeled using the Leaky Integrate-and-Fire
(LIF) model and all synaptic currents elicited by spikes are modeled using alpha functions.
Parameters for 24 of the glomerular channels are based upon currently available
ORN type data (Hallem et al., 2006); all other channels are configured with
artificial parameters.
A script that generates a GEXF file containing the antennal lobe model configuration is included in the examples/olfaction/data subdirectory of the Neurokernel source code. 
Executing the Model
Assuming that the Neurokernel source has been cloned to ~/neurokernel, we first generate an input signal of duration 1.0 seconds and construct the LPU configuration:
End of explanation
import re
import networkx as nx
import neurokernel.tools.graph
g = nx.read_gexf('antennallobe.gexf.gz')
df_node, df_edge = neurokernel.tools.graph.graph_to_df(g)
glom_name = 'DA1'
osn_ind = sorted(list(set([ind[0] for ind in \
                           df_edge[df_edge.name.str.contains('.*-%s_.*' % glom_name)].index])))
pn_ind = sorted(list(set([ind[1] for ind in \
                          df_edge[df_edge.name.str.contains('.*-%s_.*' % glom_name)].index])))
# Get OSN and PN label indices:
osn_ind_labels = [int(re.search('osn_.*_(\d+)', name).group(1)) \
                  for name in df_node.ix[osn_ind].name]
pn_ind_labels = [int(re.search('.*_pn_(\d+)', name).group(1)) \
                 for name in df_node.ix[pn_ind].name]
Explanation: Next, we identify the indices of the olfactory sensory neurons (OSNs) and projection neurons (PNs) associated with a specific glomerulus; in this case, we focus on glomerulus DA1:
End of explanation
%cd -q ~/neurokernel/examples/olfaction
%run olfaction_demo.py
Explanation: We now execute the model:
End of explanation
%matplotlib inline
import h5py
import matplotlib as mpl
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import numpy as np
fmt = lambda x, pos: '%2.2f' % (float(x)/1e4)
with h5py.File('./data/olfactory_input.h5', 'r') as fi, \
    h5py.File('olfactory_output_spike.h5','r') as fo:
    data_i = fi['array'].value
    data_o = fo['array'].value 
mpl.rcParams['figure.dpi'] = 120 
mpl.rcParams['figure.figsize'] = (12,9)
raster = lambda data: plt.eventplot([np.nonzero(data[i, :])[0] for i in xrange(data.shape[0])],
                                    colors = [(0, 0, 0)],
                                    lineoffsets = np.arange(data.shape[0]),
                                    linelengths = np.ones(data.shape[0])/2.0)
f = plt.figure()
plt.subplot(311)
ax = plt.gca()
ax.xaxis.set_major_formatter(ticker.FuncFormatter(fmt))
plt.plot(data_i[:10000, 0]); 
ax.set_ylim(np.min(data_i)-1, np.max(data_i)+1)
ax.set_xlim(0, 10000)
plt.title('Input Stimulus'); plt.ylabel('Concentration') 
plt.subplot(312)
raster(data_o.T[osn_ind, :])
plt.title('Spikes Generated by OSNs'); plt.ylabel('OSN #');
ax = plt.gca()
ax.set_ylim(np.min(osn_ind_labels), np.max(osn_ind_labels))
ax.xaxis.set_major_formatter(ticker.FuncFormatter(fmt))
ax.yaxis.set_major_locator(ticker.MultipleLocator(base=5.0))
plt.subplot(313)
raster(data_o.T[pn_ind, :])
plt.title('Spikes Generated by PNs'); plt.ylabel('PN #');
ax = plt.gca()
ax.set_ylim(np.min(pn_ind_labels)-0.5, np.max(pn_ind_labels)+0.5)
ax.xaxis.set_major_formatter(ticker.FuncFormatter(fmt))
ax.yaxis.set_major_locator(ticker.MultipleLocator(base=1.0))
plt.xlabel('time (s)')
plt.subplots_adjust()
f.savefig('olfactory_output.png')
Explanation: Next, we display the input odorant concentration profile and the spikes produced by the 25 OSNs and 3 PNs associated with glomerulus DA1 in the model:
End of explanation
<END_TASK>