diff --git a/moose-core/tests/python/chan_proto.py b/moose-core/tests/python/chan_proto.py
new file mode 100644
index 0000000000000000000000000000000000000000..ae37024f5de98402d8df87822af6258aaeef7b54
--- /dev/null
+++ b/moose-core/tests/python/chan_proto.py
@@ -0,0 +1,140 @@
+"""\
+Create general Channel Proto, pass in name, x and y power, and params
+
+Also, create the library of channels
+Might need a few other chan_proto types, such as
+     inf-tau channels
+     Ca dep channels
+chan_proto quires alpha and beta params for both activation and inactivation
+If no inactivation, just send in empty Yparam array.
+"""
+
+from __future__ import print_function, division
+import moose
+import numpy as np
+from util import NamedList
+
+SSTauChannelParams = NamedList('SSTauChannelParams', '''
+                                Arate
+                                A_B
+                                A_C
+                                Avhalf
+                                Avslope
+                                taumin
+                                tauVdep
+                                tauPow
+                                tauVhalf
+                                tauVslope''')
+
+AlphaBetaChannelParams = NamedList('AlphaBetaChannelParams', '''
+                                A_rate
+                                A_B
+                                A_C
+                                Avhalf
+                                A_vslope
+                                B_rate
+                                B_B
+                                B_C
+                                Bvhalf
+                                B_vslope''')
+
+ZChannelParams = NamedList('ZChannelParams', 'Kd power tau')
+
+
+ChannelSettings = NamedList('ChannelSettings', 'Xpow Ypow Zpow Erev name')
+
+def interpolate_values_in_table(tabA,V_0,l=40):
+    import param_chan
+    '''This function interpolates values in the table
+    around tabA[V_0]. '''
+    V = np.linspace(param_chan.VMIN, param_chan.VMAX, len(tabA))
+    idx =  abs(V-V_0).argmin()
+    A_min = tabA[idx-l]
+    V_min = V[idx-l]
+    A_max = tabA[idx+l]
+    V_max = V[idx+l]
+    a = (A_max-A_min)/(V_max-V_min)
+    b = A_max - a*V_max
+    tabA[idx-l:idx+l] = V[idx-l:idx+l]*a+b
+    return tabA
+
+def fix_singularities(Params,Gate):
+    import param_chan
+    
+    if Params.A_C < 0:
+
+        V_0 = Params.A_vslope*np.log(-Params.A_C)-Params.Avhalf
+
+        if V_0 > param_chan.VMIN and V_0 < param_chan.VMAX:
+            #change values in tableA and tableB, because tableB contains sum of alpha and beta
+            tabA = interpolate_values_in_table(Gate.tableA,V_0)
+            tabB = interpolate_values_in_table(Gate.tableB,V_0)
+            Gate.tableA = tabA
+            Gate.tableB = tabB
+
+    if Params.B_C < 0:
+
+        V_0 = Params.B_vslope*np.log(-Params.B_C)-Params.Bvhalf
+
+        if V_0 > param_chan.VMIN and V_0 < param_chan.VMAX:
+            #change values in tableB
+            tabB = interpolate_values_in_table(Gate.tableB,V_0)
+            Gate.tableB = tabB
+
+    return Gate
+
+#may need a CaV channel if X gate uses alpha,beta and Ygate uses inf tau
+#Or, have Y form an option - if in tau, do something like NaF
+def chan_proto(chanpath, params):
+    import param_chan
+
+    chan = moose.HHChannel(chanpath)
+    chan.Xpower = params.channel.Xpow
+    if params.channel.Xpow > 0:
+        xGate = moose.HHGate(chan.path + '/gateX')
+        xGate.setupAlpha(params.X + [param_chan.VDIVS, param_chan.VMIN, param_chan.VMAX])
+        xGate = fix_singularities(params.X, xGate)
+
+    chan.Ypower = params.channel.Ypow
+    if params.channel.Ypow > 0:
+        yGate = moose.HHGate(chan.path + '/gateY')
+        yGate.setupAlpha(params.Y + [param_chan.VDIVS, param_chan.VMIN, param_chan.VMAX])
+        yGate = fix_singularities(params.Y, yGate)
+    if params.channel.Zpow > 0:
+        chan.Zpower = params.channel.Zpow
+        zgate = moose.HHGate(chan.path + '/gateZ')
+        ca_array = np.linspace(param_chan.CAMIN, param_chan.CAMAX, param_chan.CADIVS)
+        zgate.min = param_chan.CAMIN
+        zgate.max = param_chan.CAMAX
+        caterm = (ca_array/params.Z.Kd) ** params.Z.power
+        inf_z = caterm / (1 + caterm)
+        tau_z = params.Z.tau * np.ones(len(ca_array))
+        zgate.tableA = inf_z / tau_z
+        zgate.tableB = 1 / tau_z
+        chan.useConcentration = True
+    chan.Ek = params.channel.Erev
+    return chan
+
+
+TypicalOneDalpha = NamedList('TypicalOneDalpha',
+                             '''channel X Y Z=[] calciumPermeable=False calciumPermeable2=False''')
+
+_FUNCTIONS = {
+    TypicalOneDalpha: chan_proto,
+
+}
+
+#*params... passes the set of values not as a list but as individuals
+def make_channel(chanpath, params):
+    func = _FUNCTIONS[params.__class__]
+    return func(chanpath, params)
+
+def chanlib():
+    import param_chan
+    if not moose.exists('/library'):
+        moose.Neutral('/library')
+    #Adding all the channels to the library. *list removes list elements from the list,
+    #so they can be used as function arguments
+    chan = [make_channel('/library/'+key, value) for key, value in param_chan.ChanDict.items()]
+  
+    return chan
diff --git a/moose-core/tests/python/param_chan.py b/moose-core/tests/python/param_chan.py
new file mode 100644
index 0000000000000000000000000000000000000000..0db3f697226b9e30aa0a766d5e4b41ad8255cad8
--- /dev/null
+++ b/moose-core/tests/python/param_chan.py
@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+from util import NamedDict
+from chan_proto import (
+    SSTauChannelParams,
+    AlphaBetaChannelParams,
+    ZChannelParams,
+    ChannelSettings,
+    TypicalOneDalpha,)
+
+#chanDictSP.py
+#contains all gating parameters and reversal potentials
+# Gate equations have the form:
+#
+# y(x) = (rate + B * x) / (C + exp((x + vhalf) / vslope))
+#
+# OR
+# y(x) = tau_min + tau_vdep / (1 + exp((x + vhalf) / vslope))
+#
+# where x is membrane voltage and y is the rate constant
+#KDr params used by Sriram, RE paper1, Krp params used by RE paper 2
+#Parameters for Ca channels may need to be shifted - see Dorman model
+krev=-87e-3
+narev=50e-3
+carev=140e-3 #assumes CaExt=2 mM and CaIn=50e-3
+ZpowCDI=0
+
+VMIN = -100e-3
+VMAX = 50e-3
+VDIVS = 3000 #0.5 mV steps
+CAMIN=0.01e-3   #10 nM
+CAMAX=40e-3  #40 uM, might want to go up to 100 uM with spines
+CADIVS=3000 #10 nM steps
+
+#mtau: Ogata fig 5, no qfactor accounted in mtau, 1.2 will improve spike shape
+#activation minf fits Ogata 1990 figure 3C (which is cubed root)
+#inactivation hinf fits Ogata 1990 figure 6B
+#htau fits the main -50 through -10 slope of Ogata figure 9 (log tau), but a qfact of 2 is already taken into account.
+
+
+CaTparam = ChannelSettings(Xpow=3, Ypow=1, Zpow=1, Erev=carev, name='CaT')
+qfactCaT = 1
+
+#Original inactivation ws too slow compared to activation, made closder the alpha1G
+CaT_X_params = AlphaBetaChannelParams(A_rate = 5342.4*qfactCaT,
+                                      A_B = 2100.*qfactCaT,
+                                      A_C = 11.9,
+                                      Avhalf = 1e-3,
+                                      A_vslope = -12e-3,
+                                      B_rate = 289.7*qfactCaT,
+                                      B_B = 0.*qfactCaT,
+                                      B_C = 1.,
+                                      Bvhalf = 0.0969,
+                                      B_vslope = 0.0141)
+#CaT_Y_params = CaT_X_params
+CaT_Y_params = AlphaBetaChannelParams(A_rate = 0*qfactCaT,
+                                      A_B = -74.*qfactCaT,
+                                      A_C = 1.,
+                                      Avhalf = 9e-2,
+                                      A_vslope = 5e-3,
+                                      B_rate = 15*qfactCaT,
+                                      B_B = -1.5*qfactCaT,
+                                      B_C = 1.5,
+                                      Bvhalf = 0.05,
+                                      B_vslope = -15e-3)
+
+#These CDI params can be used with every channel, make ZpowCDI=2
+#If ZpowCDI=0 the CDI will not be used, power=-4 is to transform
+#(Ca/Kd)^pow/(1+(Ca/Kd)^pow) to 1/(1+(ca/Kd)^-pow)
+CDI_Z_params = ZChannelParams(Kd = 0.12e-3,
+                              power = -4,
+                              tau = 142e-3)
+
+#Dictionary of "standard" channels, to create channels using a loop
+#NaF doesn't fit since it uses different prototype form
+#will need separate dictionary for BK
+
+ChanDict = NamedDict(
+    'ChannelParams',
+    CaT =   TypicalOneDalpha(CaTparam, CaT_X_params, CaT_Y_params, CDI_Z_params, calciumPermeable=True))
diff --git a/moose-core/tests/python/params.py b/moose-core/tests/python/params.py
new file mode 100644
index 0000000000000000000000000000000000000000..406965738033096b2fd85fb6e4250c4decd88554
--- /dev/null
+++ b/moose-core/tests/python/params.py
@@ -0,0 +1,26 @@
+t_stop = 10
+dend_diameter = 2.2627398e-6
+dend_length =  1.131369936e-6
+Cm = 4.021231698e-12
+Rm = 1865100032
+Em = -0.07100000232
+Vm_0 = -0.0705
+dt = 50e-6
+spines_no = 0
+difshell_no = 2
+difshell_name = "Ca_shell"
+Ca_basal = 50e-6
+Ca_initial = Ca_basal*200
+dca = 200.0e-12
+difbuff_no = 1
+difbuff_name = "Buff"
+btotal = 80.0e-3
+kf =  0.028e6
+kb = 19.6
+d = 66e-12
+inject = 0.1e-9
+gbar = 1
+#MMpump
+km = 0.3e-3
+kcat = 85e-22 
+pumps = 1
diff --git a/moose-core/tests/python/test_all.sh b/moose-core/tests/python/test_all.sh
index 9ec99b4e4ee2dda8faa1b4f5072ed0e3c2f99052..338a20cb746752c06064f4b6a3a4eb6d83a9f221 100755
--- a/moose-core/tests/python/test_all.sh
+++ b/moose-core/tests/python/test_all.sh
@@ -6,7 +6,8 @@ test_scripts="./test_function.py
     test_mumbl.py
     test_pymoose.py
     test_synchan.py
-    test_vec.py"
+    test_vec.py
+    test_difshells.py"
 
 for testFile in $test_scripts; do
     echo "Executing $testFile"
diff --git a/moose-core/tests/python/test_difshells.py b/moose-core/tests/python/test_difshells.py
new file mode 100644
index 0000000000000000000000000000000000000000..8e6da7c8ccb8850ba98f529d8c690b8f21cad281
--- /dev/null
+++ b/moose-core/tests/python/test_difshells.py
@@ -0,0 +1,182 @@
+import moose
+import numpy as np
+import matplotlib.pyplot as plt
+import chan_proto
+
+from params import *
+
+def linoid(x,param):
+    #plt.figure()
+    #plt.plot(x,(param[2]+np.exp((V+param[3])/param[4])))
+    den = (param[2]+np.exp((V+param[3])/param[4]))
+    nom = (param[0]+param[1]*V)
+    return nom/den
+
+def add_difshell(comp,i,shell_thickness,shell_radius):
+    new_name = comp.path.split('[')[0]+'/'+comp.name+'/'+difshell_name+str(i)
+    dif = moose.DifShell(new_name)
+
+
+    #dif.C = Ca_initial
+    dif.Ceq = Ca_basal
+    dif.D = dca
+    dif.valence = 2
+    dif.leak = 0
+    dif.shapeMode = 0
+    dif.length = comp.length
+    dif.diameter = 2*shell_radius
+    dif.thickness = shell_thickness
+   
+    return dif
+
+def add_difbuffer_to_dishell(comp,i,j,shell_thickness,shell_radius):
+    new_name = comp.path.split('[')[0]+'/'+comp.name+'/'+difshell_name+str(i)+'_'+difbuff_name+str(j)
+    buf = moose.DifBuffer(new_name)
+    buf.bTot = btotal
+    buf.shapeMode = 0
+    buf.length = comp.length
+    buf.diameter = 2*shell_radius
+    buf.thickness = shell_thickness
+    buf.kf = kf
+    buf.kb = kb
+    buf.D = d
+    return buf
+
+def add_difshells_and_buffers(comp):
+    
+    if difshell_no < 1:
+        return [], []
+    
+    difshell= []
+    shell_thickness = dend.diameter/difshell_no/2.
+    difbuffer = []
+    for i in range(difshell_no):
+        shell_radius = comp.diameter/2-i*shell_thickness
+        dif = add_difshell(comp,i,shell_thickness,shell_radius)
+        difshell.append(dif)
+       
+        if i > 0 :
+            moose.connect(difshell[i-1],"outerDifSourceOut",difshell[i],"fluxFromOut")
+            moose.connect(difshell[i],"innerDifSourceOut",difshell[i-1],"fluxFromIn")
+            
+        if difbuff_no > 0:
+            difbuffer.append([])
+            for j in range(difbuff_no):
+                buf = add_difbuffer_to_dishell(comp,i,j,shell_thickness,shell_radius)
+                difbuffer[i].append(buf)
+                moose.connect(difshell[i],"concentrationOut",buf,"concentration")
+                moose.connect(buf,"reactionOut",difshell[i],"reaction")
+                if i>0:
+                    moose.connect(difbuffer[i-1][j],"outerDifSourceOut",difbuffer[i][j],"fluxFromOut")
+                    moose.connect(difbuffer[i][j],"innerDifSourceOut",difbuffer[i-1][j],"fluxFromIn")
+    
+    return difshell,difbuffer
+
+def addOneChan(chanpath,gbar,comp):
+    
+    SA = np.pi * comp.length*comp.diameter
+    proto = moose.element('/library/'+chanpath)
+    chan = moose.copy(proto, comp, chanpath)
+    chan.Gbar = gbar * SA
+    #If we are using GHK AND it is a calcium channel, connect it to GHK
+    moose.connect(comp,'VmOut',chan,'Vm')
+    moose.connect(chan,"channelOut",comp,"handleChannel")
+    return chan
+
+
+if __name__ == '__main__':
+    
+    for tick in range(0, 7):
+        moose.setClock(tick, dt)
+    moose.setClock(8,0.005) #set output clock
+    model = moose.Neutral('/model')
+    dend = moose.Compartment('/model/dend')
+    pulse = moose.PulseGen('/model/pulse')
+    data = moose.Neutral('/data')
+    vmtab = moose.Table('/data/dend_Vm')
+    gktab = moose.Table('/data/CaT_Gk')
+    iktab = moose.Table('/data/CaT_Ik')
+
+    dend.Cm = Cm
+    dend.Rm = Rm
+    dend.Em = Em
+    dend.initVm = Vm_0
+    dend.diameter = dend_diameter
+    dend.length = dend_length
+    
+    pulse.delay[0] = 8.
+    pulse.width[0] = 500e-3
+    pulse.level[0] = inject
+    pulse.delay[1] = 1e9
+
+    m = moose.connect(pulse, 'output', dend, 'injectMsg')
+    
+    moose.connect(vmtab, 'requestOut', dend, 'getVm')
+
+    chan_proto.chanlib()
+    chan = addOneChan('CaT',gbar,dend)
+
+    
+    moose.connect(gktab, 'requestOut', chan, 'getGk')
+    moose.connect(iktab, 'requestOut', chan, 'getIk')
+    diftab = []
+    buftab = []
+    difs, difb = add_difshells_and_buffers(dend)
+    if pumps:
+        pump = moose.MMPump('/model/dend/pump')
+        pump.Vmax = kcat
+        pump.Kd = km
+        moose.connect(pump,"PumpOut",difs[0],"mmPump")
+    if difs:
+        moose.connect(chan,"IkOut",difs[0],"influx")
+        moose.connect(difs[0],'concentrationOut',chan,'concen')
+        
+    for i,dif in enumerate(difs):
+        res_dif = moose.Table('/data/'+difshell_name+str(i))
+        diftab.append(res_dif)
+        moose.connect(diftab[i],'requestOut',dif,'getC')
+        if (difbuff_no):
+            buftab.append([])
+            for j,buf in enumerate(difb[i]):
+                res_buf =  moose.Table('/data/'+difshell_name+str(i)+'_'+difbuff_name+str(j))
+                buftab[i].append(res_buf)
+                moose.connect(buftab[i][j],'requestOut',buf,'getBBound')
+    
+   
+    moose.reinit()
+    if not gbar:
+        for i,dif in enumerate(difs):
+            if i == 0:
+                dif.C = Ca_initial
+            else:
+                dif.C = 0
+            for j,dbuf in enumerate(difb[i]):
+                dbuf.bFree = dbuf.bTot
+    
+    moose.start(t_stop)
+   
+    t = np.linspace(0, t_stop, len(vmtab.vector))
+    fname = 'moose_results_difshell_no_'+str(difshell_no)+'_difbuffer_no_'+str(difbuff_no)+'_pump_'+str(pumps)+'_gbar_'+str(gbar)+'.txt'
+    print fname
+    header = 'time Vm Ik Gk'
+    number  = 4+difshell_no*(difbuff_no+1)
+    res = np.zeros((len(t),number))
+    res[:,0] = t
+    res[:,1] = vmtab.vector
+    res[:,2] = iktab.vector
+    res[:,3] = gktab.vector
+ 
+    for i in range(difshell_no):
+        header += ' difshell_'+str(i)
+        res[:,4+i*(difbuff_no+1)] =  diftab[i].vector
+        if (difbuff_no):
+            for j,buf in enumerate(buftab[i]):
+                res[:,4+i*(difbuff_no+1)+j+1] =  buf.vector
+                header += ' difshell_'+str(i)+'_difbuff_'+str(j)
+    np.savetxt(fname,res,header=header, comments='')
+
+
+
+    
+
+    # plt.show()