import touchsim as ts # import touchsim package from touchsim.plotting import plot # import in-built plotting function import numpy as np import holoviews as hv # import holoviews package for plots and set some parameters hv.notebook_extension() %output holomap='scrubber' import warnings warnings.simplefilter("ignore")
touchsim includes a model of the hand surface. Its coordinate system is centered on the distal pad of the index finger. The first axis extends along the index finger towards the base and palm, while the second axis extends orthogonally towards the middle finger. Other spatial layouts can be used via the
%%output size=150 plot(coord=10)
a1 = ts.Afferent('SA1',surface=ts.hand_surface) # generate SA1 afferent located at the origin plot(region='D2') * plot(a1,size=10)
Afferent objects can be placed anywhere on the skin surface.
# generate PC afferent on distal pad of middle finger a2 = ts.Afferent('PC',surface=ts.hand_surface,location=ts.hand_surface.centers[ts.hand_surface.tag2idx('D3d')]) plot() * plot(a2,size=10)
Afferent objects combine into an
a = a1 + a2 print(a)
touchsim includes several
affpop_* functions that generate commonly used
AfferentPopulation objects. For example
affpop_grid places afferents on a grid.
affpop_hand places afferents on the hand model, in realistic densities. It can be limited to a specific hand region, afferent class, and the overall density can be adjusted.
a_d2 = ts.affpop_hand(region='D2') # limit to digit 2 a_RA = ts.affpop_hand(affclass='RA') # limit to RA afferents a = ts.affpop_hand(density_multiplier=0.2) # decrease density plot() * plot(a_d2) + plot() * plot(a_RA) + plot() * plot(a)
Tactile stimuli are represented in
Stimulus objects. These consist of individual pins. Each pin is assigned a
location on the skin surface and its movements orthogonal to the skin surface is described as a time-varying
loc = np.zeros((1,2)) trace = 0.1 * np.sin(np.linspace(0.,2.*np.pi*10,5000)) s = ts.Stimulus(location = loc, trace = trace, fs=5000) plot(s)
A number of commonly used stimuli are implemented as
stim_* functions. These include
stim_rampfor ramp-hand-hold indentations
stim_sinefor sinusoidal vibrations
stim_noisefor bandpass white noise stimuli
stim_impulsefor brief "taps" of the skin
s_ramp = ts.stim_ramp(amp=0.1) s_sine = ts.stim_sine(amp=0.05,freq=50) s_noise = ts.stim_noise() s_impulse = ts.stim_impulse(pad_len = 0.4) plot(s_ramp) + plot(s_sine) + plot(s_noise) + plot(s_impulse)
Complex stimuli can be generated by combining an object shape, that is a specific spatial pin layout, with a movement trace that is applied to all pins simultaneously. The example below creates a large rounded probe, which is then indented into the skin using a ramp-and-hold pattern. The
stim_indent_shape method is used to combine the spatial pin layout, here created using a
shape_* function, with a movement trace, created using a
s = ts.stim_indent_shape(ts.shape_circle(hdiff=0.5,pins_per_mm=2,radius=3),ts.stim_ramp(len=0.1,pad_len=0.01)) plot(region='D2d') * plot(s,spatial=True,bin=10)
response method of
AfferentPopulation objects calculates the spiking response to any
r = a.response(s) # calculate response of a to s. # Plot response as raster plot and spatially on finger plot(r) + plot() * plot(r,spatial=True,scaling_factor=0.1)
Responses can be plotted as animations.
plot() * plot(r,spatial=True,bin=5)
Objects can also print information about themselves.