Force velocity 1
Overview
This demo shows how to simulate an experiment that measures the force-velocity and force-power curves.
What this demo does
This demo runs a series of simulations in which a half-sarcomere is activated and then allowed to shorten against different loads.
The shortening velocity is calculated during the isotonic release phase of each trial.
Instructions
- In MATLAB, change the working directory to
<repo>/code/demos/force_velocity/force_velocity_1
- Open
force_velocity_1.m
- Press F5 to run
Output
After the program finishes (it may take a minute or so) you should see a figure.
How this worked
The first section of the code sets up some variables and adds the MATMyoSim folders to the current path. Line 9 creates an array called isotonic_forces
that contains 12 values evenly spaced between 5000 and 1.2e5.
function demo_force_velocity_1
% Demo demonstrates a force_velocity curve
% Variables
model_file = 'sim_input/model.json';
options_file = 'sim_input/options.json';
protocol_base_file = 'sim_input/prot';
results_base_file = 'sim_output/results';
isotonic_forces = linspace(5000, 1.2e5, 12);
no_of_time_points = 500;
time_step = 0.001;
isotonic_start_s = 0.4;
fit_time_s = [0.43 0.48];
display_time_s = [0.35 0.5];
% Make sure the path allows us to find the right files
addpath(genpath('../../../../code'));
The next section loops through isotonic_forces
creating a protocol file for each condition. Specifically, the Mode
values for the latter portion of each protocol are set to the appropriate force value. As described in the protocol page this switches MATMyoSim to a force-control mode so that the model length changes as required to keep force at the specific value.
The file names are stored in a batch structure as the loop progresses.
% Generate protocols, storing files as a batch structure
batch_structure = [];
for i = 1 : numel(isotonic_forces)
protocol_file{i} = sprintf('%s_%i.txt', protocol_base_file, i);
results_file{i} = sprintf('%s_%i.myo', results_base_file, i);
generate_isotonic_pCa_protocol( ...
'time_step', time_step, ...
'no_of_points', no_of_time_points, ...
'during_pCa', 4.5, ...
'isotonic_start_s', isotonic_start_s, ...
'isotonic_stress', isotonic_forces(i), ...
'output_file_string', ...
sprintf('%s_%i.txt', protocol_base_file, i));
% Add job as an element of an array
batch_structure.job{i}.model_file_string = model_file;
batch_structure.job{i}.options_file_string = options_file;
batch_structure.job{i}.protocol_file_string = protocol_file{i};
batch_structure.job{i}.results_file_string = results_file{i};
end
The next section is very short. It runs all 12 simulations in parallel using all of the threads that are available to MATLAB.
% Now that you have all the files, run the batch jobs in parallel
run_batch(batch_structure);
The next section loads the results files back into memory and plots the force and length traces. The force and shortening velocity for each simulation are calculated from (1) mean force and (2) the slope of the half-sarcomere length against time during the isotonic release phase.
% Now load the result files and calculate force-velocity and power
% Display the data as you go
figure(4);
clf;
cm = jet(numel(isotonic_forces));
for i = 1 : numel(isotonic_forces)
% Load the simulation back in
sim = load(results_file{i}, '-mat');
sim_output = sim.sim_output;
% Display the full simulation
subplot(3,2,1);
hold on;
plot(sim_output.time_s, sim_output.hs_force, '-', 'Color', cm(i,:));
subplot(3,2,3);
hold on;
plot(sim_output.time_s, sim_output.hs_length, '-', 'Color', cm(i,:));
% Find the indices for fitting
vi = find((sim_output.time_s > fit_time_s(1)) & ...
(sim_output.time_s <= fit_time_s(end)));
% Pull off mean force and shortening velocity
stress(i) = mean(sim_output.hs_force(vi));
p = polyfit(sim_output.time_s(vi), sim_output.hs_length(vi), 1);
velocity(i) = -p(1) ./ sim_output.hs_length(1);
power(i) = stress(i) * velocity(i);
% Display the zoomed area with the fits
di = find((sim_output.time_s > display_time_s(1)) & ...
(sim_output.time_s <= display_time_s(end)));
subplot(3,2,2);
hold on;
plot(sim_output.time_s(di), sim_output.hs_force(di), '-', 'Color', cm(i,:));
plot(sim_output.time_s(vi), stress(i) * ones(numel(vi),1), 'k-');
subplot(3,2,4);
hold on;
plot(sim_output.time_s(di), sim_output.hs_length(di), '-', 'Color', cm(i,:));
plot(sim_output.time_s(vi), polyval(p, sim_output.time_s(vi)), 'k-');
% Add in force-velocity and force-power curves
subplot(3,2,5);
hold on;
plot(stress(i), velocity(i), 'o', 'Color', cm(i,:));
subplot(3,2,6);
hold on;
plot(stress(i), power(i), 'o', 'Color', cm(i,:));
% Add labels
if (i == numel(isotonic_forces))
for j=1:2
subplot(3,2,j);
xlabel('Time (s)');
ylabel('Stress (kN m^{-2})');
subplot(3,2,j+2);
xlabel('Time (s)');
ylabel('Half-sarcomere length (nm)');
end
subplot(3,2,5);
xlabel('Stress (kN m^{-2})');
ylabel('Shortening velocity (l_0 s^{-1})');
subplot(3,2,6);
xlabel('Stress (kN m^{-2})');
ylabel('Power (kN m^{-2} l_0 s^{-1})');
end
end
The last section fits smooth curves to the force-velocity and force-power data.
% Add in fits for fv and force power curves
% First the fv curve
[x0,a,b,r_squared,stress_fit,vel_fit] = fit_hyperbola( ...
'x_data', stress, 'y_data', velocity, ...
'x_fit', linspace(0, 1.2e5, 100));
subplot(3,2,5);
plot(stress_fit, vel_fit, 'k-');
title(sprintf('(x+a)(y+b)=b(x_0+a)\na=%g, b=%g, x_0=%g',a,b,x0));
% Now the power curve
[x0,a,b,r_squared,stress_fit,pow_fit] = fit_power_curve(...
stress, power, ...
'x_fit', linspace(0, 1.2e5, 100));
subplot(3,2,6);
plot(stress_fit, pow_fit, 'k-');
title(sprintf('y=x*b*(((x_0+a)/(x+a))-1)\na=%g, b=%g, x_0=%g',a,b,x0));