def exercise2a(): """ Exercise 2a The goal of this exercise is to understand the relationship between muscle length and tension. Here you will re-create the isometric muscle contraction experiment. To do so, you will have to keep the muscle at a constant length and observe the force while stimulating the muscle at a constant activation.""" # Defination of muscles parameters = MuscleParameters() biolog.warning("Loading default muscle parameters") biolog.info(parameters.showParameters()) # Create muscle object muscle = Muscle.Muscle(parameters) muscle.l_opt = 0.11 activation = 0.05 stretch=np.arange(-0.09, 0.09, 0.001) res = isometric_contraction(muscle, stretch, activation) plt.title('Force-Length when activation is %s' %activation) plt.title('Force-Length when Lopt is %s' %muscle.l_opt) plt.ylim(0,1.7*max(res[1])) # plt.ylim(0,2500) plt.plot(res[0],res[1]) plt.plot(res[0],res[2]) plt.plot(res[0],res[2]+res[1]) plt.legend(['active force','passive force','total force']) plt.xlabel('Length(m)') plt.ylabel('Force(N)') plt.grid() plt.show() """ Example for plotting graphs using matplotlib. """
def exercise2b(): """ Exercise 2b Under isotonic conditions external load is kept constant. A constant stimulation is applied and then suddenly the muscle is allowed contract. The instantaneous velocity at which the muscle contracts is of our interest""" # Defination of muscles muscle_parameters = MuscleParameters() print(muscle_parameters.showParameters()) mass_parameters = MassParameters() print(mass_parameters.showParameters()) # Create muscle object muscle = Muscle.Muscle(muscle_parameters) # Run the isotonic_contraction load=np.arange(0, 300, 10) res = isotonic_contraction(muscle,load,muscle_parameters=MuscleParameters(),mass_parameters=MassParameters()) plt.plot(res[1],res[0]) plt.title('force-velocity when activation is %s' %res[2]) plt.ylim(0,60) plt.xlabel('Velocity of the contractile element Vce (m/s)') plt.ylabel('Force generated by the muscle(N)') plt.show()
def exercise2b(): """ Exercise 2b Under isotonic conditions external load is kept constant. A constant stimulation is applied and then suddenly the muscle is allowed contract. The instantaneous velocity at which the muscle contracts is of our interest""" # Definition of muscles muscle_parameters = MuscleParameters() print(muscle_parameters.showParameters()) mass_parameters = MassParameters() print(mass_parameters.showParameters()) # Create muscle object muscle = Muscle.Muscle(muscle_parameters) # Point 2d. Different load values. biolog.info("Calling for point 2d") isoK = isotonic_contraction(muscle) lineV = np.arange(-1, 2500, 1) zerV = np.zeros(np.size(lineV)) plt.figure("Plot of Force vs Velocity") plt.plot(isoK[0], isoK[1]) plt.title("Tension vs Normalised Velocity", fontsize=18) plt.plot(zerV, lineV, linestyle=':', color='red') plt.xlabel('Normalised Velocity [-]') plt.ylabel('Total Force of the Muscle [N]') plt.legend(['Force/Velocity [N]']) plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='black') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('velociplot') # plt.plot(isoK[0], isoK[1], 'o', markersize = 5) # Point 2f. Different muscle activation values. activations = np.arange(0.5, 1.05, 0.05) plt.figure( 'Muscle Force vs Normalised velocity for varying activation time') legend2 = list() #print(activations) for i, a in enumerate(activations): muscle1 = Muscle.Muscle(muscle_parameters) #print("Activation = {} [s]".format(a)) iso = isotonic_contraction(muscle1, activation=a) #print("lapin \n {}".format(iso[2])) legend2.append("Activation = {} [-]".format(a)) plt.plot(iso[0], iso[1]) # plot for active force plt.xlabel('Normalised Velocity [-]') plt.ylabel('Total Force [N]') plt.plot(zerV, lineV, linestyle=':', color='red') plt.legend(legend2) plt.grid() plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='black') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('F_vs_Vel_Activations')
def isotonic_contraction(muscle, load, muscle_parameters=MuscleParameters(), mass_parameters=MassParameters()): """ This function implements the isotonic contraction of the muscle. Parameters: ----------- muscle : <Muscle> Instance of Muscle class load : list/array External load to be applied on the muscle. It is the mass suspended by the muscle muscle_parameters : MuscleParameters Muscle paramters instance mass_paramters : MassParameters Mass parameters instance Since the muscle model is complex and sensitive to integration, use the following example as a hint to complete your implementation. """ # Time settings t_start = 0.0 # Start time t_stop = 0.2 # Stop time dt = 0.001 # Time step time = np.arange(t_start,t_stop,dt) load = np.array(load) activation = 0.2 j = 0 res_ = np.ones(len(time)) velocity_ce = np.ones(len(load)) x0 = np.array([-0.0, 0.0]) for load_ in load: muscle.initializeMuscleLength() mass_parameters.mass = load_ # load is mass (kg) state = np.copy(x0) for time_ in time: # before release, iterate to stable state res = muscle_integrate(muscle,state[0],activation, dt) i = 0 # print muscle.force for time_ in time: # release, integrate for the state equations mass_res = odeint(mass_integration,state,[time_, time_ + dt],args=(muscle.force, load_, mass_parameters)) # returns the position & velocity at each t state[0] = mass_res[-1,0] # position of the end of the muscle state[1] = mass_res[-1,1] # velocity of the end of the muscle res = muscle_integrate(muscle,state[0],activation,dt) res_[i] = res['v_CE'] i += 1 if(res['l_MTC'] > muscle_parameters.l_opt + muscle_parameters.l_slack): velocity_ce[j] = min(res_[:]) else: velocity_ce[j] = max(res_[:]) j+=1 return load, velocity_ce,activation
def generate_muscle_parameters(self, muscle_name): """To create muscle parameters from json file. Parameters ---------- muscle_name: string Name of the muscle """ param = self.muscle_parameters[muscle_name] if param is None: print('Invalid muscle name') sys.exit(1) return MuscleParameters(l_slack=param['l_slack'], l_opt=param['l_opt'], v_max=param['v_max'], f_max=param['f_max'], pennation=param['pennation'], name=muscle_name)
def exercise3(): """ Main function to run for Exercise 3. Parameters ---------- None Returns ------- None """ # Define and Setup your pendulum model here # Check Pendulum.py for more details on Pendulum class P_params = PendulumParameters() # Instantiate pendulum parameters P_params.L = .5 # To change the default length of the pendulum P_params.mass = 5. # To change the default mass of the pendulum pendulum = Pendulum(P_params) # Instantiate Pendulum object #### CHECK OUT PendulumSystem.py to ADD PERTURBATIONS TO THE MODEL ##### biolog.info('Pendulum model initialized \n {}'.format( pendulum.parameters.showParameters())) # Define and Setup your pendulum model here # Check MuscleSytem.py for more details on MuscleSytem class M1_param = MuscleParameters() # Instantiate Muscle 1 parameters M1_param.f_max = 1500 # To change Muscle 1 max force M2_param = MuscleParameters() # Instantiate Muscle 2 parameters M2_param.f_max = 1500 # To change Muscle 2 max force M1 = Muscle(M1_param) # Instantiate Muscle 1 object M2 = Muscle(M2_param) # Instantiate Muscle 2 object # Use the MuscleSystem Class to define your muscles in the system muscles = MuscleSytem(M1, M2) # Instantiate Muscle System with two muscles biolog.info('Muscle system initialized \n {} \n {}'.format( M1.parameters.showParameters(), M2.parameters.showParameters())) ### ########################################## 3a ######################################## # # # Define a huge mass, such that the pendulum goes up to pi/2 and up t -pi/2 # P_params.mass = 15000. # # Defines 3 different origins and 3 different insertions for each muscle # origins1 = [-0.01, -0.05, -0.10, -0.15, -0.2] # origins2 = map(lambda x: -(x), origins1) # insertions1 = [-0.15, -0.20, -0.25, -0.30] # insertions2 = insertions1[:] # Just for visibility # legendsertion =np.array(['Insertion at -15 cm', 'Insertion at -20 cm', 'Insertion at -25 cm', 'Insertion at -30 cm']) # legleg = np.array(['Insertion at -15 cm', 'Insertion at -15 cm', 'Insertion at -20 cm', 'Insertion at -20 cm', 'Insertion at -25 cm', 'Insertion at -25 cm', 'Insertion at -30 cm', 'Insertion at -30 cm']) # cols = ('blue', 'red', 'olive', 'purple') ## length1 = np.array() # # for o1,o2 in zip(origins1, origins2): # fig, (ax1, ax2) = plt.subplots(1,2, sharex = True) # fig.suptitle('Origin of muscles: o1 = {}, o2 = {}'.format(o1,o2), fontsize='26') # for i,j in enumerate(insertions1): # # Define Muscle Attachment points # m1_origin = np.array([o1, 0.0]) # Origin of Muscle 1 # m1_insertion = np.array([0.0, j]) # Insertion of Muscle 1 # # m2_origin = np.array([o2, 0.0]) # Origin of Muscle 2 # m2_insertion = np.array([0.0, j]) # Insertion of Muscle 2 # # # Attach the muscles # muscles.attach(np.array([m1_origin, m1_insertion]), # np.array([m2_origin, m2_insertion])) # # # Create a system with Pendulum and Muscles using the System Class # # Check System.py for more details on System class # sys = System() # Instantiate a new system # sys.add_pendulum_system(pendulum) # Add the pendulum model to the system # sys.add_muscle_system(muscles) # Add the muscle model to the system # # ##### Time ##### # # dt=0.01 # t_max = 1. # Maximum simulation time # time = np.arange(0., t_max, dt) # Time vector # # # # ##### Model Initial Conditions ##### # x0_P = np.array([np.pi/2. - 0.00001,0.]) # Pendulum initial condition # # # Muscle Model initial condition # x0_M = np.array([0., M1.l_CE, 0., M2.l_CE]) # # x0 = np.concatenate((x0_P, x0_M)) # System initial conditions # # ##### System Simulation ##### # # For more details on System Simulation check SystemSimulation.py # # SystemSimulation is used to initialize the system and integrate # # over time # # sim = SystemSimulation(sys) # Instantiate Simulation object # # # Add muscle activations to the simulation # # Here you can define your muscle activation vectors # # that are time dependent # # act1=np.ones((len(time),1))*0.05 # act2=np.ones((len(time),1))*0.05 # # activations = np.hstack((act1, act2)) # # # Method to add the muscle activations to the simulation # # sim.add_muscle_activations(activations) # # # Simulate the system for given time # # sim.initalize_system(x0, time) # Initialize the system state # # # Integrate the system for the above initialized state and time # sim.simulate() # # # Obtain the states of the system after integration # # res is np.array [time, states] # # states vector is in the same order as x0 # res = sim.results() # # # In order to obtain internal paramters of the muscle # # Check SystemSimulation.py results_muscles() method for more information # res_muscles = sim.results_muscles() # length1 = np.array(map(lambda x: np.sqrt(o1**2. + j**2. + 2.*o1*j*np.sin(x)), res[:,1])) # muscle 1 length # length2 = np.array(map(lambda x: np.sqrt(o2**2. + j**2. + 2.*o2*j*np.sin(x)), res[:,1])) # muscle 2 length # # moment arm of muscles calculation # h1lambda = np.array(map(lambda x: np.abs(o1)*np.abs(j)*np.cos(x), res[:,1])) # h2lambda = np.array(map(lambda x: np.abs(o2)*np.abs(j)*np.cos(x), res[:,1])) # h1 = h1lambda/length1 # h2 = h2lambda/length2 # # Plotting the result for the current origins # ax1.plot(res[:, 1], length1) # ax2.plot(res[:, 1], h1) # if o1 == -0.1: # plt.figure('Muscles\' moment arm for insertions at {} and {}'.format(o1, o2)) # if j == -0.15: # temp = 0.0 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = ':') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = ':') # elif j == -0.2: # temp = 0.3 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = '--') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = '--') # elif j == -0.25: # temp = 0.7 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = '-.') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = '-.') # else: # temp = 1.0 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0)) # plt.plot(res[:, 1], h2, color=(temp, .5, 1.)) # plt.legend(legleg) # plt.xlabel('Pendulum position [rad]', fontsize = '18') # plt.ylabel('Muscle moment arm [m]', fontsize = '18') # plt.title('Muscles\' moment arm for insertions at {} and {}.\nRedish = muscle 1 (left), Blueish = muscle 2 (right)'.format(o1, o2), fontsize='26') # plt.grid('ON') # # ax1.legend(legendsertion) # ax2.legend(legendsertion) # ax1.set_xlabel('Position [rad]', fontsize='18') # ax2.set_xlabel('Position [rad]', fontsize='18') # ax1.set_ylabel('Muscle length [m]', fontsize='18') # Here we computed length 1 but muscle 2 has the same behaviour for identical params # ax2.set_ylabel('Muscle moment arm [m]', fontsize='18') # ax1.set_title('Muscle-tendon unit length in terms of pendulum position', fontsize='20') # ax2.set_title('Muscle\'s moment arm', fontsize='20') # ax1.grid() # ax2.grid() # ######################################## End OF 3a ######################################## ## ########################################## 3b ######################################## # # # Define a huge mass, such that the pendulum goes up to pi/2 and up t -pi/2 # P_params.mass = 1500. # # Defines 3 different origins and 3 different insertions for each muscle # origins1 = [-0.01, -0.05, -0.10, -0.15, -0.2] # origins2 = map(lambda x: -(x), origins1) # insertions1 = [-0.15, -0.20, -0.25, -0.30] # insertions2 = insertions1[:] # Just for visibility # legendsertion =np.array(['Insertion at -15 cm', 'Insertion at -20 cm', 'Insertion at -25 cm', 'Insertion at -30 cm']) # legleg = np.array(['Insertion at -15 cm', 'Insertion at -15 cm', 'Insertion at -20 cm', 'Insertion at -20 cm', 'Insertion at -25 cm', 'Insertion at -25 cm', 'Insertion at -30 cm', 'Insertion at -30 cm']) # cols = ('blue', 'red', 'olive', 'purple') ## length1 = np.array() # # for o1,o2 in zip(origins1, origins2): # fig, (ax1, ax2) = plt.subplots(1,2, sharex = True) # fig.suptitle('Origin of muscles - passive: o1 = {}, o2 = {}'.format(o1,o2), fontsize='26') # for i,j in enumerate(insertions1): # # Define Muscle Attachment points # m1_origin = np.array([o1, 0.0]) # Origin of Muscle 1 # m1_insertion = np.array([0.0, j]) # Insertion of Muscle 1 # # m2_origin = np.array([o2, 0.0]) # Origin of Muscle 2 # m2_insertion = np.array([0.0, j]) # Insertion of Muscle 2 # # # Attach the muscles # muscles.attach(np.array([m1_origin, m1_insertion]), # np.array([m2_origin, m2_insertion])) # # # Create a system with Pendulum and Muscles using the System Class # # Check System.py for more details on System class # sys = System() # Instantiate a new system # sys.add_pendulum_system(pendulum) # Add the pendulum model to the system # sys.add_muscle_system(muscles) # Add the muscle model to the system # # ##### Time ##### # # dt=0.01 # t_max = 1. # Maximum simulation time # time = np.arange(0., t_max, dt) # Time vector # # # # ##### Model Initial Conditions ##### # x0_P = np.array([np.pi/2. - 0.00001,0.]) # Pendulum initial condition # # # Muscle Model initial condition # x0_M = np.array([0., M1.l_CE, 0., M2.l_CE]) # # x0 = np.concatenate((x0_P, x0_M)) # System initial conditions # # ##### System Simulation ##### # # For more details on System Simulation check SystemSimulation.py # # SystemSimulation is used to initialize the system and integrate # # over time # # sim = SystemSimulation(sys) # Instantiate Simulation object # # # Add muscle activations to the simulation # # Here you can define your muscle activation vectors # # that are time dependent # # act1=np.ones((len(time),1))*0.00 # Passive muscles, unactivated. # act2=np.ones((len(time),1))*0.00 # # activations = np.hstack((act1, act2)) # # # Method to add the muscle activations to the simulation # # sim.add_muscle_activations(activations) # # # Simulate the system for given time # # sim.initalize_system(x0, time) # Initialize the system state # # # Integrate the system for the above initialized state and time # sim.simulate() # # # Obtain the states of the system after integration # # res is np.array [time, states] # # states vector is in the same order as x0 # res = sim.results() # # # In order to obtain internal paramters of the muscle # # Check SystemSimulation.py results_muscles() method for more information # res_muscles = sim.results_muscles() # length1 = np.array(map(lambda x: np.sqrt(o1**2. + j**2. + 2.*o1*j*np.sin(x)), res[:,1])) # muscle 1 length # length2 = np.array(map(lambda x: np.sqrt(o2**2. + j**2. + 2.*o2*j*np.sin(x)), res[:,1])) # muscle 2 length # # moment arm of muscles calculation # h1lambda = np.array(map(lambda x: np.abs(o1)*np.abs(j)*np.cos(x), res[:,1])) # h2lambda = np.array(map(lambda x: np.abs(o2)*np.abs(j)*np.cos(x), res[:,1])) # h1 = h1lambda/length1 # h2 = h2lambda/length2 # # Plotting the result for the current origins # ax1.plot(res[:, 1], length1) # ax2.plot(res[:, 1], h1) # if o1 == -0.1: # plt.figure('Muscles\' moment arm for insertions at {} and {} - passive'.format(o1, o2)) # if j == -0.15: # temp = 0.0 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = ':') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = ':') # elif j == -0.2: # temp = 0.3 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = '--') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = '--') # elif j == -0.25: # temp = 0.7 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0), linestyle = '-.') # plt.plot(res[:, 1], h2, color=(temp, .5, 1.), linestyle = '-.') # else: # temp = 1.0 # plt.plot(res[:, 1], h1, color=(1.0, temp, 0.0)) # plt.plot(res[:, 1], h2, color=(temp, .5, 1.)) # plt.legend(legleg) # plt.xlabel('Pendulum position [rad]', fontsize = '18') # plt.ylabel('Muscle moment arm [m]', fontsize = '18') # plt.title('Muscles\' moment arm for insertions at {} and {} - passive.\nRedish = muscle 1 (left), Blueish = muscle 2 (right)'.format(o1, o2), fontsize='26') # plt.grid('ON') # # ax1.legend(legendsertion) # ax2.legend(legendsertion) # ax1.set_xlabel('Position [rad]', fontsize='18') # ax2.set_xlabel('Position [rad]', fontsize='18') # ax1.set_ylabel('Muscle length [m]', fontsize='18') # Here we computed length 1 but muscle 2 has the same behaviour for identical params # ax2.set_ylabel('Muscle moment arm [m]', fontsize='18') # ax1.set_title('Muscle-tendon unit length in terms of pendulum position', fontsize='20') # ax2.set_title('Muscle\'s moment arm', fontsize='20') # ax1.grid() # ax2.grid() # ######################################## End OF 3b ######################################## ######################################## Part 3c,d,e,f ########################################## LC = True # Limit Cycle ON => LC True, Limit Cyle OFF => LC False if LC == True: P_params.mass = 10. else: P_params.mass = 100. # For point 3f, we changed max forces up here (line 55 and 57) # Define Muscle Attachment points m1_origin = np.array([-0.17, 0.0]) # Origin of Muscle 1 m1_insertion = np.array([0.0, -0.17]) # Insertion of Muscle 1 m2_origin = np.array([0.17, 0.0]) # Origin of Muscle 2 m2_insertion = np.array([0.0, -0.17]) # Insertion of Muscle 2 # Attach the muscles muscles.attach(np.array([m1_origin, m1_insertion]), np.array([m2_origin, m2_insertion])) # Create a system with Pendulum and Muscles using the System Class # Check System.py for more details on System class sys = System() # Instantiate a new system sys.add_pendulum_system(pendulum) # Add the pendulum model to the system sys.add_muscle_system(muscles) # Add the muscle model to the system ##### Time ##### dt = 0.01 t_max = 5. # Maximum simulation time time = np.arange(0., t_max, dt) # Time vector ##### Model Initial Conditions ##### x0_P = np.array([2 * np.pi / 6., 0.]) # Pendulum initial condition # Muscle Model initial condition x0_M = np.array([0., M1.l_CE, 0., M2.l_CE]) x0 = np.concatenate((x0_P, x0_M)) # System initial conditions ##### System Simulation ##### # For more details on System Simulation check SystemSimulation.py # SystemSimulation is used to initialize the system and integrate # over time sim = SystemSimulation(sys) # Instantiate Simulation object # Add muscle activations to the simulation # Here you can define your muscle activation vectors # that are time dependent act1 = np.arange(0., t_max, dt) act2 = np.arange(0., t_max, dt) if LC == True: act1 = (np.sin(2. * np.pi / t_max * 5. * act1) + 1.) * .5 # acts = time act2 = ( -np.sin(2. * np.pi / t_max * 5. * act2) + 1. ) * .5 # by increasing frequency, we don't let the time to gravity to make its office and contribute to the system's equilibrium, so the amplitude of the pendulum diminues. act1 = act1.reshape(len(act1), 1) act2 = act2.reshape(len(act2), 1) else: act1 = np.ones((len(time), 1)) * 0.25 act2 = np.ones((len(time), 1)) * 0.25 activations = np.hstack((act1, act2)) # Method to add the muscle activations to the simulation sim.add_muscle_activations(activations) # Simulate the system for given time sim.initalize_system(x0, time) # Initialize the system state # Integrate the system for the above initialized state and time sim.simulate() # Obtain the states of the system after integration # res is np.array [time, states] # states vector is in the same order as x0 res = sim.results() # In order to obtain internal paramters of the muscle # Check SystemSimulation.py results_muscles() method for more information res_muscles = sim.results_muscles() # Plotting the results plt.figure('Pendulum') # plt.title('Pendulum Phase') plt.title('Limit cycle behaviour for a max force of {} N'.format(M1.F_max), fontsize='22') # plt.plot(res[:, 1], res[:, 2]) plt.plot(time, res[:, 1]) # plt.xlabel('Position [rad]') # plt.ylabel('Velocity [rad.s]') plt.xlabel('Time [s]') plt.ylabel('Pendulum position [rad]') plt.grid() # Plotting activation legact = ("Muscle 1 - left", "Muscle 2 - right") plt.figure('Activations') # plt.title('Pendulum Phase') plt.title('Muscle activation patterns', fontsize='22') # plt.plot(res[:, 1], res[:, 2]) plt.plot(time, act1, color='red') plt.plot(time, act2, color='green') # plt.xlabel('Position [rad]') # plt.ylabel('Velocity [rad.s]') plt.xlabel('Time [s]') plt.ylabel('Activation [-]') plt.legend(legact) plt.grid() if DEFAULT["save_figures"] is False: plt.show() else: figures = plt.get_figlabels() biolog.debug("Saving figures:\n{}".format(figures)) for fig in figures: plt.figure(fig) save_figure(fig) plt.close(fig) # To animate the model, use the SystemAnimation class # Pass the res(states) and systems you wish to animate simulation = SystemAnimation(res, pendulum, muscles) # To start the animation simulation.animate()
def exercise4(): """ Main function to run for Exercise 3. Parameters ---------- None Returns ------- None """ # Define and Setup your pendulum model here # Check Pendulum.py for more details on Pendulum class P_params = PendulumParameters() # Instantiate pendulum parameters P_params.L = 0.5 # To change the default length of the pendulum P_params.mass = 1. # To change the default mass of the pendulum pendulum = Pendulum(P_params) # Instantiate Pendulum object #### CHECK OUT Pendulum.py to ADD PERTURBATIONS TO THE MODEL ##### biolog.info('Pendulum model initialized \n {}'.format( pendulum.parameters.showParameters())) # Define and Setup your pendulum model here # Check MuscleSytem.py for more details on MuscleSytem class M1_param = MuscleParameters() # Instantiate Muscle 1 parameters M1_param.f_max = 1500 # To change Muscle 1 max force M2_param = MuscleParameters() # Instantiate Muscle 2 parameters M2_param.f_max = 1500 # To change Muscle 2 max force M1 = Muscle(M1_param) # Instantiate Muscle 1 object M2 = Muscle(M2_param) # Instantiate Muscle 2 object # Use the MuscleSystem Class to define your muscles in the system muscles = MuscleSytem(M1, M2) # Instantiate Muscle System with two muscles biolog.info('Muscle system initialized \n {} \n {}'.format( M1.parameters.showParameters(), M2.parameters.showParameters())) # Define Muscle Attachment points m1_origin = np.array([-0.10, 0.0]) # Origin of Muscle 1 m1_insertion = np.array([0.0, -0.17]) # Insertion of Muscle 1 m2_origin = np.array([0.17, 0.0]) # Origin of Muscle 2 m2_insertion = np.array([0.0, -0.10]) # Insertion of Muscle 2 # Attach the muscles muscles.attach(np.array([m1_origin, m1_insertion]), np.array([m2_origin, m2_insertion])) ##### Neural Network ##### # The network consists of four neurons N_params = NetworkParameters() # Instantiate default network parameters N_params.D = 1. # To change a network parameter # Similarly to change w -> N_params.w = (4x4) array N_params.w=[[.0,-5.,-5.0,0.], [-5.,0.,.0,-5.0], [3.0,-1.0,.0,.0], [-1.0,3.,.0,.0]] N_params.b=[3.0,3.0,-3.0,-3.] N_params.tau=[.02,.02,.1,.1] biolog.info(N_params.showParameters()) # Create a new neural network with above parameters neural_network = NeuralSystem(N_params) # Create system of Pendulum, Muscles and neural network using SystemClass # Check System.py for more details on System class sys = System() # Instantiate a new system sys.add_pendulum_system(pendulum) # Add the pendulum model to the system sys.add_muscle_system(muscles) # Add the muscle model to the system # Add the neural network to the system sys.add_neural_system(neural_network) ##### Time ##### t_max = 20. # Maximum simulation time time = np.arange(0., t_max, 0.001) # Time vector ##### Model Initial Conditions ##### x0_P = np.array([0., 0.]) # Pendulum initial condition # Muscle Model initial condition x0_M = np.array([0., M1.l_CE, 0., M2.l_CE]) x0_N = np.array([-0.5, 1, 0.5, 1]) # Neural Network Initial Conditions x0 = np.concatenate((x0_P, x0_M, x0_N)) # System initial conditions ##### System Simulation ##### # For more details on System Simulation check SystemSimulation.py # SystemSimulation is used to initialize the system and integrate # over time sim = SystemSimulation(sys) # Instantiate Simulation object # Add external inputs to neural network heaviside=np.heaviside(time - np.mean(time),0.5) h4=np.zeros((len(time),4)) h4[:,0]=heaviside h4[:,1]=heaviside h4[:,2]=heaviside h4[:,3]=heaviside sim.add_external_inputs_to_network(h4) # Activates the external drive to its max (1) # sim.add_external_inputs_to_network(ext_in) sim.initalize_system(x0, time) # Initialize the system state # Integrate the system for the above initialized state and time sim.simulate() # Obtain the states of the system after integration # res is np.array [time, states] # states vector is in the same order as x0 res = sim.results() # In order to obtain internal paramters of the muscle # Check SystemSimulation.py results_muscles() method for more information res_muscles = sim.results_muscles() # Plotting the results plt.figure('Pendulum') plt.title('Pendulum Phase',fontsize = '18') plt.plot(res[:, 1], res[:, 2]) plt.xlabel('Position [rad]',fontsize = '16') plt.ylabel('Velocity [rad/s]', fontsize = '16') plt.grid() if DEFAULT["save_figures"] is False: plt.show() else: figures = plt.get_figlabels() biolog.debug("Saving figures:\n{}".format(figures)) for fig in figures: plt.figure(fig) save_figure(fig) plt.close(fig) # To animate the model, use the SystemAnimation class # Pass the res(states) and systems you wish to animate simulation = SystemAnimation(res, pendulum, muscles, neural_network) # To start the animation simulation.animate() # Plotting the results plt.figure('Time & Phase') plt.subplot(2,1,1) plt.plot(res[:,0],res[:,1]) # plt.xlabel('Time [s]') plt.grid() plt.ylabel('Pos. [rad]',fontsize = '16') plt.title('Position',fontsize = '18') plt.subplot(2,1,2) plt.title('Velocity',fontsize = '18') plt.plot(res[:,0],res[:,2]) plt.xlabel('Time [s]',fontsize = '16') plt.ylabel('Vel [rad/s]',fontsize = '16') plt.grid() plt.show()
def exercise2a(): """ Exercise 2a The goal of this exercise is to understand the relationship between muscle length and tension. Here you will re-create the isometric muscle contraction experiment. To do so, you will have to keep the muscle at a constant length and observe the force while stimulating the muscle at a constant activation.""" font1 = {'family': 'normal', 'weight': 'bold', 'size': 18} font2 = {'family': 'normal', 'weight': 'normal', 'size': 12} # Definition of muscles parameters = MuscleParameters() biolog.warning("Loading default muscle parameters") biolog.info(parameters.showParameters()) # Create muscle object muscle = Muscle.Muscle(parameters) # Isometric contraction, varying the activation between [0-1] isoM = isometric_contraction(muscle) legend1 = ("Passive Force", "Active Force", "Total Force") plt.figure('Forces vs Length') plt.title("Force-Length relationship") plt.plot(isoM[0], isoM[1]) plt.plot(isoM[0], isoM[2]) plt.plot(isoM[0], isoM[3]) plt.xlabel('Total length of the contractile element [m]') plt.ylabel('Force [N]') plt.legend(legend1) plt.grid() save_figure('F_vs_length') # Stabilisation has been verified for integrating the muscle for 0.2s. However, to be sure, we integrated it for 0.25s # plt.figure("Stab??") # plt.plot(isoM[4],isoM[5]) # Effect of varying l_opt (fiber length) NOT SURE) muscleS = Muscle.Muscle(parameters) # 'short' muscle muscleS.l_opt = 0.05 # short fiber length muscleL = Muscle.Muscle(parameters) # 'long' muscle muscleL.l_opt = 0.25 # long fiber length muscleXL = Muscle.Muscle(parameters) # 'extra long' muscle muscleXL.l_opt = 0.50 # extra long fiber length isoS = isometric_contraction(muscleS, stretch=np.arange(-0.25, 0.25, 0.001), activation=0.25) isoL = isometric_contraction(muscleL, stretch=np.arange(-0.25, 0.25, 0.001), activation=0.25) isoXL = isometric_contraction(muscleXL, stretch=np.arange(-0.25, 0.25, 0.001), activation=0.25) legendS = ("Short fibers: {} [m], \n max_total_length: {} [m]".format( muscleS.l_opt, np.max(isoS[0])), "Long fibers: {} [m], \n max_total_length: {} [m]".format( muscleL.l_opt, np.max(isoL[0])), "Extra Long fibers: {} [m], \n max_total_length: {} [m]".format( muscleXL.l_opt, np.max(isoXL[0]))) plt.figure( 'Short, Long and Extra Long muscle fibers (l_opt) active force vs length' ) plt.title( "Stretching of -25% to +25% and activation of 25% for each muscle type" ) plt.plot((isoS[0]) / (np.max(isoS[0])) * 100, isoS[2]) # we plot the percentage of total length plt.plot((isoL[0]) / (np.max(isoL[0])) * 100, isoL[2]) plt.plot((isoXL[0]) / (np.max(isoXL[0])) * 100, isoXL[2]) plt.xlabel( 'Percentage of maximal total length (l_CE + stretching) of the contractile element [m]' ) plt.ylabel('Active Force [N]') plt.legend(legendS) plt.grid() plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='black') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('short_vs_long_vs_xtraLong') legendSx = ("Short fibers: {} [m], \n max_total_length: {} [m]".format( muscleS.l_opt, np.max(isoS[0])), "Long fibers: {} [m], \n max_total_length: {} [m]".format( muscleL.l_opt, np.max(isoL[0]))) plt.figure('Short and Long muscle fibers (l_opt) active force vs length') plt.plot(isoS[0], isoS[2]) plt.plot(isoL[0], isoL[2]) plt.xlabel('Length (l_CE + stretching) of the contractile element [m]') plt.ylabel('Active Force [N]') plt.legend(legendSx) plt.grid() plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='black') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('short_vs_Long') # Effect of varying activation (stimulation) activations = np.arange(0.0, 1.05, 0.05) max_F_Diff = np.zeros( np.size(activations) ) # vectors to assess the evolution of the difference of the maximas of passive and active force ratio = np.zeros( np.size(activations) ) # to implement the total_force/total_length ratio for every activation value plt.figure('Active force vs Length with varying activation time') legend2 = list() #print(activations) for i, a in enumerate(activations): muscle1 = Muscle.Muscle(parameters) #print("Activation = {} [s]".format(a)) iso = isometric_contraction(muscle1, activation=a) #print("lapin \n {}".format(iso[2])) legend2.append("Activation = {} [-]".format(a)) plt.plot(iso[0], iso[2]) # plot for active force # plt.plot(iso[0],iso[3]) # plot for total force max_F_Diff[i] = np.abs(np.max(iso[1]) - np.max(iso[2])) ratio[i] = ((np.mean(iso[3])) / (np.mean(iso[0]))) / 1000 plt.xlabel('Total length of the contractile element [m]') plt.ylabel('Force [N]') plt.legend(legend2) plt.grid() save_figure('F_vs_length') # Force difference figure plt.figure( 'Difference between the max of the passive and the active force') plt.plot(activations, max_F_Diff, color='black', marker='v', linestyle='dashed', linewidth=1, markersize=5) plt.xlabel('Activation value [s]') plt.ylabel('Force Difference [N]') plt.legend(['$\Delta$']) plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='red') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('delta_plot') # Force/length ratio plt.figure( 'Ratio between the total force (active + passive) and the total length of the contractile element' ) plt.plot(activations, ratio, color='black', marker='v', linestyle='dashed', linewidth=1, markersize=5) plt.xlabel('Activation value [-]') plt.ylabel('(Total_force/total_length)/1000 [N]/[m]') plt.legend(['$Ratio$']) plt.minorticks_on() plt.grid(which='major', linestyle='-', linewidth='0.5', color='red') plt.grid(which='minor', linestyle=':', linewidth='0.5', color='black') save_figure('ratio_plot') biolog.info("Isometric muscle contraction implemented") """ Example for plotting graphs using matplotlib. """
def isotonic_contraction(muscle, load=np.arange(1., 330., 10), muscle_parameters=MuscleParameters(), mass_parameters=MassParameters(), activation=1.0): """ This function implements the isotonic contraction of the muscle. Parameters: ----------- muscle : <Muscle> Instance of Muscle class load : list/array External load to be applied on the muscle. It is the mass suspended by the muscle muscle_parameters : MuscleParameters Muscle paramters instance mass_paramters : MassParameters Mass parameters instance Since the muscle model is complex and sensitive to integration, use the following example as a hint to complete your implementation. Example: -------- >>> for load_ in load: >>> # Iterate over the different muscle load values >>> mass_parameters.mass = load_ # Set the mass applied on the muscle >>> state = np.copy(x0) # Reset the state for next iteration >>> for time_ in time: >>> # Integrate for 0.2 seconds >>> # Integration before the quick release >>> res = muscle_integrate(muscle, state[0], activation=1.0, dt) >>> for time_ in time: >>> # Quick Release experiment >>> # Integrate the mass system by applying the muscle force on to it for a time step dt >>> mass_res = odeint(mass_integration, state, [ >>> time_, time_ + dt], args=(muscle.force, load_, mass_parameters)) >>> state[0] = mass_res[-1, 0] # Update state with final postion of mass >>> state[1] = mass_res[-1, 1] # Update state with final position of velocity >>> # Now update the muscle model with new position of mass >>> res = muscle_integrate(muscle, state[0], 1.0, dt) >>> # Save the relevant data >>> res_[id] = res['v_CE'] >>> if(res['l_MTC'] > muscle_parameters.l_opt + muscle_parameters.l_slack): >>> velocity_ce[idx] = min(res_[:]) >>> else: >>> velocity_ce[idx] = max(res_[:]) """ load = np.array(load) biolog.info('Exercise 2b isotonic contraction running') # Time settings t_start = 0.0 # Start time t_stop = 0.1 # Stop time dt = 0.001 # Time step timesteps = np.arange(t_start, t_stop, dt) timecharge = np.arange(0.0, 2.5, dt) x0 = np.array([0.0, 0.0]) # Initial state of the muscle # Empty vectors for further isotonic representations F = np.zeros(np.size(load)) # force V = np.zeros(np.size( load)) # will contain contractile element's velocity for each loads temp = np.zeros(np.size(timesteps)) for k, l in enumerate(load): mass_parameters.mass = l # Set the mass applied on the muscle state = np.copy(x0) # reset the state for next iteration print("The current load is: {}\n\n{}\n\n".format( mass_parameters.mass, "pump-it")) for t in timecharge: effect = muscle_integrate(muscle, state[0], activation, dt=dt) # print(effect['activeForce']) for j, t in enumerate(timesteps): mass_res = odeint(mass_integration, state, [t, t + dt], args=(muscle.force, mass_parameters)) state[0] = mass_res[-1, 0] # Update state with final postion of mass state[1] = mass_res[ -1, 1] # Update state with final position of velocity effect = muscle_integrate(muscle, state[0], activation, dt) temp[j] = effect['v_CE'] # print(effect['force']) # print("The velocity is : {}".format(temp[j])) # print("LMTC TAMERE: {}".format(effect['l_MTC'])) # print("\n\n {} \n\n {}".format(effect['l_MTC'],(effect['l_MTC'] > muscle_parameters.l_opt + muscle_parameters.l_slack))) if (effect['l_MTC'] > muscle_parameters.l_opt + muscle_parameters.l_slack): V[k] = min(temp[:]) else: V[k] = max(temp[:]) F[k] = effect['force'] # print(V) # print(k,F) return V, F # V = isoK[0], F = isoK[1]