-
Notifications
You must be signed in to change notification settings - Fork 2
/
arm.py
499 lines (440 loc) · 27.2 KB
/
arm.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
"""
MSARM
Code to connect a virtual arm to the M1 model
Multipe arm options depending on self.type:
- 'randomInput': the object provides random values matching the format (used for test/debugging)
- 'dummyArm': simple kinematic arm implemented in python
- 'musculoskeletal': realistic musculoskeletal arm implemented in C++ and interfaced via pipes
Adapted from arm.hoc in arm2dms
Version: 2015jan28 by salvadordura@gmail.com
"""
from neuron import h
import arminterface
from numpy import array, zeros, pi, ones, cos, sin, mean
from pylab import concatenate, figure, show, ion, ioff, pause,xlabel, ylabel, plot, Circle, sqrt, arctan, arctan2, close
from copy import copy
from random import uniform, seed, sample, randint
[SH,EL] = [X,Y] = [0,1]
[SH_EXT, SH_FLEX, EL_EXT, EL_FLEX] = [0,1,2,3]
class Arm:
#%% init
def __init__(self, type, anim, graphs): # initialize variables
self.type = type # 'randomOutput', 'dummyArm', 'musculoskeletal'
self.anim = anim # whether to show arm animation or not
self.graphs = graphs # whether to show graphs at the end
################################
### SUPPORT METHODS
################################
# convert cartesian position to joint angles
def pos2angles(self, armPos, armLen):
x = armPos[0]
y = armPos[1]
l1 = armLen[0]
l2 = armLen[1]
elang = abs(2*arctan(sqrt(((l1 + l2)**2 - (x**2 + y**2))/((x**2 + y**2) - (l1 - l2)**2))));
phi = arctan2(y,x);
psi = arctan2(l2 * sin(elang), l1 + (l2 * cos(elang)));
shang = phi - psi;
return [shang,elang]
# convert joint angles to cartesian position
def angles2pos(self, armAng, armLen):
elbowPosx = armLen[0] * cos(armAng[0]) # end of elbow
elbowPosy = armLen[0] * sin(armAng[0])
wristPosx = elbowPosx + armLen[1] * cos(+armAng[0]+armAng[1]) # wrist=arm position
wristPosy = elbowPosy + armLen[1] * sin(+armAng[0]+armAng[1])
return [wristPosx,wristPosy]
#%% setTargetByID
def setTargetByID(self, id, startAng, targetDist, armLen):
startPos = self.angles2pos(startAng, armLen)
if id == 0:
targetPos = [startPos[0]+0.15, startPos[1]+0]
elif id == 1:
targetPos = [startPos[0]-0.15, startPos[1]+0]
elif id == 2:
targetPos = [startPos[0]+0, startPos[1]+0.15]
elif id == 3:
targetPos = [startPos[0]+0, startPos[1]-0.15]
return targetPos
#%% setupDummyArm
def setupDummyArm(self):
if self.anim:
ion()
self.fig = figure() # create figure
l = 1.1*sum(self.armLen)
self.ax = self.fig.add_subplot(111, autoscale_on=False, xlim=(-l/2, +l), ylim=(-l/2, +l)) # create subplot
self.ax.grid()
self.line, = self.ax.plot([], [], 'o-', lw=2)
self.circle = Circle((0,0),0.04, color='g', fill=False)
self.ax.add_artist(self.circle)
#%% runDummyArm: update position and velocity based on motor commands; and plot
def runDummyArm(self, dataReceived):
friction = 0.5 # friction coefficient
shang = (self.ang[SH] + self.angVel[SH] * self.interval/1000) #% update shoulder angle
elang = (self.ang[EL] + self.angVel[EL] * self.interval/1000) #% update elbow angle
if shang<self.minPval: shang = self.minPval # limits
if elang<self.minPval: elang = self.minPval # limits
if shang>self.maxPval: shang = self.maxPval # limits
if elang>self.maxPval: elang = self.maxPval # limits
elpos = [self.armLen[SH] * cos(shang), self.armLen[SH] * sin(shang)] # calculate shoulder x-y pos
handpos = [elpos[X] + self.armLen[EL] * cos(shang+elang), elpos[Y] + self.armLen[EL] * sin(shang+elang)]
shvel = self.angVel[SH] + (dataReceived[1]-dataReceived[0]) - (friction * self.angVel[SH])# update velocities based on incoming commands (accelerations) and friction
elvel = self.angVel[EL] + (dataReceived[3]-dataReceived[2]) - (friction * self.angVel[EL])
if self.anim:
self.circle.center = self.targetPos
self.line.set_data([0, elpos[0], handpos[0]], [0, elpos[1], handpos[1]]) # update line in figure
self.ax.set_title('Time = %.1f ms, shoulder: pos=%.2f rad, vel=%.2f, acc=%.2f ; elbow: pos = %.2f rad, vel = %.2f, acc=%.2f' % (float(self.duration), shang, shvel, dataReceived[0] - (friction * shvel), elang, elvel, dataReceived[1] - (friction * elvel) ), fontsize=10)
show(block=False)
pause(0.0001) # pause so that the figure refreshes at every time step
return [shang, elang, shvel, elvel, handpos[0], handpos[1]]
#%% Reset arm variables so doesn't move between trials
def resetArm(self, s, t):
self.trial = self.trial + 1
s.timeoflastreset = t
if self.type == 'dummyArm':
self.ang = list(self.startAng) # keeps track of shoulder and elbow angles
self.angVel = [0,0] # keeps track of joint angular velocities
self.motorCmd = [0,0,0,0] # motor commands to muscles
self.error = 0 # error signal (eg. difference between )
self.critic = 0 # critic signal (1=reward; -1=punishment)
self.initArmMovement = self.initArmMovement + s.testTime
def setPMdInput(self, s):
for c in range(0, s.popnumbers[s.PMd], 2):
try:
gid = s.popGidStart[s.PMd] + c # find gid of PMd
lid = s.gidDic[gid] # find local index corresponding to gid
if (gid in s.targetPMdInputs[s.targetid]): # if gid in PMdinputs for this target
#print "yes:",gid
s.cells[lid].interval=1000/s.maxPMdRate # set low interval (in ms as a function of rate)
else: # if angle not in range -> low firing rate
s.cells[lid].interval=1000/s.minPMdRate # set high interval (in ms as a function of rate)
#print "no:",gid
except:
pass # local index corresponding to gid not found in this node
#%% plot motor commands
def RLcritic(self, t):
if t > self.initArmMovement: # do not calculate critic signal in between trials
# Calculate critic signal and activate RL (check synapses between nsloc->cells)
RLsteps = int(self.RLinterval/self.interval)
if len(self.errorAll) >= RLsteps:
diff = self.error - mean(self.errorAll[-RLsteps:-1]) # difference between error at t and at t-(RLdt/dt) eg. t-50/5 = t-10steps
else:
diff = 0
if diff < -self.minRLerror: # if error negative: LTP
self.critic = 1 # return critic signal to model.py so can update synaptic weights
elif diff > self.minRLerror: # if error positive: LTD
self.critic = -1
else: # if difference not significant: no weight change
self.critic = 0
else: # if
self.critic = 0
return self.critic
#%% plot joint angles
def plotTraj(self, filename):
fig = figure()
l = 1.1*sum(self.armLen)
ax = fig.add_subplot(111, autoscale_on=False, xlim=(-l/2, +l), ylim=(-l/2, +l)) # create subplot
posX, posY = list(zip(*[self.angles2pos([x[SH],x[EL]], self.armLen) for x in self.angAll]))
ax.plot(posX, posY, 'r')
targ = Circle((self.targetPos),0.04, color='g', fill=False) # target
ax.add_artist(targ)
ax.grid()
ax.set_title('X-Y Hand trajectory')
xlabel('x')
ylabel('y')
print('saving '+filename)
fig.savefig(filename)
#%% plot joint angles
def plotAngs(self):
fig = figure()
ax = fig.add_subplot(111) # create subplot
sh = [x[SH] for x in self.angAll]
el = [x[EL] for x in self.angAll]
ax.plot(sh, 'r', label='shoulder')
ax.plot(el, 'b', label='elbow')
shTarg = self.pos2angles(self.targetPos, self.armLen)[0]
elTarg = self.pos2angles(self.targetPos, self.armLen)[1]
ax.plot(list(range(0,len(sh))), [shTarg] * len(sh), 'r:', label='sh target')
ax.plot(list(range(0,len(el))), [elTarg] * len(el), 'b:', label='el target')
ax.set_title('Joint angles')
xlabel('time')
ylabel('angle')
ax.legend()
#%% plot motor commands
def plotMotorCmds(self):
fig = figure()
ax = fig.add_subplot(111) # create subplot
shext = [x[SH_EXT] for x in self.motorCmdAll]
elext = [x[EL_EXT] for x in self.motorCmdAll]
shflex = [x[SH_FLEX] for x in self.motorCmdAll]
elflex = [x[EL_FLEX] for x in self.motorCmdAll]
ax.plot(shext, 'r', label='sh ext')
ax.plot(shflex, 'r:', label='sh flex')
ax.plot(elext, 'b', label='el ext')
ax.plot(elflex, 'b:', label='el flex')
ax.set_title('Motor commands')
xlabel('time')
ylabel('motor command')
ax.legend()
#%% plot RL critic signal and error
def plotRL(self):
fig = figure()
ax = fig.add_subplot(111) # create subplot
ax.plot(self.errorAll, 'r', label='error')
ax.plot((array(self.criticAll)+1.0) * max(self.errorAll) / 2.0, 'b', label='RL critic')
ax.set_title('RL critic and error')
xlabel('time')
ylabel('Error (m) / RL signal')
ax.legend()
################################
### SETUP
################################
def setup(self, s):#, nduration, loopstep, RLinterval, pc, scale, popnumbers, p):
self.duration = s.duration#/1000.0 # duration in msec
self.interval = s.loopstep#/1000.0 # interval between arm updates in ,sec
self.RLinterval = s.RLinterval # interval between RL updates in msec
self.minRLerror = s.minRLerror # minimum error change for RL (m)
self.armLen = s.armLen # elbow - shoulder from MSM;radioulnar - elbow from MSM;
self.handPos = [0,0] # keeps track of hand (end-effector) x,y position
self.handPosAll = [] # list with all handPos
self.handVel = [0,0] # keeps track of hand (end-effector) x,y velocity
self.handVelAll = [] # list with all handVel
self.startAng = s.startAng # starting shoulder and elbow angles (rad) = natural rest position
self.ang = list(self.startAng) # keeps track of shoulder and elbow angles
self.angAll = [] # list with all ang
self.angVel = [0,0] # keeps track of joint angular velocities
self.angVelAll = [] # list with all angVel
self.motorCmd = [0,0,0,0] # motor commands to muscles
self.motorCmdAll = [] # list with all motorCmd
self.targetDist = s.targetDist # target distance from center (15 cm)
#self.targetid = 0 # target id (eg. 0=right, 1=left, 2=top, 3=bottom)
self.targetidAll = [] # list with all targetid
self.targetPos = self.setTargetByID(s.targetid, self.startAng, self.targetDist, self.armLen) # set the target location based on target id
self.error = 0 # error signal (eg. difference between )
self.errorAll = [] # list with all error
self.critic = 0 # critic signal (1=reward; -1=punishment)
self.criticAll = [] # list with all critic
self.randDur = 0 # initialize explor movs duration
self.initArmMovement = int(s.initArmMovement) # start arm movement after x msec
self.trial = 0 # trial number
# motor command encoding
self.vec = h.Vector()
self.cmdmaxrate = s.cmdmaxrate # maximum spikes for motor command (normalizing value)
self.cmdtimewin = s.cmdtimewin # spike time window for shoulder motor command (ms)
# proprioceptive encoding
self.pStart = s.pStart # proprioceptive encoding first cell
self.numPcells = s.numPcells # number of proprioceptive cells to encode shoulder and elbow angles
self.prange = zeros((self.numPcells,2)) # range of values encoded by each P cell (proprioceptive tuning curve)
self.minPval = s.minPval # min angle to encode
self.maxPval = s.maxPval # max angle to encode
self.minPrate = s.minPrate # firing rate when angle not within range
self.maxPrate = s.maxPrate # firing rate when angle within range
angInterval = (self.maxPval - self.minPval) / (self.numPcells - 2) * 2 # angle interval (times 2 because shoulder+elbow)
currentPval = self.minPval
for c in range(0,self.numPcells,2):
self.prange[c,0] = currentPval # shoulder lower range
self.prange[c,1] = currentPval + angInterval # shoulder higher range
self.prange[c+1,0] = currentPval # elbow lower range
self.prange[c+1,1] = currentPval + angInterval # elbow higher range
currentPval += angInterval
# initialize dummy or musculoskeletal arm
if s.rank == 0:
if self.type == 'dummyArm':
self.setupDummyArm() # setup dummyArm (eg. graph animation)
elif self.type == 'musculoskeletal':
damping = 1 # damping of muscles (.osim parameter)
shExtGain = 2 # gain factor to multiply force of shoulder extensor muscles (.osim parameter)
shFlexGain = 1 # gain factor to multiply force of shoulder flexor muscles (.osim parameter)
elExtGain = 1 # gain factor to multiply force of elbow extensor muscles (.osim parameter)
elFlexGain = 0.8 # gain factor to multiply force of elbox flexor muscles (.osim parameter)
# call function to initialize virtual arm params and run virtual arm C++ executable
arminterface.setup(self.duration/1000.0, self.interval, self.startAng[SH], self.startAng[EL], self.targetPos[X], self.targetPos[Y], damping, shExtGain, shFlexGain, elExtGain, elFlexGain)
# set PMd inputs
if s.PMdinput == 'targetSplit':
self.setPMdInput(s) # set PMd inputs
################################
### RUN
################################
def run(self, t, s): #pc, cells, gidVec, gidDic, cellsperhost=[], hostspikevecs=[]):
# Append to list the the value of relevant variables for this time step (only worker0)
if s.rank == 0:
self.handPosAll.append(list(self.handPos)) # list with all handPos
self.handVelAll.append(list(self.handVel)) # list with all handVel
self.angAll.append(list(self.ang)) # list with all ang
self.angVelAll.append(list(self.angVel)) # list with all angVel
self.motorCmdAll.append(list(self.motorCmd)) # list with all motorCmd
self.targetidAll.append(self.targetid) # list with all targetid
self.errorAll.append(self.error) # error signal (eg. difference between )
self.criticAll.append(self.critic) # critic signal (1=reward; -1=punishment)
############################
# dummyArm or musculoskeletal: gather spikes for motor command
############################
if self.type == 'dummyArm' or self.type == 'musculoskeletal':
## Exploratory movements
if s.explorMovs and t-s.timeoflastexplor >= self.randDur: # if time to update exploratory movement
seed(s.id32('%d'%(int(t)+s.randseed))) # init seed
self.randMus = int(uniform(0,s.nMuscles)) # select random muscle group
self.randMul = uniform(s.explorMovsFactor/5,s.explorMovsFactor) # select random multiplier
self.randDur = uniform(s.explorMovsDur/5, s.explorMovsDur) # select random duration
s.timeoflastexplor = t
if s.explorMovs == 1: # add random noise to EDSC+IDSC population
IDSCgids = array(s.motorCmdCellRange[self.randMus]) - int(s.popGidStart[s.EDSC]) + int(s.popGidStart[s.IDSC])
IDSCgidsInverse = [j for j in range(s.popGidStart[s.IDSC],s.popGidEnd[s.IDSC]+1) if j not in list(IDSCgids)]
for (i,x) in enumerate(s.backgroundsources): # for all background input netstims
if s.backgroundgid[i] in s.motorCmdCellRange[self.randMus] or s.backgroundgid[i] in list(IDSCgids): # if connected to chosen muscle cells
#print s.backgroundgid[i]
x.interval = (self.randMul*s.backgroundrateExplor)**-1*1e3 # increase firing
elif s.backgroundgid[i] in [y for z in range(s.nMuscles) if z != self.randMus for y in s.motorCmdCellRange[z]+IDSCgidsInverse]:
x.interval = s.backgroundrateMin**-1*1e3 # otherwise set to minimum
#if s.rank==0: print 'exploratory movement, randMus',self.randMus,' strength:',self.randMul,' duration:', self.randDur
#print 'IDSC cells:', IDSCgids
#print 'IDSC inverse cells:', IDSCgidsInverse
elif s.explorMovs == 2: # add random noise to EB5 population
self.targetCells = list(range(s.popGidStart[s.EB5], s.popGidEnd[s.EB5]+1)) # EB5 cell gids
self.randNumCells = randint(1, int(s.explorCellsFraction*len(self.targetCells))) # num of cells to stimumales
self.randCells = sample(self.targetCells, int(self.randNumCells)) # select random gids
for (i,x) in enumerate(s.backgroundsources): # for all input background netstims
if s.backgroundgid[i] in self.randCells: # if connectd to selected random cells
x.interval = s.backgroundrateExplor**-1*1e3 # increase input
elif s.backgroundgid[i] in [y for y in self.targetCells if y not in self.randCells]: # for the rest of cells
x.interval = s.backgroundrateMin**-1*1e3 # set to normal level
#if s.rank==0:
#print 'Nodes:', s.rank,' - exploratory movement, numcells:',self.randNumCells,' strength:',self.randMul,' duration:', self.randDur, 'cells:', self.randCells
## Reset arm and set target after every trial -start from center etc
if s.trialReset and t-s.timeoflastreset > s.testTime:
self.resetArm(s, t)
s.targetid = s.trialTargets[self.trial] # set target based on trial number
self.targetPos = self.setTargetByID(s.targetid, self.startAng, self.targetDist, self.armLen)
if s.PMdinput == 'targetSplit': self.setPMdInput(s)
## Only move after initial period - avoids initial transitory spiking period (NSLOC sync spikes), and allows for variables with history to clear
# can be justified as preparatory period (eg. watiing for go cue)
if t > self.initArmMovement:
## Gather spikes #### from all vectors to then calculate motor command
for i in range(s.nMuscles):
cmdVecs = [array(s.hostspikevecs[x]) for x in range(s.cellsperhost) if (s.gidVec[x] in s.motorCmdCellRange[i])]
self.motorCmd[i] = sum([len(x[(x < t) * (x > t-self.cmdtimewin)]) for x in cmdVecs])
s.pc.allreduce(self.vec.from_python([self.motorCmd[i]]), 1) # sum
self.motorCmd[i] = self.vec.to_python()[0]
# else:
# for i in range(s.nMuscles): # stimulate all muscles equivalently so arm doesnt move
# self.motorCmd[i] = 0.2 * self.cmdmaxrate
## Calculate final motor command
if s.rank==0:
self.motorCmd = [x / self.cmdmaxrate for x in self.motorCmd] # normalize motor command
if s.antagInh: # antagonist inhibition
if self.motorCmd[SH_EXT] > self.motorCmd[SH_FLEX]: # sh ext > sh flex
self.motorCmd[SH_FLEX] = self.motorCmd[SH_FLEX]**2 / self.motorCmd[SH_EXT] / s.antagInh
elif self.motorCmd[SH_EXT] < self.motorCmd[SH_FLEX]: # sh flex > sh ext
self.motorCmd[SH_EXT] = self.motorCmd[SH_EXT]**2 / self.motorCmd[SH_FLEX] / s.antagInh
if self.motorCmd[EL_EXT] > self.motorCmd[EL_FLEX]: # el ext > el flex
self.motorCmd[EL_FLEX] = self.motorCmd[EL_FLEX]**2 / self.motorCmd[EL_EXT] / s.antagInh
elif self.motorCmd[EL_EXT] < self.motorCmd[EL_FLEX]: # el ext > el flex
self.motorCmd[EL_EXT] = self.motorCmd[EL_EXT]**2 / self.motorCmd[EL_FLEX] / s.antagInh
############################
# ALL arms: Send motor command to virtual arm; receive new position; update proprioceptive population (ASC)
############################
# Worker 0 sends motor commands and receives data from virtual arm
#print "t=%f , self.initArmMovement=%f"%(t, self.initArmMovement)
if s.rank == 0:
if self.type == 'musculoskeletal': # MUSCULOSKELETAL
try:
dataReceived = arminterface.sendAndReceiveDataPackets(t, self.interval, self.motorCmd[0], self.motorCmd[1], self.motorCmd[2], self.motorCmd[3])
except:
dataReceived = [self.ang[SH], self.ang[EL]]
if not dataReceived or dataReceived==[-3,3]: # if error receiving packet
dataReceived = [self.ang[SH], self.ang[EL]] # use previous packet
print('Missed packet at t=%.2f',t)
elif self.type == 'dummyArm': # DUMMYARM
dataReceived = self.runDummyArm(self.motorCmd) # run dummyArm
elif self.type == 'randomOutput': # RANDOMOUTPUT
dataReceived = [0,0]
dataReceived[0] = uniform(self.minPval, self.maxPval) # generate 2 random values
dataReceived[1] = uniform(self.minPval, self.maxPval)
# broadcast dataReceived to other workers.
n = s.pc.broadcast(self.vec.from_python(dataReceived), 0) # convert python list to hoc vector for broadcast data received from arm
else: # other workers
n = s.pc.broadcast(self.vec, 0) # receive shoulder and elbow angles from worker0 so can compare with cells in this worker
dataReceived = self.vec.to_python()
if self.type == 'musculoskeletal':
[self.ang[SH], self.ang[EL]] = dataReceived
self.handPos = self.angles2pos(self.ang, self.armLen)
self.angVel[SH] = self.angVel[EL] = 0
else:
[self.ang[SH], self.ang[EL], self.angVel[SH], self.angVel[EL], self.handPos[SH], self.handPos[EL]] = dataReceived # map data received to shoulder and elbow angles
#[self.ang[SH], self.ang[EL], self.angVel[SH], self.angVel[EL]] = dataReceived # map data received to shoulder and elbow angles
#### Update proprio pop ASC
for c in range(0, self.numPcells, 2):
try:
id = s.gidDic[self.pStart + c] # find local index corresponding to gid
if (self.ang[SH] >= self.prange[c,0] and self.ang[SH] < self.prange[c,1]): # in angle in range -> high firing rate
s.cells[id].interval=1000/self.maxPrate # interval in ms as a function of rate
else: # if angle not in range -> low firing rate
s.cells[id].interval=1000/self.minPrate # interval in ms as a function of rate
except:
pass # local index corresponding to gid not found in this node
try:
id = s.gidDic[self.pStart + c + 1] # find local index corresponding to gid
if (self.ang[EL] >= self.prange[c+1,0] and self.ang[EL] < self.prange[c+1,1]): # in angle in range -> high firing rate
s.cells[id].interval=1000/self.maxPrate # interval in ms as a function of rate
else: # if angle not in range -> low firing rate
s.cells[id].interval=1000/self.minPrate # interval in ms as a function of rate
except:
pass # local index corresponding to gid not found in this node
#### Calculate error between hand and target for interval between RL updates
if s.rank == 0 and self.initArmMovement: # do not update between trials
#print 't=%.2f, xpos=%.2f'%(t,self.targetPos[X])
self.error = sqrt((self.handPos[X] - self.targetPos[X])**2 + (self.handPos[Y] - self.targetPos[Y])**2)
return self.critic
################################
### CLOSE
################################
def close(self, s):
if self.type == 'randomOutput':
print('\nClosing random output virtual arm...')
if self.type == 'dummyArm':
if s.explorMovs == 1: # remove explor movs related noise to cells
for imus in range(s.nMuscles):
IDSCgids = array(s.motorCmdCellRange[self.randMus]) - int(s.popGidStart[s.EDSC]) + int(s.popGidStart[s.IDSC])
for (i,x) in enumerate(s.backgroundsources):
if s.backgroundgid[i] in s.motorCmdCellRange[imus]+list(IDSCgids):
x.interval = 0.0001**-1*1e3
x.noise = s.backgroundnoise # Fractional noise in timing
elif s.explorMovs == 2: # remove explor movs related noise to cells
for (i,x) in enumerate(s.backgroundsources): # for all input background netstims
if s.backgroundgid[i] in self.targetCells: # for the rest of cells
x.interval = s.backgroundrate**-1*1e3 # set to normal level
if s.trialReset:
s.timeoflastreset = 0
self.initArmMovement = int(s.initArmMovement)
if s.rank == 0:
print('\nClosing dummy virtual arm ...')
if self.anim:
ioff() # turn interactive mode off
close(self.fig) # close arm animation graph
if self.graphs: # plot graphs
self.plotTraj(s.filename)
#self.plotAngs()
#self.plotMotorCmds()
#self.plotRL()
if self.type == 'musculoskeletal':
if s.explorMovs == 1: # remove explor movs related noise to cells
for imus in range(s.nMuscles):
IDSCgids = array(s.motorCmdCellRange[self.randMus]) - int(s.popGidStart[s.EDSC]) + int(s.popGidStart[s.IDSC])
for (i,x) in enumerate(s.backgroundsources):
if s.backgroundgid[i] in s.motorCmdCellRange[imus]+list(IDSCgids):
x.interval = 0.0001**-1*1e3
x.noise = s.backgroundnoise # Fractional noise in timing
elif s.explorMovs == 2: # remove explor movs related noise to cells
for (i,x) in enumerate(s.backgroundsources): # for all input background netstims
if s.backgroundgid[i] in self.targetCells: # for the rest of cells
x.interval = s.backgroundrate**-1*1e3 # set to normal level
if s.trialReset:
s.timeoflastreset = 0
self.initArmMovement = int(s.initArmMovement)
if s.rank == 0:
print('\nClosing dummy virtual arm ...')
arminterface.closeSavePlot(self.duration/1000.0, self.interval)
if self.graphs: # plot graphs
self.plotTraj(s.filename)
#self.plotAngs()
self.plotMotorCmds()
self.plotRL()