https://github.com/NikVard/memstim-hh
Tip revision: 563f808f6c4f40630f5b8876cc0b440cdf4159e8 authored by NikVard on 22 September 2023, 08:19:24 UTC
[UPDATE] Updated default figure names in scripts
[UPDATE] Updated default figure names in scripts
Tip revision: 563f808
compare_structures.py
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
from brian2 import *
from scipy import optimize
import re # regular expressions
# Initialization
areas = ['EC', 'DG', 'CA1', 'CA3']
types1 = ['exc', 'inh']
types2 = ['E', 'I']
scale_aussel = 150*umetre
# ==============
# Optimization
# ==============
def parse_coords(fname):
""" Opens file and parses coordinates """
pattern = r'[\[\],\n]' # to remove from read lines
x_tmp = []
y_tmp = []
with open(fname, 'r') as fin:
for line in fin:
tok = re.sub(pattern, '', line).split()
x_tmp.append(float(tok[0]))
y_tmp.append(float(tok[1]))
return array([x_tmp,y_tmp]).T
# read coordinates from files
ref = []
adj = []
# EC
# ============
## E
tmp1 = parse_coords(fname='positions/EC_exc.txt')
tmp2 = load('./neuron_positions/full/EC_E-stipple-10000.npy')
ref.append(tmp1)
adj.append(tmp2)
## I
tmp1 = parse_coords(fname='positions/EC_inh.txt')
tmp2 = load('./neuron_positions/full/EC_I-stipple-1000.npy')
ref.append(tmp1)
adj.append(tmp2)
# DG
# ============
## E
tmp1 = parse_coords(fname='positions/DG_exc.txt')
tmp2 = load('./neuron_positions/full/DG_E-stipple-10000.npy')
ref.append(tmp1)
adj.append(tmp2)
## I
tmp1 = parse_coords(fname='positions/DG_inh.txt')
tmp2 = load('./neuron_positions/full/DG_I-stipple-100.npy')
ref.append(tmp1)
adj.append(tmp2)
# CA3
# ============
## E
tmp1 = parse_coords(fname='positions/CA3_exc.txt')
tmp2 = load('./neuron_positions/full/CA3_E-stipple-1000.npy')
ref.append(tmp1)
adj.append(tmp2)
##I
tmp1 = parse_coords(fname='positions/CA3_inh.txt')
tmp2 = load('./neuron_positions/full/CA3_I-stipple-100.npy')
ref.append(tmp1)
adj.append(tmp2)
# CA1
# ============
## E
tmp1 = parse_coords(fname='positions/CA1_exc.txt')
tmp2 = np.load('./neuron_positions/full/CA1_E-stipple-10000.npy')
ref.append(tmp1)
adj.append(tmp2)
## I
tmp1 = parse_coords(fname='positions/CA1_inh.txt')
tmp2 = load('./neuron_positions/full/CA1_I-stipple-1000.npy')
ref.append(tmp1)
adj.append(tmp2)
# ============
def f0(pc1, pc2):
''' Function to be minimized - difference between point clouds '''
# we will add the range differences between point clouds
diff = 0.
for idx in arange(len(pc1)):
curr_ref = pc1[idx]
rx_ref = abs(amin(curr_ref[:,0]) - amax(curr_ref[:,0]))
ry_ref = abs(amin(curr_ref[:,1]) - amax(curr_ref[:,1]))
curr_adj = pc2[idx]
rx = abs(amin(curr_adj[:,0]) - amax(curr_adj[:,0]))
ry = abs(amin(curr_adj[:,1]) - amax(curr_adj[:,1]))
diff += (rx_ref - rx)**2 + (ry_ref - ry)**2
return diff
def f1(x, *params):
''' Wrapper around f0(); adjusts the scale '''
reference, adjusted, scale_ref = params
# calculate the new scale
scale_adj = (1000./x)*umetre
# scale the point clouds, remove units
reference_scaled = [elem*scale_ref/mmetre for elem in reference]
adjusted_scaled = [elem*scale_adj/mmetre for elem in adjusted]
return f0(pc1=reference_scaled, pc2=adjusted_scaled)
# run the optimization
resbrute = optimize.brute(func=f1, args=(ref, adj, scale_aussel), ranges=((500.,1000.),), Ns=501, full_output=True, disp=True)
# update the scale
scale_adj = round(1000./resbrute[0][0],6)*umetre
print("========================================")
print("Minimized value: ", resbrute[0][0])
print("Adjusted scale: ", scale_adj)
print("========================================")
# set up a figure twice as wide as it is tall
fig = figure(figsize=plt.figaspect(0.5))
# =============
# First subplot
# =============
# set up the axes for the first plot
ax = fig.add_subplot(121, projection='3d')
ax.set_title("Reference")
ax.set_xlabel("X [m]")
ax.set_ylabel("Y [m]")
ax.set_zlabel("Z [m]")
# Function for parsing coordinates
def parse_coords_3d(fname):
""" Opens file and parses coordinates """
pattern = r'[\[\],\n]' # to remove from read lines
coords = []
with open(fname, 'r') as fin:
idx = 0
for line in fin:
tok = re.sub(pattern, '', line).split()
tmp = [float(tok[0]), float(tok[1]), float(tok[2])]
coords.append(tmp)
idx += 1
return coords
# Iterate over position files from original Aussel model
for area in areas:
for type in types1:
fname = 'positions/' + area + '_' + type + '.txt'
coords_aussel = asarray(parse_coords_3d(fname))*scale_aussel
if type=='exc':
if area=='DG':
c = 'green'
else:
c = 'blue'
else:
c = 'red'
ax.scatter(coords_aussel[:,0], coords_aussel[:,1], coords_aussel[:,2], c=c)
# ==============
# Second subplot
# ==============
# set up the axes for the second plot
ax = fig.add_subplot(122, projection='3d')
ax.set_title("Adjusted")
ax.set_xlabel("X [m]")
ax.set_ylabel("Y [m]")
ax.set_zlabel("Z [m]")
# Iterate over position files from adjusted model
for area in areas:
for type in types2:
fname = 'neuron_positions/test/' + area + '_' + type + '-stipple.npy'
coords_adj = load(fname)
N = max(coords_adj.shape)
coords_adj = hstack((coords_adj, zeros((N, 1)))) # add z-axis
coords_adj *= scale_adj
coords_adj[:,2] += 15*mm*rand(N)
if type=='E':
if area=='DG':
c = 'green'
else:
c = 'blue'
else:
c = 'red'
ax.scatter(coords_adj[:,0], -coords_adj[:,1], coords_adj[:,2], c=c)
show()
