Skip to content

Commit

Permalink
Merge branch 'ow-0.9.5' into ow-dev-pg
Browse files Browse the repository at this point in the history
* ow-0.9.5:
  Fix issue with fig.canvas.set_window_title on later matplotlib versions
  More test with replay
  Improved replay script
  Initial replay script
  Fix plot positions
  Improved catching of errors during execution
  Bump to py script v0.1.6; More info on error with muscle input MVL24
  Update GitHub actions versions
  • Loading branch information
pgleeson committed Jan 9, 2025
2 parents 6ccc5e8 + cb8f51a commit 6f38c25
Show file tree
Hide file tree
Showing 7 changed files with 223 additions and 34 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci-build-intel.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install Intel OpenCL libraries needed for Sibernetic
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/ci-build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
git config --global core.autocrlf false
git config --global core.eol lf
- uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install AMD OpenCL libraries needed for Sibernetic
run: |
Expand Down
17 changes: 13 additions & 4 deletions main_sim.py
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,9 @@ def run(self, skip_to_time=-1):
try:
val = getattr(self.h, var)[0].soma.cai
except AttributeError as e:
print(e)
print("Problem passing neuronal output of %s to muscle in Sibernetic: %s"%(var, e))
continue
val = 0
scaled_val = self._scale(val)
values.append(scaled_val)
vars_read.append(var)
Expand All @@ -206,7 +207,8 @@ def run(self, skip_to_time=-1):
try:
val = getattr(self.h, var)[0].soma.cai
except AttributeError as e:
print(e)
print("Problem passing neuronal output of %s to muscle in Sibernetic: %s"%(var, e))
val = 0
continue
scaled_val = self._scale(val)
values.append(scaled_val)
Expand All @@ -216,7 +218,13 @@ def run(self, skip_to_time=-1):
try:
val = getattr(self.h, var)[0].soma.cai
except AttributeError as e:
print(e)
if var=='a_MVL24':
extra = "Note: not an issue as no muscle MVL24 in the real C. elegans"
else:
extra = ''
print("Problem passing output of %s to muscle in Sibernetic: %s %s"%(var, e, extra))

val = 0
continue
scaled_val = self._scale(val)
values.append(scaled_val)
Expand All @@ -226,7 +234,8 @@ def run(self, skip_to_time=-1):
try:
val = getattr(self.h, var)[0].soma.cai
except AttributeError as e:
print(e)
print("Problem passing neuronal output of %s to muscle in Sibernetic: %s"%(var, e))
val = 0
continue
scaled_val = self._scale(val)
values.append(scaled_val)
Expand Down
3 changes: 2 additions & 1 deletion plot_positions.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ def plot_positions(pos_file_name, rate_to_plot = 100, save_figure=True, show_plo
if plot_frame:
print_(" >> Plotting frame %i at %s ms; line %i: %s...\n"%(num_plotted_frames,t_ms,index,line))
ax.plot(xs,ys,'.', markersize=1)
ax.axis('equal')
num_plotted_frames+=1
if num_plotted_frames%3 == 1:
time = '%sms'%t_ms if not t_ms==int(t_ms) else '%sms'%int(t_ms)
Expand Down Expand Up @@ -171,7 +172,7 @@ def plot_muscle_activity(muscle_file_name, dt, logstep, save_figure=True, show_p
fig, ax0 = plt.subplots(4, sharex=True, sharey=True)

info = "Muscle activation values per quadrant"
fig.canvas.set_window_title(info)
fig.canvas.manager.set_window_title(info)

ax0[0].set_title('Muscle activation values per quadrant - '+quadrant0, size='small')
ax0[0].set_ylabel('muscle #')
Expand Down
170 changes: 170 additions & 0 deletions replay.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
import pyvista as pv

import sys
import time


last_mesh = None
all_points = None
all_point_types = None
plotter = None

colours = {1.1: "lightblue", 2.1: "green", 2.2: "turquoise", 3: "#eeeeee"}
colours = {1.1: "blue", 2.2: "turquoise"}

log_step = None
time_step = None
slider = None

def create_mesh(step):
step_count = step
value = step_count
global last_mesh, all_points, all_point_types, plotter
global log_step
global time_step
global slider

index = int(value)
timeindex_offset = 1
time_ms = (index+timeindex_offset)*log_step*time_step*1000

curr_points = all_points[index]
curr_types = all_point_types[index]

print(
"Changing to time %g ms, step: %s (%s), displaying %i points "
% (time_ms, index, value, len(curr_points))
)

if last_mesh is None:
last_mesh = pv.PolyData(curr_points)
last_mesh["types"] = curr_types
print(last_mesh)

plotter.add_mesh(
last_mesh,
render_points_as_spheres=True,
cmap=[c for c in colours.values()],
point_size=3,
)
else:
last_mesh.points = curr_points

plotter.render()

time.sleep(0.1)

return


def replay_simulation(position_file):
global last_mesh, all_points, all_point_types, plotter
global log_step
global time_step
global slider

points = []
types = []

line_count = 0
pcount = 0

all_points = []
all_point_types = []

time_count = 0

include_boundary = False

for line in open(position_file):
ws = line.split()
# print(ws)

if line_count == 6:
numOfElasticP = int(ws[0])
if line_count == 7:
numOfLiquidP = int(ws[0])
if line_count == 8:
numOfBoundaryP = int(ws[0])
if line_count == 9:
time_step = float(ws[0])
if line_count == 10:
log_step = int(ws[0])

if len(ws) == 4:
type = float(ws[3])

if not (type == 3 and not include_boundary):
points.append([float(ws[0]), float(ws[1]), float(ws[2])])
types.append(type)

if log_step is not None:
pcount += 1

if pcount == numOfBoundaryP + numOfElasticP + numOfLiquidP:
print(
"End of one batch of %i added, %i total points (B: %i, E: %i, L: %i) at line %i, time count: %i"
% (
len(points),
pcount,
numOfBoundaryP,
numOfElasticP,
numOfLiquidP,
line_count,
time_count,
)
)
all_points.append(points)
all_point_types.append(types)

points = []
types = []
pcount = 0
numOfBoundaryP = 0

time_count += 1

line_count += 1

print(
"Loaded positions with %i elastic, %i liquid and %i boundary points (%i total), %i lines. Time step: %s, log step: %s"
% (
numOfElasticP,
numOfLiquidP,
numOfBoundaryP,
numOfElasticP + numOfLiquidP + numOfBoundaryP,
line_count,
time_step,
log_step,
)
)

print("Num of time points found: %i" % len(all_points))

plotter = pv.Plotter()
plotter.set_background("lightgrey")

last_mesh = None

create_mesh(0)

max_time = len(all_points) - 1

slider = plotter.add_slider_widget(
create_mesh, rng=[0, max_time], value=max_time, title="Time point"
)

plotter.add_timer_event(
max_steps=len(all_points), duration=200, callback=create_mesh
)

plotter.show()


if __name__ == "__main__":
position_file = "buffers/position_buffer.txt"

if len(sys.argv) == 2:
position_file = sys.argv[1]

replay_simulation(position_file)
55 changes: 32 additions & 23 deletions sibernetic_c302.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import pprint
pp = pprint.PrettyPrinter(indent=4)

script_version = '0.1.5' # This will change at different rate to C++ code...
script_version = '0.1.7' # This will change at different rate to C++ code...

DEFAULTS = {'duration': 2.0,
'dt': 0.005,
Expand Down Expand Up @@ -326,15 +326,17 @@ def run(a=None,**kwargs):

command = './Release/Sibernetic %s -f %s -no_g -l_to lpath=%s timelimit=%s timestep=%s logstep=%s device=%s'%('' if a.noc302 else '-c302', a.configuration, sim_dir, a.duration/1000.0, a.dt/1000, a.logstep, a.device)

env = { "DISPLAY": os.environ.get('DISPLAY'),
env = { "DISPLAY": os.environ.get('DISPLAY') if os.environ.get('DISPLAY') is not None else '',
"XAUTHORITY": os.environ.get('XAUTHORITY') if os.environ.get('XAUTHORITY') is not None else '',
"PYTHONPATH": ".:%s:%s" % (os.environ.get('PYTHONPATH', '.'), os.path.abspath(sim_dir))}

sim_start = time.time()

reportj = {}

completion_status = 'Completed successfully'
SUCCESS = 'Completed successfully'
completion_status = SUCCESS

announce("Executing main Sibernetic simulation of %sms using: \n\n %s \n\n in %s with %s"%(a.duration, command, run_dir, env))
try:
pynml.execute_command_in_dir_with_realtime_output(command, run_dir, prefix="Sibernetic: ", env=env, verbose=True)
Expand All @@ -346,6 +348,9 @@ def run(a=None,**kwargs):
completion_status = 'Error during simulation'

reportj['completion_status'] = completion_status

successful = completion_status == SUCCESS

sim_end = time.time()


Expand Down Expand Up @@ -403,7 +408,7 @@ def run(a=None,**kwargs):
report_file.write(s)


if not a.noc302:
if not a.noc302 and successful:

announce("Generating images for neuronal activity...")

Expand All @@ -430,27 +435,31 @@ def run(a=None,**kwargs):
# time.sleep(2)
#plot_positions(pos_file_name,rate_to_plot = int(a.duration/5), show_plot=False)

from plot_positions import plot_muscle_activity
musc_act_file = os.path.join(sim_dir, 'muscles_activity_buffer.txt')
plot_muscle_activity(musc_act_file,a.dt,a.logstep, show_plot=False)

from wcon.generate_wcon import generate_wcon

num_steps = int(a.duration/a.dt)
num_steps_logged = num_steps/a.logstep
rate = max(1,int(num_steps_logged/20.0))
#print("%s, %s"%(num_steps, rate))
generate_wcon(os.path.join(sim_dir, 'worm_motion_log.txt'),
os.path.join(sim_dir, 'worm_motion_log.wcon'),
rate_to_plot=rate,
plot=False,
save_figure1_to=os.path.join(sim_dir, 'worm_motion_1.png'),
save_figure2_to=os.path.join(sim_dir, 'worm_motion_2.png'),
save_figure3_to=os.path.join(sim_dir, 'worm_motion_3.png'))
if successful:
from plot_positions import plot_muscle_activity
musc_act_file = os.path.join(sim_dir, 'muscles_activity_buffer.txt')
plot_muscle_activity(musc_act_file,a.dt,a.logstep, show_plot=False)

from wcon.generate_wcon import generate_wcon

num_steps = int(a.duration/a.dt)
num_steps_logged = num_steps/a.logstep
rate = max(1,int(num_steps_logged/20.0))
#print("%s, %s"%(num_steps, rate))
generate_wcon(os.path.join(sim_dir, 'worm_motion_log.txt'),
os.path.join(sim_dir, 'worm_motion_log.wcon'),
rate_to_plot=rate,
plot=False,
save_figure1_to=os.path.join(sim_dir, 'worm_motion_1.png'),
save_figure2_to=os.path.join(sim_dir, 'worm_motion_2.png'),
save_figure3_to=os.path.join(sim_dir, 'worm_motion_3.png'))


run_dur_sec = sim_end-sim_start
announce("Finished run in %s sec (%s hours)!\n\nSimulation saved in: %s\n\n"%(run_dur_sec,run_dur_sec/3600.0,sim_dir) + \
announce("Finished run in %s sec (%s hours)!\n\n"%(run_dur_sec,run_dur_sec/3600.0)+ \
("Simulation output saved in: %s\n\n"%(sim_dir) if successful else 'SIMULATION UNSUCCESSFUL!\n\n') + \
"Report of simulation at: %s/report.json\n\n"%(sim_dir)+ \
"Replay recorded simulation with: ./Release/Sibernetic -l_from lpath=%s\n"%(sim_dir))
("Replay recorded simulation with: ./Release/Sibernetic -l_from lpath=%s\n"%(sim_dir) if successful else ''))


if a.test:
Expand Down
8 changes: 4 additions & 4 deletions wcon/generate_wcon.py
Original file line number Diff line number Diff line change
Expand Up @@ -232,15 +232,15 @@ def generate_wcon(pos_file_name,

plt.xlabel("x direction")
plt.ylabel("y direction")
fig.canvas.set_window_title(info)
fig.canvas.manager.set_window_title(info)
plt.title(info)

if save_figure1_to:
plt.savefig(save_figure1_to)

fig = plt.figure()
info = "Speed of worm in x (lateral) & y (along body) directions"
fig.canvas.set_window_title(info)
fig.canvas.manager.set_window_title(info)
plt.title(info)
plt.xlabel("Time (s)")
plt.ylabel("Speed")
Expand Down Expand Up @@ -274,7 +274,7 @@ def generate_wcon(pos_file_name,
ax = plt.gca();

info = "Propagation of curvature along body of worm (180=straight)"
fig.canvas.set_window_title(info)
fig.canvas.manager.set_window_title(info)
plt.title(info)

xt = ax.get_xticks()
Expand Down Expand Up @@ -372,7 +372,7 @@ def get_rainbow_color_for_volts(fract):
fig = plt.figure()
info = "Pos at %sms"%t
fig.canvas.set_window_title(info)
fig.canvas.manager.set_window_title(info)
plt.title(info)
mx = y[t]
Expand Down

0 comments on commit 6f38c25

Please sign in to comment.