%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%22marimo%3E%3D0.23.9%22%2C%20%22numpy%3E%3D2.0%22%2C%20%22matplotlib%3E%3D3.9%22%2C%20%22scipy%3E%3D1.14%22%2C%20%22urllib3%3E%3D2.2%22%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.25.2%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Musculoskeletal%20modeling%20and%20simulation%0A%0A%20%20%20%20%3E%20Marcos%20Duarte%2C%20Renato%20Watanabe%3Cbr%3E%0A%20%20%20%20%3E%20%5BLaboratory%20of%20Biomechanics%20and%20Motor%20Control%5D(https%3A%2F%2Fbmclab.pesquisa.ufabc.edu.br%2F)%3Cbr%3E%0A%20%20%20%20%3E%20Federal%20University%20of%20ABC%2C%20Brazil%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20How%20to%20use%20this%20tutorial%0A%0A%20%20%20%20This%20notebook%20is%20a%20guided%20study%20session%2C%20and%20it%20is%20the%20third%20step%20of%20a%20sequence%3A%0A%0A%20%20%20%201.%20%5BMuscle%20modeling%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_modeling.py)%20built%20a%20Hill-type%20muscle%20out%20of%20its%20force-length%2C%20force-velocity%2C%20and%20activation%20relationships.%0A%20%20%20%202.%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%20put%20that%20muscle%20in%20motion%2C%20but%20the%20muscle-tendon%20length%20%24L_%7BMT%7D%24%20was%20*prescribed*%3A%20at%20every%20instant%20we%20told%20the%20muscle%20how%20long%20to%20be.%0A%20%20%20%203.%20This%20notebook%20removes%20that%20crutch.%20The%20muscle%20now%20pulls%20on%20a%20real%20limb%3A%20its%20force%20accelerates%20the%20leg%2C%20the%20leg%20rotates%2C%20the%20rotation%20changes%20%24L_%7BMT%7D%24%2C%20and%20the%20new%20length%20changes%20the%20force.%20Nothing%20about%20the%20movement%20is%20dictated%20in%20advance.%0A%0A%20%20%20%20That%20feedback%20loop%20is%20what%20turns%20muscle%20simulation%20into%20*musculoskeletal*%20simulation.%20The%20muscle%20and%20the%20skeleton%20are%20now%20two%20dynamical%20systems%20wired%20into%20each%20other%2C%20and%20we%20have%20to%20integrate%20them%20together.%0A%0A%20%20%20%20Read%20a%20short%20explanation%2C%20predict%20what%20the%20leg%20and%20the%20muscle%20should%20do%2C%20run%20the%20cell%2C%20and%20then%20use%20the%20plot%20to%20answer%20the%20challenge%20questions.%20Keep%20a%20scratchpad%20nearby%20and%20write%20your%20prediction%20*before*%20you%20reveal%20each%20plot.%0A%0A%20%20%20%20You%20do%20not%20need%20to%20finish%20every%20challenge%20on%20the%20first%20pass.%20Run%20the%20cells%20in%20order%20first%3B%20then%20come%20back%20and%20change%20one%20parameter%20at%20a%20time.%20The%20goal%20is%20not%20to%20make%20the%20code%20run%20%E2%80%94%20it%20already%20runs.%20The%20goal%20is%20to%20connect%20the%20free-body%20diagram%2C%20the%20coupled%20differential%20equations%2C%20and%20the%20movement%20you%20see%20in%20the%20plots.%0A%0A%20%20%20%20**Challenge%200.**%20Before%20you%20begin%2C%20picture%20the%20task%20we%20are%20about%20to%20simulate%3A%20a%20seated%20person%20with%20the%20knee%20flexed%20at%20%2490%5Eo%24%20suddenly%20activates%20the%20quadriceps%20fully%2C%20and%20the%20leg%20swings%20up%20into%20extension.%20Predict%20three%20things%20and%20write%20them%20down%3A%0A%0A%20%20%20%201.%20As%20the%20knee%20extends%2C%20does%20the%20quadriceps%20muscle-tendon%20unit%20shorten%20or%20lengthen%3F%0A%20%20%20%202.%20Gravity%20pulls%20the%20leg%20back%20down.%20Early%20in%20the%20movement%20(knee%20near%20%2490%5Eo%24)%2C%20does%20gravity%20help%20or%20oppose%20the%20extension%3F%0A%20%20%20%203.%20The%20muscle%20shortens%20*while*%20producing%20force.%20From%20the%20force-velocity%20relationship%20you%20met%20in%20%5BMuscle%20modeling%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_modeling.py)%2C%20should%20the%20force%20rise%20or%20fall%20as%20the%20shortening%20speeds%20up%3F%0A%0A%20%20%20%20Connect%20the%20existing%20muscle%20model%20to%20a%20joint%20equation.%20Now%20joint%20angle%20affects%20musculotendon%20length%2C%20and%20muscle%20force%20affects%20joint%20acceleration.%20Track%20this%20feedback%20through%20the%20state%20vector%2C%20then%20compare%20the%20constant%20and%20measured%20moment%20arms%20without%20mixing%20their%20geometry.%0A%0A%20%20%20%20Try%20the%20distributed%20**Exercises**%20before%20opening%20their%20collapsed%20worked%20solutions.%20Then%20use%20the%20**Checkpoint%20questions**%20and%20attempt%20the%20**Problems**%20independently%3B%20their%20panels%20contain%20final%20answers%20only.%20Predict%20the%20effect%20of%20a%20parameter%20change%20before%20running%20it%2C%20and%20check%20units%20and%20limiting%20cases.%0A%0A%20%20%20%20**Opening%20challenge.**%20A%20muscle%20pulls%20on%20a%20freely%20moving%20shank.%20Why%20can%20doubling%20its%20force%20fail%20to%20double%20the%20final%20knee%20angle%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Python%20setup%0A%0A%20%20%20%20The%20dependency%20declaration%20at%20the%20top%20of%20this%20file%20lists%20the%20packages%20used%20by%20this%20guide.%20Marimo%20runs%20cells%20in%20dependency%20order.%20Run%20the%20notebook%20in%20an%20editor%20to%20use%20its%20displays%20and%20controls%3B%20the%20computational%20examples%20below%20explain%20their%20inputs%20before%20using%20them.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20We%20will%20now%20simulate%20the%20dynamics%20of%20the%20musculoskeletal%20system%20with%20muscle%20dynamics.%20You%20should%20have%20read%20%5BMuscle%20modeling%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_modeling.py)%20and%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%20first.%20In%20addition%2C%20chapter%204%20of%20Nigg%20and%20Herzog%20(2006)%20is%20a%20good%20introduction%20to%20this%20topic.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Forward%20and%20inverse%20dynamics%0A%0A%20%20%20%20In%20a%20typical%20movement%20analysis%20using%20inverse%20dynamics%2C%20we%20would%20measure%20the%20leg%20and%20thigh%20positions%2C%20calculate%20the%20leg%20and%20knee%20linear%20and%20angular%20position%20and%20acceleration%2C%20and%20then%20estimate%20the%20net%20moment%20of%20force%20at%20the%20knee%20joint%20and%20the%20force%20of%20the%20quadriceps%20muscle.%20Now%20we%20want%20to%20do%20the%20opposite%3A%20perform%20*forward*%20dynamics%2C%20where%20muscle%20force%20is%20the%20input%20and%20the%20movement%20of%20the%20leg%20is%20the%20output.%20The%20figure%20below%20compares%20the%20two%20approaches.%0A%0A%20%20%20%20%3Cimg%20src%3D%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Fimages%2FInvDirDyn.png%22%20width%3D%22600%22%20alt%3D%22Forward%20and%20inverse%20dynamics.%22%20%2F%3E%0A%0A%20%20%20%20*Figure.%20Inverse%20dynamics%20and%20Forward%20(or%20Direct)%20dynamics%20approaches%20for%20movement%20analysis%20(adapted%20from%20Zajac%20and%20Gordon%2C%201989).*%0A%0A%20%20%20%20**Guiding%20questions%201.**%0A%0A%20%20%20%201.%20Inverse%20dynamics%20starts%20from%20measured%20movement%20and%20works%20backwards%20to%20forces.%20Forward%20dynamics%20starts%20from%20forces%20and%20works%20forwards%20to%20movement.%20Which%20one%20can%20predict%20a%20movement%20that%20has%20*never%20been%20measured*%2C%20and%20why%20does%20that%20matter%20for%20answering%20questions%20such%20as%20%22what%20would%20happen%20if%20this%20muscle%20were%20weaker%3F%22%0A%20%20%20%202.%20Inverse%20dynamics%20gives%20you%20the%20*net*%20joint%20moment.%20Why%20can%20it%20not%20tell%20you%2C%20on%20its%20own%2C%20how%20much%20of%20that%20moment%20came%20from%20the%20quadriceps%20and%20how%20much%20from%20a%20co-contracting%20hamstring%3F%0A%20%20%20%203.%20Forward%20dynamics%20needs%20an%20initial%20state%20(position%20and%20velocity)%20and%20it%20needs%20to%20be%20integrated%20in%20time.%20Inverse%20dynamics%20needs%20neither.%20What%20does%20that%20tell%20you%20about%20which%20of%20the%20two%20accumulates%20numerical%20error%20over%20a%20long%20trial%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Exercise%201%20%E2%80%94%20Convert%20force%20to%20torque.**%20A%20tendon%20force%20of%20800%20N%20acts%20with%20a%200.04%20m%20knee%20moment%20arm.%20Find%20its%20torque.%20If%20the%20joint%20moves%20at%202%20rad%2Fs%2C%20what%20is%20its%20joint%20power%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%201%0A%0A%20%20%20%20%24%5Ctau%3DrF%3D32%24%20N%20m%20and%20%24P%3D%5Ctau%5Cdot%5Ctheta%3D64%24%20W%20for%20matching%20positive%20signs.%20The%20moment%20arm%20also%20controls%20the%20musculotendon%20length%20rate%2C%20so%20changing%20it%20alters%20both%20torque%20and%20fiber%20dynamics.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20One-link%20system%20with%20one%20DoF%20and%20one%20muscle%0A%0A%20%20%20%20Let's%20start%20with%20the%20simplest%20case%2C%20a%20one-link%20rigid%20body%20with%20one%20degree%20of%20freedom%20and%20one%20muscle.%0A%0A%20%20%20%20Let's%20simulate%20the%20extension%20movement%20of%20the%20knee.%20This%20problem%20is%20based%20on%20an%20example%20from%20chapter%204%20of%20Nigg%20and%20Herzog%20(2006).%20We%20will%20model%20the%20task%20as%20a%20planar%20movement%2C%20the%20leg%20and%20foot%20as%20one%20rigid%20segment%20and%20the%20rest%20of%20the%20body%20as%20fixed%2C%20the%20knee%20as%20a%20revolute%20joint%20with%20a%20fixed%20axis%20of%20rotation%20and%20one%20degree%20of%20freedom%2C%20and%20only%20one%20muscle%20as%20knee%20extensor%2C%20as%20illustrated%20in%20the%20figure%20below.%0A%0A%20%20%20%20%3Cimg%20src%3D%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Fimages%2Fknee.png%22%20width%3D%22500%22%20alt%3D%22Planar%20knee%20model.%22%20%2F%3E%0A%0A%20%20%20%20*Figure.%20Planar%20model%20of%20the%20knee%20with%20one%20degree%20of%20freedom%2C%20one%20extensor%20muscle%2C%20and%20the%20corresponding%20free-body%20diagram%20for%20the%20leg.%20%24%5Ctheta%24%3A%20knee%20angle%20with%20the%20horizontal%3B%20%24F_M%24%3A%20force%20of%20the%20quadriceps%20muscle%3B%20%24F_J%24%3A%20force%20at%20the%20knee%20joint%3B%20%24r_M%24%3A%20moment%20arm%20of%20the%20quadriceps%3B%20%24r_%7Bcm%7D%24%3A%20distance%20from%20the%20knee%20joint%20to%20the%20center%20of%20mass%20of%20the%20leg%2Bfoot%20segment%3B%20%24mg%24%3A%20weight%20of%20the%20leg%2Bfoot%3B%20%24L_%7BMT0%7D%24%3A%20muscle-tendon%20unit%20length%20at%20%24%5Ctheta%20%3D%2090%5Eo%24.*%0A%0A%20%20%20%20From%20the%20figure%20above%2C%20the%20Newton-Euler%20equation%20for%20the%20sum%20of%20moments%20of%20force%20around%20the%20knee%20joint%20is%3A%0A%0A%20%20%20%20%24r_M%20F_M%20%2B%20r_%7Bcm%7D%5Ccos(%5Ctheta)mg%20%3D%20I%5Cdfrac%7B%5Cmathrm%7Bd%7D%5E2%20%5Ctheta%7D%7B%5Cmathrm%7Bd%7Dt%5E2%7D%24%0A%0A%20%20%20%20where%20%24I%24%20is%20the%20rotational%20inertia%20of%20the%20leg%2Bfoot%20segment%20around%20the%20knee%20joint.%0A%0A%20%20%20%20In%20our%20convention%2C%20the%20first%20term%20on%20the%20left-hand%20side%20is%20a%20positive%20(extensor)%20moment%20of%20force%2C%20and%20the%20second%20term%20becomes%20a%20negative%20(flexor)%20moment%20of%20force%20when%20%24%5Ctheta%24%20is%20greater%20than%20%2490%5Eo%24.%20The%20Newton-Euler%20equation%20above%20is%20a%20second-order%20nonlinear%20differential%20equation.%0A%0A%20%20%20%20**Guiding%20questions%202.**%0A%0A%20%20%20%201.%20The%20gravitational%20term%20is%20%24r_%7Bcm%7D%5Ccos(%5Ctheta)mg%24.%20Evaluate%20%24%5Ccos%5Ctheta%24%20at%20%24%5Ctheta%20%3D%2090%5Eo%24%2C%20at%20%24%5Ctheta%20%3D%20135%5Eo%24%2C%20and%20at%20%24%5Ctheta%20%3D%20180%5Eo%24.%20At%20which%20of%20these%20knee%20angles%20does%20gravity%20resist%20the%20extension%20most%20strongly%2C%20and%20where%20does%20it%20do%20nothing%20at%20all%3F%0A%20%20%20%202.%20The%20muscle%20term%20is%20%24r_M%20F_M%24.%20Two%20muscles%20could%20produce%20the%20same%20joint%20moment%20with%20very%20different%20forces.%20What%20would%20have%20to%20differ%20between%20them%3F%0A%20%20%20%203.%20The%20equation%20is%20called%20*nonlinear*.%20Point%20to%20the%20term%20that%20makes%20it%20so.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20length%20of%20the%20quadriceps%20muscle-tendon%20unit%20depends%20on%20the%20knee%20angle%3A%0A%0A%20%20%20%20%24L_%7BMT%7D%20%3D%20L_%7BMT0%7D%20-%20r_M%20(%5Ctheta%20-%20%5Cpi%2F2)%24%0A%0A%20%20%20%20Look%20carefully%20at%20what%20these%20equations%20imply.%20If%20we%20excite%20the%20muscle%2C%20it%20generates%20force%3B%20that%20force%20is%20transmitted%20to%20the%20leg%20segment%20and%20accelerates%20it%3B%20the%20rotation%20changes%20the%20muscle-tendon%20length%20and%20hence%20the%20muscle%20velocity%3B%20and%20those%20in%20turn%20change%20the%20muscle%20force.%20We%20already%20saw%20in%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%20that%20muscle%20force%20is%20related%20to%20muscle%20length%20and%20velocity%20through%20a%20first-order%20ODE.%20So%20muscle%20force%20and%20joint%20angle%20are%20described%20by%20two%20*coupled*%20ODEs%2C%20and%20neither%20can%20be%20solved%20without%20the%20other.%0A%0A%20%20%20%20Mathematically%2C%20the%20musculoskeletal%20system%20we%20modeled%20has%20as%20state%20variables%20%24L_M%24%2C%20%24%5Ctheta%24%2C%20and%20%24%5Comega%20%3D%20%5Cdot%7B%5Ctheta%7D%24.%20(Muscle%20activation%20%24a%24%20could%20also%20be%20a%20state%20variable%20in%20other%20situations%2C%20but%20not%20in%20this%20problem%2C%20where%20we%20hold%20it%20fixed%20as%20an%20input.)%0A%0A%20%20%20%20Let's%20rewrite%20the%20Newton-Euler%20equation%20in%20a%20clearer%20form%3A%0A%0A%20%20%20%20%24%5Cdfrac%7B%5Cmathrm%7Bd%7D%5E2%20%5Ctheta%7D%7B%5Cmathrm%7Bd%7Dt%5E2%7D%20%3D%20I%5E%7B-1%7D%20%5Cleft%5B%20r_M%20F_M%20%2B%20r_%7Bcm%7D%5Ccos(%5Ctheta)mg%20%5Cright%5D%24%0A%0A%20%20%20%20%24F_M%24%20is%20determined%20once%20%24L_M%24%20is%20known%2C%20which%20according%20to%20the%20muscle%20model%20we%20used%20in%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%20is%20the%20solution%20of%20the%20following%20first-order%20ODE%3A%0A%0A%20%20%20%20%24%5Cdfrac%7B%5Cmathrm%7Bd%7D%20L_M%7D%7B%5Cmathrm%7Bd%7Dt%7D%20%3D%20f_v%5E%7B-1%7D%5Cleft(%5Cdfrac%7BF_%7BSE%7D(L_%7BMT%7D-L_M%5Ccos%5Calpha)%2F%5Ccos%5Calpha%20-%20F_%7BPE%7D(L_M)%7D%7Ba%20f_l(L_M)%7D%5Cright)%24%0A%0A%20%20%20%20and%3A%0A%0A%20%20%20%20%24F_M%20%3D%20F_%7BSE%7D(L_%7BMT%7D-L_M%5Ccos%5Calpha)%2F%5Ccos%5Calpha%24%0A%0A%20%20%20%20To%20apply%20numerical%20methods%20to%20these%20coupled%20equations%2C%20we%20have%20to%20express%20them%20as%20a%20system%20of%20*first-order*%20differential%20equations%20(see%20%5BOrdinary%20differential%20equation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fordinary_differential_equation.py)).%20The%20trick%20is%20to%20promote%20the%20angular%20velocity%20%24%5Comega%24%20to%20a%20state%20variable%20of%20its%20own%2C%20which%20turns%20one%20second-order%20equation%20into%20two%20first-order%20ones%3A%0A%0A%20%20%20%20%24%5Cleft%5C%7B%0A%20%20%20%20%5Cbegin%7Barray%7D%7Bl%20l%7D%0A%20%20%20%20%5Cdfrac%7B%5Cmathrm%7Bd%7D%20L_M%7D%7B%5Cmathrm%7Bd%7Dt%7D%20%3D%20f%5E%7B-1%7D_%7Bv%7D(L_M%2C%20L_%7BMT%7D(%5Ctheta))%2C%20%5Cquad%20%26%20L_M(t_0)%20%3D%20L_%7BM0%7D%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cdfrac%7B%5Cmathrm%7Bd%7D%20%5Ctheta%7D%7B%5Cmathrm%7Bd%7Dt%7D%20%3D%20%5Comega%2C%20%5Cquad%20%26%20%5Ctheta(t_0)%20%3D%20%5Ctheta_0%0A%20%20%20%20%5C%5C%0A%20%20%20%20%5Cdfrac%7B%5Cmathrm%7Bd%7D%20%5Comega%7D%7B%5Cmathrm%7Bd%7Dt%7D%20%3D%20I%5E%7B-1%7D%20%5Cleft%5B%20r_M%20F_M(L_M%2C%20%5Ctheta)%20%2B%20r_%7Bcm%7D%5Ccos(%5Ctheta)mg%20%5Cright%5D%2C%20%5Cquad%20%26%20%5Comega(t_0)%20%3D%20%5Comega_0%0A%20%20%20%20%5Cend%7Barray%7D%0A%20%20%20%20%5Cright.%24%0A%0A%20%20%20%20**Guiding%20questions%203.**%0A%0A%20%20%20%201.%20In%20%24L_%7BMT%7D%20%3D%20L_%7BMT0%7D%20-%20r_M(%5Ctheta%20-%20%5Cpi%2F2)%24%2C%20the%20sign%20in%20front%20of%20%24r_M%24%20is%20negative.%20Confirm%20that%20this%20means%20the%20quadriceps%20*shortens*%20as%20the%20knee%20extends%20(%24%5Ctheta%24%20grows%20past%20%24%5Cpi%2F2%24).%20Does%20that%20agree%20with%20the%20prediction%20you%20wrote%20for%20Challenge%200%3F%0A%20%20%20%202.%20The%20three%20equations%20are%20coupled.%20Find%20the%20term%20in%20the%20third%20equation%20that%20depends%20on%20the%20first%20equation's%20state%2C%20and%20the%20term%20in%20the%20first%20equation%20that%20depends%20on%20the%20second%20equation's%20state.%20That%20pair%20of%20arrows%20is%20the%20feedback%20loop.%0A%20%20%20%203.%20Why%20is%20%24%5Cmathrm%7Bd%7D%5Ctheta%2F%5Cmathrm%7Bd%7Dt%20%3D%20%5Comega%24%20not%20a%20physical%20statement%20about%20muscles%20at%20all%3F%20What%20is%20it%20doing%20in%20the%20system%3F%0A%0A%20%20%20%20**Challenge%201.**%20In%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%2C%20%24L_%7BMT%7D%24%20was%20a%20function%20you%20wrote%20by%20hand%2C%20%60lmt_eq(t%2C%20lmt0)%60%20%E2%80%94%20a%20function%20of%20*time*.%20Here%2C%20%24L_%7BMT%7D%24%20is%20a%20function%20of%20%24%5Ctheta%24%2C%20and%20%24%5Ctheta%24%20is%20a%20state%20the%20solver%20is%20computing%20as%20it%20goes.%20Explain%20in%20one%20sentence%20why%20this%20makes%20the%20problem%20qualitatively%20harder%20than%20the%20previous%20notebook%2C%20even%20though%20the%20muscle%20model%20is%20identical.%0A%0A%20%20%20%20Let's%20solve%20this%20problem%20in%20Python.%20First%2C%20let's%20import%20the%20necessary%20Python%20libraries%20and%20customize%20the%20environment%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20import%20matplotlib%0A%20%20%20%20from%20scipy.integrate%20import%20odeint%0A%20%20%20%20from%20scipy%20import%20interpolate%0A%0A%20%20%20%20matplotlib.rcParams%5B%22lines.linewidth%22%5D%20%3D%202%0A%20%20%20%20matplotlib.rcParams%5B%22font.size%22%5D%20%3D%2012%0A%20%20%20%20matplotlib.rcParams%5B%22lines.markersize%22%5D%20%3D%204%0A%20%20%20%20matplotlib.rc(%22axes%22%2C%20grid%3DTrue%2C%20labelsize%3D12%2C%20titlesize%3D13%2C%20ymargin%3D0.01)%0A%20%20%20%20matplotlib.rc(%22legend%22%2C%20numpoints%3D1%2C%20fontsize%3D10)%0A%20%20%20%20return%20np%2C%20odeint%2C%20plt%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20The%20muscle%20model%20itself%20is%20the%20class%20%60Thelen2003%60%2C%20the%20same%20one%20used%20in%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py).%20Instead%20of%20importing%20it%20from%20an%20external%20%60muscles.py%60%20file%2C%20we%20define%20it%20at%20the%20end%20of%20this%20notebook%2C%20so%20the%20notebook%20is%20self-contained%20and%20runs%20anywhere%2C%20including%20in%20the%20browser%20at%20%5Bmarimo.app%5D(https%3A%2F%2Fmarimo.app%2F).%0A%0A%20%20%20%20Same%20for%20its%20parameters%20and%20initial%20states%2C%20which%20we%20write%20directly%20as%20Python%20dictionaries.%20These%20are%20the%20values%20from%20the%20exercise%20in%20chapter%204%20of%20Nigg%20and%20Herzog%20(2006)%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20parameters%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22id%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%22u_max%22%3A%201.0%2C%20%20%23%20maximum%20value%20for%20muscle%20excitation%0A%20%20%20%20%20%20%20%20%22u_min%22%3A%200.01%2C%20%20%23%20minimum%20value%20for%20muscle%20excitation%0A%20%20%20%20%20%20%20%20%22t_act%22%3A%200.015%2C%20%20%23%20activation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%22t_deact%22%3A%200.050%2C%20%20%23%20deactivation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%22lmopt%22%3A%200.093%2C%20%20%23%20optimal%20CE%20length%0A%20%20%20%20%20%20%20%20%22alpha0%22%3A%200.0%2C%20%20%23%20pennation%20angle%20at%20rest%0A%20%20%20%20%20%20%20%20%22fm0%22%3A%207400.0%2C%20%20%23%20maximum%20isometric%20muscle%20force%0A%20%20%20%20%20%20%20%20%22gammal%22%3A%200.45%2C%20%20%23%20CE%20force-length%20shape%20factor%0A%20%20%20%20%20%20%20%20%22kpe%22%3A%205.0%2C%20%20%23%20PE%20exponential%20shape%20factor%0A%20%20%20%20%20%20%20%20%22epsm0%22%3A%200.6%2C%20%20%23%20PE%20passive%20muscle%20strain%20due%20to%20maximum%20isometric%20force%0A%20%20%20%20%20%20%20%20%22vmmax%22%3A%2010.0%2C%20%20%23%20CE%20force-velocity%20maximum%20velocity%20(concentric)%0A%20%20%20%20%20%20%20%20%22fmlen%22%3A%201.4%2C%20%20%23%20CE%20force-velocity%20maximum%20force%20(lengthening)%0A%20%20%20%20%20%20%20%20%22af%22%3A%200.25%2C%20%20%23%20CE%20force-velocity%20shape%20factor%0A%20%20%20%20%20%20%20%20%22ltslack%22%3A%200.223%2C%20%20%23%20tendon%20slack%20length%0A%20%20%20%20%20%20%20%20%22epst0%22%3A%200.04%2C%20%20%23%20tendon%20strain%20at%20the%20maximal%20isometric%20muscle%20force%0A%20%20%20%20%20%20%20%20%22kttoe%22%3A%203.0%2C%20%20%23%20tendon%20linear%20scale%20factor%0A%20%20%20%20%7D%0A%20%20%20%20return%20(parameters%2C)%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20states%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22id%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22%22%2C%0A%20%20%20%20%20%20%20%20%22lmt0%22%3A%200.310%2C%20%20%23%20muscle-tendon%20length%20at%20the%20initial%20knee%20angle%20of%2090%20deg%0A%20%20%20%20%20%20%20%20%22lm0%22%3A%200.087%2C%20%20%23%20initial%20muscle%20length%0A%20%20%20%20%20%20%20%20%22lt0%22%3A%20np.nan%2C%20%20%23%20initial%20tendon%20length%20(computed%20from%20the%20others%20if%20NaN)%0A%20%20%20%20%7D%0A%20%20%20%20return%20(states%2C)%0A%0A%0A%40app.cell%0Adef%20_(Thelen2003%2C%20parameters%2C%20states)%3A%0A%20%20%20%20ms%20%3D%20Thelen2003(parameters.copy()%2C%20states.copy())%0A%20%20%20%20return%20(ms%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Note%20that%20%24L_%7BT0%7D%20%3D%20L_%7BMT0%7D%20-%20L_%7BM0%7D%20%3D%200.310%20-%200.087%20%3D%200.223%24%20m%2C%20exactly%20the%20tendon%20slack%20length.%20The%20simulation%20therefore%20starts%20with%20the%20tendon%20slack%20and%20the%20muscle%20carrying%20no%20force%20at%20all.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20cell**%2C%20predict%20the%20three%20curves%3A%20the%20initial%20fiber%20length%20is%20%240.087%24%20m%20and%20the%20optimal%20length%20is%20%240.093%24%20m%2C%20so%20will%20the%20muscle%20start%20on%20the%20ascending%20or%20the%20descending%20limb%20of%20the%20active%20force-length%20curve%3F%20And%20with%20the%20tendon%20exactly%20at%20slack%2C%20where%20on%20the%20tendon%20curve%20should%20the%20red%20marker%20sit%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ms)%3A%0A%20%20%20%20ms.muscle_plot()%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Now%20the%20skeletal%20side%20of%20the%20model.%20These%20are%20the%20properties%20of%20the%20leg%2Bfoot%20segment%20and%20of%20the%20knee%20joint%2C%20also%20from%20Nigg%20and%20Herzog%20(2006)%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20LMT0%20%3D%200.310%20%20%23%20muscle-tendon%20length%20at%20theta%20%3D%2090%20deg%20%5Bm%5D%0A%20%20%20%20RCM%20%3D%200.264%20%20%23%20knee%20joint%20to%20the%20center%20of%20mass%20of%20the%20leg%2Bfoot%20%5Bm%5D%0A%20%20%20%20MASS%20%3D%2010.0%20%20%23%20mass%20of%20the%20leg%2Bfoot%20segment%20%5Bkg%5D%0A%20%20%20%20G%20%3D%209.8%20%20%23%20acceleration%20of%20gravity%20%5Bm%2Fs2%5D%0A%20%20%20%20INERTIA%20%3D%200.1832%20%20%23%20rotational%20inertia%20of%20the%20leg%2Bfoot%20about%20the%20knee%20%5Bkg.m2%5D%0A%20%20%20%20return%20G%2C%20INERTIA%2C%20LMT0%2C%20MASS%2C%20RCM%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Next%2C%20the%20moment%20arm%20of%20the%20quadriceps%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.function%0Adef%20rm_const(theta)%3A%0A%20%20%20%20%22%22%22Vastus%20intermedius%20moment%20arm%2C%20assumed%20constant%20%5Bm%5D.%22%22%22%0A%0A%20%20%20%20return%200.033%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Now%20two%20helper%20functions%20for%20the%20muscle%20side%20of%20the%20problem.%20They%20are%20the%20same%20equations%20used%20in%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%2C%20specialized%20to%20this%20problem%20by%20fixing%20the%20activation%20at%20%24a%20%3D%201%24%20(the%20muscle%20is%20fully%20excited%20throughout)%20and%20the%20pennation%20angle%20at%20%24%5Calpha%20%3D%200%24%20(a%20fusiform%20muscle%2C%20so%20%24%5Ccos%5Calpha%20%3D%201%24)%3A%0A%0A%20%20%20%20-%20%60muscle_velocity%60%20inverts%20the%20force-velocity%20relationship%3A%20given%20the%20current%20fiber%20length%20and%20the%20current%20muscle-tendon%20length%2C%20it%20returns%20how%20fast%20the%20fiber%20is%20shortening.%0A%20%20%20%20-%20%60muscle_force%60%20evaluates%20the%20force-length%20and%20force-velocity%20relationships%20to%20return%20the%20muscle%20force%20in%20newtons.%0A%0A%20%20%20%20Note%20the%20guard%20%60lm%20%3D%20max(lm%2C%200.1%20*%20lmopt)%60.%20That%20is%20the%20%24f_l(L_M)%20%5Crightarrow%200%24%20singularity%20you%20met%20in%20the%20previous%20notebook%2C%20clamped%20so%20that%20the%20solver%20cannot%20divide%20by%20zero.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(ms%2C%20np)%3A%0A%20%20%20%20def%20muscle_velocity(lm%2C%20lmt)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Muscle%20fiber%20velocity%20from%20the%20muscle-tendon%20force%20equilibrium.%22%22%22%0A%0A%20%20%20%20%20%20%20%20lmopt%20%3D%20ms.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20ltslack%20%3D%20ms.P%5B%22ltslack%22%5D%0A%20%20%20%20%20%20%20%20a%20%3D%201%20%20%23%20the%20muscle%20is%20fully%20activated%0A%20%20%20%20%20%20%20%20alpha%20%3D%200%20%20%23%20fusiform%20muscle%2C%20cos(alpha)%20%3D%201%0A%20%20%20%20%20%20%20%20lm%20%3D%20max(lm%2C%200.1%20*%20lmopt)%20%20%23%20avoid%20the%20fl%20-%3E%200%20singularity%0A%0A%20%20%20%20%20%20%20%20lt%20%3D%20lmt%20-%20lm%20*%20np.cos(alpha)%0A%20%20%20%20%20%20%20%20fse%20%3D%20ms.force_se(lt%3Dlt%2C%20ltslack%3Dltslack)%0A%20%20%20%20%20%20%20%20fpe%20%3D%20ms.force_pe(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20fl%20%3D%20ms.force_l(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20fce_t%20%3D%20fse%20%2F%20np.cos(alpha)%20-%20fpe%0A%20%20%20%20%20%20%20%20vm%20%3D%20ms.velo_fm(fm%3Dfce_t%2C%20a%3Da%2C%20fl%3Dfl)%0A%0A%20%20%20%20%20%20%20%20return%20vm%0A%0A%20%20%20%20def%20muscle_force(lm%2C%20vm)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Muscle%20force%20%5BN%5D%20from%20the%20force-length%20and%20force-velocity%20relationships.%22%22%22%0A%0A%20%20%20%20%20%20%20%20fm0%20%3D%20ms.P%5B%22fm0%22%5D%0A%20%20%20%20%20%20%20%20lmopt%20%3D%20ms.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20a%20%3D%201%0A%20%20%20%20%20%20%20%20lm%20%3D%20max(lm%2C%200.1%20*%20lmopt)%0A%0A%20%20%20%20%20%20%20%20fl%20%3D%20ms.force_l(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20fpe%20%3D%20ms.force_pe(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20fm%20%3D%20ms.force_vm(vm%3Dvm%2C%20fl%3Dfl%2C%20lmopt%3Dlmopt%2C%20a%3Da)%20%2B%20fpe%0A%0A%20%20%20%20%20%20%20%20return%20fm%20*%20fm0%0A%0A%20%20%20%20return%20muscle_force%2C%20muscle_velocity%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20And%20here%20is%20the%20system%20of%20first-order%20ODEs%20itself%20%E2%80%94%20the%20three%20equations%20we%20wrote%20above%2C%20in%20code.%20Read%20it%20next%20to%20the%20mathematics%3A%20%60state%60%20holds%20%24%5BL_M%2C%20%5Ctheta%2C%20%5Comega%5D%24%20and%20the%20function%20returns%20%24%5B%5Cdot%7BL%7D_M%2C%20%5Cdot%7B%5Ctheta%7D%2C%20%5Cdot%7B%5Comega%7D%5D%24%2C%20in%20the%20same%20order.%0A%0A%20%20%20%20The%20moment%20arm%20is%20passed%20in%20as%20an%20argument%2C%20%60rm_fun%60%2C%20rather%20than%20hard-coded.%20That%20way%20the%20*same*%20equations%20can%20be%20solved%20with%20a%20constant%20moment%20arm%20or%20with%20a%20measured%2C%20angle-dependent%20one%2C%20and%20we%20can%20compare%20the%20two%20fairly.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20G%2C%0A%20%20%20%20INERTIA%2C%0A%20%20%20%20MASS%2C%0A%20%20%20%20RCM%2C%0A%20%20%20%20muscle_force%2C%0A%20%20%20%20muscle_velocity%2C%0A%20%20%20%20musculotendon_length%2C%0A%20%20%20%20np%2C%0A)%3A%0A%20%20%20%20def%20onelink_eq(state%2C%20t%2C%20rm_fun)%3A%0A%20%20%20%20%20%20%20%20%22%22%22System%20of%20first-order%20ODEs%20for%20the%20one-link%20system.%0A%0A%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20state%20%3A%20array_like%2C%20%5Blm%2C%20theta%2C%20omega%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20muscle%20length%20%5Bm%5D%2C%20knee%20angle%20%5Brad%5D%2C%20knee%20angular%20velocity%20%5Brad%2Fs%5D%0A%20%20%20%20%20%20%20%20t%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20time%20instant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20rm_fun%20%3A%20callable%0A%20%20%20%20%20%20%20%20%20%20%20%20moment%20arm%20of%20the%20knee%20extensor%20%5Bm%5D%20as%20a%20function%20of%20theta%20%5Brad%5D%0A%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20derivatives%20%3A%20list%2C%20%5Blmd%2C%20omega%2C%20thetadd%5D%0A%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20lm%2C%20theta%2C%20omega%20%3D%20state%0A%0A%20%20%20%20%20%20%20%20rm%20%3D%20rm_fun(theta)%0A%20%20%20%20%20%20%20%20lmt%20%3D%20musculotendon_length(theta%2C%20rm_fun)%0A%20%20%20%20%20%20%20%20lmd%20%3D%20muscle_velocity(lm%2C%20lmt)%0A%20%20%20%20%20%20%20%20thetadd%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20rm%20*%20muscle_force(lm%2C%20lmd)%20%2B%20RCM%20*%20np.cos(theta)%20*%20MASS%20*%20G%0A%20%20%20%20%20%20%20%20)%20%2F%20INERTIA%0A%0A%20%20%20%20%20%20%20%20return%20%5Blmd%2C%20omega%2C%20thetadd%5D%0A%0A%20%20%20%20return%20(onelink_eq%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20Let's%20set%20the%20initial%20states%20and%20use%20%60scipy.integrate.odeint%60%20to%20solve%20the%20ODEs.%20Unlike%20the%20fixed-step%20forward%20Euler%20solver%20we%20wrote%20by%20hand%20in%20the%20previous%20notebook%2C%20%60odeint%60%20chooses%20its%20own%20internal%20step%20size%20adaptively%3B%20the%20%60time%60%20array%20only%20says%20where%20we%20want%20the%20answer%20reported.%0A%0A%20%20%20%20The%20movement%20is%20fast%2C%20so%20we%20only%20simulate%20%240.12%24%20s.%0A%0A%20%20%20%20**Before%20you%20run%20the%20next%20two%20cells**%2C%20sketch%20the%20knee%20angle%20you%20expect%20over%20those%20%240.12%24%20s%3A%20starting%20at%20%2490%5Eo%24%2C%20fully%20activated%20quadriceps.%20Does%20the%20angle%20rise%20linearly%2C%20or%20does%20it%20accelerate%3F%20Roughly%20how%20far%20does%20the%20knee%20get%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20odeint%2C%20onelink_eq)%3A%0A%20%20%20%20state0%20%3D%20%5B0.087%2C%20np.pi%20%2F%202%2C%200%5D%20%20%23%20%5Blm%20(m)%2C%20theta%20(rad)%2C%20omega%20(rad%2Fs)%5D%0A%20%20%20%20time%20%3D%20np.arange(0%2C%200.12%2C%200.001)%0A%20%20%20%20data%20%3D%20odeint(onelink_eq%2C%20state0%2C%20time%2C%20args%3D(rm_const%2C))%0A%20%20%20%20return%20data%2C%20time%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%60odeint%60%20returns%20only%20the%20three%20state%20variables.%20The%20function%20below%20replays%20the%20solution%20to%20recover%20every%20muscle-tendon%20variable%20at%20each%20instant%20(lengths%2C%20velocity%2C%20and%20the%20separate%20force%20contributions)%2C%20so%20that%20we%20can%20reuse%20the%20plotting%20routine%20of%20the%20muscle%20model.%20It%20also%20plots%20the%20simulated%20knee%20angle%20and%20angular%20velocity.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(musculotendon_length%2C%20np%2C%20plt)%3A%0A%20%20%20%20def%20sim_plot(time%2C%20data%2C%20ms%2C%20rm_fun)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Plot%20the%20knee%20kinematics%20and%20rebuild%20the%20muscle-tendon%20variables.%22%22%22%0A%0A%20%20%20%20%20%20%20%20fm0%20%3D%20ms.P%5B%22fm0%22%5D%0A%20%20%20%20%20%20%20%20lmopt%20%3D%20ms.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20ltslack%20%3D%20ms.P%5B%22ltslack%22%5D%0A%20%20%20%20%20%20%20%20a%20%3D%201%0A%20%20%20%20%20%20%20%20alpha%20%3D%200%0A%0A%20%20%20%20%20%20%20%20datam%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20i%2C%20t%20in%20enumerate(time)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20data%5Bi%2C%200%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20theta%20%3D%20data%5Bi%2C%201%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt%20%3D%20musculotendon_length(theta%2C%20rm_fun)%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3D%20lmt%20-%20lm%20*%20np.cos(alpha)%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3D%20ms.force_l(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%20ms.force_pe(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20ms.force_se(lt%3Dlt%2C%20ltslack%3Dltslack)%0A%20%20%20%20%20%20%20%20%20%20%20%20fce_t%20%3D%20fse%20%2F%20np.cos(alpha)%20-%20fpe%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20ms.velo_fm(fm%3Dfce_t%2C%20a%3Da%2C%20fl%3Dfl%2C%20lmopt%3Dlmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fm%20%3D%20ms.force_vm(vm%3Dvm%2C%20fl%3Dfl%2C%20lmopt%3Dlmopt%2C%20a%3Da)%20%2B%20fpe%0A%20%20%20%20%20%20%20%20%20%20%20%20datam.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Bt%2C%20lmt%2C%20lm%2C%20lt%2C%20vm%2C%20fm%20*%20fm0%2C%20fse%20*%20fm0%2C%20a%20*%20fl%20*%20fm0%2C%20fpe%20*%20fm0%2C%20alpha%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20datam%20%3D%20np.array(datam)%0A%0A%20%20%20%20%20%20%20%20_fig%2C%20axs%20%3D%20plt.subplots(nrows%3D1%2C%20ncols%3D2%2C%20sharex%3DTrue%2C%20figsize%3D(9%2C%204))%0A%20%20%20%20%20%20%20%20axs%5B0%5D.plot(time%2C%20data%5B%3A%2C%201%5D%20*%20180%20%2F%20np.pi)%0A%20%20%20%20%20%20%20%20axs%5B0%5D.set_xlabel(%22Time%20(s)%22)%0A%20%20%20%20%20%20%20%20axs%5B0%5D.set_ylabel(r%22Knee%20angle%20%24(%5Eo)%24%22)%0A%20%20%20%20%20%20%20%20axs%5B1%5D.plot(time%2C%20data%5B%3A%2C%202%5D%20*%20180%20%2F%20np.pi)%0A%20%20%20%20%20%20%20%20axs%5B1%5D.set_xlabel(%22Time%20(s)%22)%0A%20%20%20%20%20%20%20%20axs%5B1%5D.set_ylabel(r%22Knee%20velocity%20%24(%5Eo%2Fs)%24%22)%0A%20%20%20%20%20%20%20%20plt.suptitle(%22Simulation%20of%20the%20knee%20extension%22)%0A%20%20%20%20%20%20%20%20plt.tight_layout()%0A%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20return%20datam%0A%0A%20%20%20%20return%20(sim_plot%2C)%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20ms%2C%20sim_plot%2C%20time)%3A%0A%20%20%20%20data2%20%3D%20sim_plot(time%2C%20data%2C%20ms%2C%20rm_const)%0A%20%20%20%20return%20(data2%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20And%20here%20are%20the%20plots%20for%20the%20simulated%20muscle%20mechanics%2C%20using%20the%20same%20six-panel%20layout%20as%20in%20the%20previous%20notebook.%0A%0A%20%20%20%20**Before%20you%20run%20it**%2C%20predict%20the%20%24L_%7BMT%7D%24%20panel.%20In%20the%20previous%20notebook%20%24L_%7BMT%7D%24%20was%20a%20flat%20line%20during%20the%20isometric%20runs%20because%20we%20prescribed%20it.%20Here%20nobody%20prescribed%20it.%20What%20should%20it%20do%20now%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data2%2C%20ms)%3A%0A%20%20%20%20axs_lm%20%3D%20ms.lm_plot(data2)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Challenge%202.**%20Look%20at%20the%20knee%20angle%20plot%20together%20with%20the%20muscle%20force%20plot.%20The%20force%20does%20*not*%20stay%20at%20its%20maximum%20even%20though%20activation%20is%20pinned%20at%20%24a%20%3D%201%24%20the%20whole%20time.%20Name%20the%20two%20effects%20from%20the%20muscle%20model%20that%20pull%20the%20force%20down%20as%20the%20movement%20proceeds.%20(Hint%3A%20one%20is%20about%20how%20fast%20the%20fiber%20is%20shortening%2C%20the%20other%20about%20how%20short%20it%20has%20become.)%0A%0A%20%20%20%20**Challenge%203.**%20The%20knee%20velocity%20keeps%20increasing%20throughout%20the%20simulation.%20Using%20the%20Newton-Euler%20equation%2C%20explain%20what%20would%20eventually%20have%20to%20happen%20to%20the%20angular%20acceleration%20for%20the%20leg%20to%20stop%20accelerating%2C%20and%20identify%20which%20term%20would%20be%20responsible.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Moment%20arm%20is%20not%20constant%0A%0A%20%20%20%20The%20original%20notebook%20also%20used%20the%20measured%20vastus-intermedius%20moment%20arm%20in%20%60data%2Fvas_int_r.mot%60.%20We%20restore%20that%20comparison%20here.%20Its%20numeric%20knee%20angles%20run%20from%20%E2%88%92120%C2%B0%20to%2010%C2%B0%2C%20despite%20a%20misleading%20%60inDegrees%3Dno%60%20header.%20For%20this%20notebook%E2%80%99s%20knee%20angle%2C%20use%20%24q%3D180%5Ctheta%2F%5Cpi-180%24%20degrees.%20The%20measured%20range%20corresponds%20to%20%2460%5E%5Ccirc%5Cle%5Ctheta%5Cle190%5E%5Ccirc%24.%0A%0A%20%20%20%20A%20varying%20moment%20arm%20is%20a%20derivative%20of%20musculotendon%20length%3A%0A%20%20%20%20%24L_%7BMT%7D(%5Ctheta)%3DL_%7BMT0%7D-%5Cint_%7B%5Cpi%2F2%7D%5E%7B%5Ctheta%7Dr_M(s)%5C%2Cds%24.%0A%20%20%20%20Multiplying%20the%20current%20moment%20arm%20by%20the%20whole%20angle%20change%20is%20valid%20only%20when%20the%20arm%20is%20constant.%20We%20use%20the%20spline%E2%80%99s%20antiderivative%20for%20the%20measured%20geometry%20and%20refuse%20extrapolation%20beyond%20its%20measured%20range.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20plt%2C%20repo_file)%3A%0A%20%20%20%20from%20scipy.interpolate%20import%20CubicSpline%0A%20%20%20%20_arm_data%20%3D%20np.loadtxt(repo_file(%22data%2Fvas_int_r.mot%22)%2C%20skiprows%3D7)%0A%20%20%20%20arm_angles%20%3D%20np.deg2rad(_arm_data%5B%3A%2C%201%5D%20%2B%20180.0)%0A%20%20%20%20arm_spline%20%3D%20CubicSpline(arm_angles%2C%20_arm_data%5B%3A%2C%202%5D%2C%20extrapolate%3DFalse)%0A%20%20%20%20arm_integral%20%3D%20arm_spline.antiderivative()%0A%20%20%20%20_fig%2C%20_ax%20%3D%20plt.subplots(figsize%3D(7%2C%204))%0A%20%20%20%20_ax.plot(np.rad2deg(arm_angles)%2C%20_arm_data%5B%3A%2C%202%5D%2C%20%22o%22%2C%20ms%3D3%2C%20label%3D%22Recorded%20geometry%22)%0A%20%20%20%20_q%20%3D%20np.linspace(arm_angles%5B0%5D%2C%20arm_angles%5B-1%5D%2C%20300)%0A%20%20%20%20_ax.plot(np.rad2deg(_q)%2C%20arm_spline(_q)%2C%20label%3D%22Cubic%20spline%22)%0A%20%20%20%20_ax.set(xlabel%3D%22Knee%20angle%20in%20this%20guide%20(degrees)%22%2C%20ylabel%3D%22Moment%20arm%20(m)%22)%0A%20%20%20%20_ax.legend()%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20arm_angles%2C%20arm_integral%2C%20arm_spline%0A%0A%0A%40app.cell%0Adef%20_(LMT0%2C%20arm_angles%2C%20arm_integral%2C%20arm_spline%2C%20np)%3A%0A%20%20%20%20def%20rm_measured(theta)%3A%0A%20%20%20%20%20%20%20%20if%20not%20arm_angles%5B0%5D%20%3C%3D%20theta%20%3C%3D%20arm_angles%5B-1%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20ValueError(%22Knee%20angle%20is%20outside%20measured%20moment-arm%20data.%22)%0A%20%20%20%20%20%20%20%20return%20float(arm_spline(theta))%0A%0A%20%20%20%20def%20musculotendon_length(theta%2C%20rm_fun)%3A%0A%20%20%20%20%20%20%20%20if%20rm_fun%20is%20rm_measured%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20rm_measured(theta)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20float(LMT0%20-%20(arm_integral(theta)%20-%20arm_integral(np.pi%20%2F%202)))%0A%20%20%20%20%20%20%20%20%23%20General%20callable%20fallback%20also%20handles%20a%20modified%20constant%20arm.%0A%20%20%20%20%20%20%20%20from%20scipy.integrate%20import%20quad%0A%20%20%20%20%20%20%20%20return%20LMT0%20-%20quad(rm_fun%2C%20np.pi%20%2F%202%2C%20theta)%5B0%5D%0A%0A%20%20%20%20return%20musculotendon_length%2C%20rm_measured%0A%0A%0A%40app.cell%0Adef%20_(ms%2C%20np%2C%20odeint%2C%20onelink_eq%2C%20rm_measured%2C%20sim_plot%2C%20time)%3A%0A%20%20%20%20measured_state%20%3D%20odeint(onelink_eq%2C%20%5B0.087%2C%20np.pi%20%2F%202%2C%200.0%5D%2C%20time%2C%20args%3D(rm_measured%2C))%0A%20%20%20%20measured_muscle%20%3D%20sim_plot(time%2C%20measured_state%2C%20ms%2C%20rm_measured)%0A%20%20%20%20ms.lm_plot(measured_muscle)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Exercise%202%20%E2%80%94%20Build%20a%20consistent%20state.**%20At%20%24%5Ctheta_0%3D%5Cpi%2F2%24%2C%20total%20musculotendon%20length%20is%200.30%20m.%20With%20constant%20moment%20arm%200.04%20m%2C%20what%20is%20the%20length%20at%20%24%5Ctheta%3D2%5Cpi%2F3%24%3F%20Assume%20a%200.20%20m%20slack%20tendon%20and%20zero%20pennation%20to%20find%20the%20initial%20fiber%20length.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%202%0A%0A%20%20%20%20%24L_%7BMT%7D%3D0.30-0.04(2%5Cpi%2F3-%5Cpi%2F2)%3D0.27906%24%20m.%20With%20the%20stated%20initial%20slack%20tendon%2C%20%24L_M%3D0.07906%24%20m.%20Changing%20angle%20without%20updating%20fiber%20length%20would%20create%20an%20artificial%20initial%20tendon%20stretch.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20**Exercise%203%20%E2%80%94%20Check%20angular%20acceleration.**%20A%20shank%20has%20inertia%200.20%20kg%20m%C2%B2.%20Muscle%20extension%20torque%20is%2015%20N%20m%20and%20gravity%20supplies%205%20N%20m%20in%20flexion.%20Find%20angular%20acceleration.%20Is%20this%20enough%20to%20determine%20its%20final%20angle%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Solution%20to%20Exercise%203%0A%0A%20%20%20%20%24%5Cddot%5Ctheta%3D(15-5)%2F0.20%3D50%24%20rad%2Fs%C2%B2%20initially.%20It%20is%20not%20a%20final-angle%20prediction%3A%20torque%20varies%20with%20angle%2C%20velocity%20and%20fiber%20state%2C%20and%20the%20initial%20velocity%20and%20simulation%20duration%20also%20matter.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Module%20muscles.py%0A%0A%20%20%20%20This%20is%20the%20same%20%60Thelen2003%60%20class%20used%20in%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%2C%20defined%20here%20rather%20than%20imported%20so%20that%20the%20notebook%20is%20self-contained.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20from%20notebook_resources%20import%20repo_file%0A%20%20%20%20except%20ModuleNotFoundError%20as%20_error%3A%0A%20%20%20%20%20%20%20%20if%20_error.name%20!%3D%20%22notebook_resources%22%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%0A%20%20%20%20%20%20%20%20raise%20ModuleNotFoundError(%0A%20%20%20%20%20%20%20%20%20%20%20%20%22This%20notebook%20needs%20notebook_resources.py.%20Download%20it%20from%3A%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22https%3A%2F%2Fraw.githubusercontent.com%2FBMClab%2FBMC%2Fmaster%2Ffunctions%2Fnotebook_resources.py%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%22Save%20it%20in%20the%20same%20folder%20as%20this%20notebook%2C%20then%20rerun%20this%20cell.%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20name%3D%22notebook_resources%22%2C%0A%20%20%20%20%20%20%20%20)%20from%20None%0A%20%20%20%20return%20(repo_file%2C)%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20repo_file)%3A%0A%20%20%20%20%22%22%22Muscle%20modeling%20and%20simulation.%22%22%22%0A%0A%20%20%20%20import%20configparser%0A%0A%20%20%20%20__author__%20%3D%20%22Marcos%20Duarte%2C%20https%3A%2F%2Fgithub.com%2FBMClab%2FBMC%22%0A%20%20%20%20__version__%20%3D%20%22muscles.py%20v.1.03%202026%2F07%2F07%22%0A%0A%20%20%20%20class%20Thelen2003%3A%0A%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20muscle%20model.%22%22%22%0A%0A%20%20%20%20%20%20%20%20def%20__init__(self%2C%20parameters%3DNone%2C%20states%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20parameters%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.set_parameters(parameters)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20states%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.set_states(states)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.lm_data%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20self.act_data%20%3D%20%5B%5D%0A%0A%20%20%20%20%20%20%20%20def%20set_parameters(self%2C%20var%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Load%20and%20set%20parameters%20for%20the%20muscle%20model.%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20var%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20%3D%20str(repo_file(%22data%2Fmuscle_parameter.txt%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20isinstance(var%2C%20str)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.P%20%3D%20self.config_parser(var%2C%20%22parameters%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20isinstance(var%2C%20dict)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.P%20%3D%20var%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20raise%20ValueError(%22Wrong%20parameters!%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22The%20parameters%20were%20successfully%20loaded%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22and%20are%20stored%20in%20the%20variable%20P.%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20def%20set_states(self%2C%20var%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Load%20and%20set%20states%20for%20the%20muscle%20model.%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20var%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var%20%3D%20str(repo_file(%22data%2Fmuscle_state.txt%22))%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20isinstance(var%2C%20str)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.S%20%3D%20self.config_parser(var%2C%20%22states%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20isinstance(var%2C%20dict)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.S%20%3D%20var%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20raise%20ValueError(%22Wrong%20states!%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20print(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22The%20states%20were%20successfully%20loaded%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%20%22and%20are%20stored%20in%20the%20variable%20S.%22%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20def%20config_parser(self%2C%20filename%2C%20var)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%20%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20parser%20%3D%20configparser.ConfigParser()%0A%20%20%20%20%20%20%20%20%20%20%20%20parser.optionxform%20%3D%20str%20%20%23%20make%20option%20names%20case%20sensitive%0A%20%20%20%20%20%20%20%20%20%20%20%20read_files%20%3D%20parser.read(filename)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20not%20read_files%20or%20not%20parser.sections()%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20raise%20ValueError(f%22Could%20not%20read%20%7Bvar%7D%20from%20'%7Bfilename%7D'.%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20var%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20key%2C%20value%20in%20parser.items(parser.sections()%5B0%5D)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20key.lower()%20in%20%5B%22name%22%2C%20%22id%22%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var.update(%7Bkey%3A%20value%7D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%20%3D%20float(value)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20except%20ValueError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(f%22%7Bkey%7D%20value%20%7Bvalue%7D%20was%20replaced%20by%20NaN.%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20value%20%3D%20np.nan%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20var.update(%7Bkey%3A%20value%7D)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20var%0A%0A%20%20%20%20%20%20%20%20def%20force_l(self%2C%20lm%2C%20gammal%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20force%20of%20the%20contractile%20element%20vs.%20muscle%20length.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20gammal%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shape%20factor%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20force%20of%20the%20muscle%20contractile%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20gammal%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20gammal%20%3D%20self.P%5B%22gammal%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3D%20np.exp(-((lm%20-%201)%20**%202)%20%2F%20gammal)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20fl%0A%0A%20%20%20%20%20%20%20%20def%20force_pe(self%2C%20lm%2C%20kpe%3DNone%2C%20epsm0%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20force%20of%20the%20muscle%20parallel%20element%20vs.%20muscle%20length.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20kpe%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20exponential%20shape%20factor%0A%20%20%20%20%20%20%20%20%20%20%20%20epsm0%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20passive%20muscle%20strain%20due%20to%20maximum%20isometric%20force%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20force%20of%20the%20muscle%20parallel%20(passive)%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20kpe%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kpe%20%3D%20self.P%5B%22kpe%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20epsm0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20epsm0%20%3D%20self.P%5B%22epsm0%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lm%20%3C%3D%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%200%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%20(np.exp(kpe%20*%20(lm%20-%201)%20%2F%20epsm0)%20-%201)%20%2F%20(np.exp(kpe)%20-%201)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20fpe%0A%0A%20%20%20%20%20%20%20%20def%20force_se(self%2C%20lt%2C%20ltslack%3DNone%2C%20epst0%3DNone%2C%20kttoe%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20force-length%20relationship%20of%20tendon%20vs.%20tendon%20length.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tendon%20length%20(normalized%20or%20not)%0A%20%20%20%20%20%20%20%20%20%20%20%20ltslack%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tendon%20slack%20length%20(normalized%20or%20not)%0A%20%20%20%20%20%20%20%20%20%20%20%20epst0%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tendon%20strain%20at%20the%20maximal%20isometric%20muscle%20force%0A%20%20%20%20%20%20%20%20%20%20%20%20kttoe%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20linear%20scale%20factor%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20force%20of%20the%20tendon%20series%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20ltslack%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ltslack%20%3D%20self.P%5B%22ltslack%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20epst0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20epst0%20%3D%20self.P%5B%22epst0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20kttoe%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20kttoe%20%3D%20self.P%5B%22kttoe%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20epst%20%3D%20(lt%20-%20ltslack)%20%2F%20ltslack%0A%20%20%20%20%20%20%20%20%20%20%20%20fttoe%20%3D%200.33%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20values%20from%20OpenSim%20Thelen2003Muscle%0A%20%20%20%20%20%20%20%20%20%20%20%20epsttoe%20%3D%200.99%20*%20epst0%20*%20np.e**3%20%2F%20(1.66%20*%20np.e**3%20-%200.67)%0A%20%20%20%20%20%20%20%20%20%20%20%20ktlin%20%3D%200.67%20%2F%20(epst0%20-%20epsttoe)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20epst%20%3C%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%200%0A%20%20%20%20%20%20%20%20%20%20%20%20elif%20epst%20%3C%3D%20epsttoe%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20fttoe%20%2F%20(np.exp(kttoe)%20-%201)%20*%20(np.exp(kttoe%20*%20epst%20%2F%20epsttoe)%20-%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20ktlin%20*%20(epst%20-%20epsttoe)%20%2B%20fttoe%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20fse%0A%0A%20%20%20%20%20%20%20%20def%20velo_fm(self%2C%20fm%2C%20a%2C%20fl%2C%20lmopt%3DNone%2C%20vmmax%3DNone%2C%20fmlen%3DNone%2C%20af%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20velocity%20of%20the%20force-velocity%20relationship%20vs.%20CE%20force.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20fm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20muscle%20force%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle%20activation%20level%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20muscle%20force%20due%20to%20the%20force-length%20relationship%0A%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20optimal%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20maximum%20muscle%20velocity%20for%20concentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20fmlen%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20maximum%20force%20generated%20at%20the%20lengthening%20phase%0A%20%20%20%20%20%20%20%20%20%20%20%20af%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shape%20factor%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20velocity%20of%20the%20muscle%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lmopt%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3D%20self.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20vmmax%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3D%20self.P%5B%22vmmax%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fmlen%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fmlen%20%3D%20self.P%5B%22fmlen%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20af%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20af%20%3D%20self.P%5B%22af%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fm%20%3C%3D%20a%20*%20fl%3A%20%20%23%20isometric%20and%20concentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20fm%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20b%20%3D%20a%20*%20fl%20%2B%20fm%20%2F%20af%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20b%20%3D%20a%20*%20fl%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%20%20%23%20eccentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20asyE_thresh%20%3D%200.95%20%20%23%20from%20OpenSim%20Thelen2003Muscle%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20fm%20%3C%20a%20*%20fl%20*%20fmlen%20*%20asyE_thresh%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20b%20%3D%20(2%20%2B%202%20%2F%20af)%20*%20(a%20*%20fl%20*%20fmlen%20-%20fm)%20%2F%20(fmlen%20-%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fm_thresh%20%3D%20a%20*%20fl%20*%20fmlen%20*%20asyE_thresh%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20b%20%3D%20(2%20%2B%202%20%2F%20af)%20*%20(a%20*%20fl%20*%20fmlen%20-%20fm_thresh)%20%2F%20(fmlen%20-%201)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20(0.25%20%2B%200.75%20*%20a)%20*%20(fm%20-%20a%20*%20fl)%20%2F%20b%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20vm%20*%20vmmax%20*%20lmopt%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20vm%0A%0A%20%20%20%20%20%20%20%20def%20force_vm(self%2C%20vm%2C%20a%2C%20fl%2C%20lmopt%3DNone%2C%20vmmax%3DNone%2C%20fmlen%3DNone%2C%20af%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20force%20of%20the%20contractile%20element%20vs.%20muscle%20velocity.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle%20velocity%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle%20activation%20level%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20muscle%20force%20due%20to%20the%20force-length%20relationship%0A%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20optimal%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20maximum%20muscle%20velocity%20for%20concentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20fmlen%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20normalized%20maximum%20force%20generated%20at%20the%20lengthening%20phase%0A%20%20%20%20%20%20%20%20%20%20%20%20af%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20shape%20factor%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20fvm%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20normalized%20force%20of%20the%20muscle%20contractile%20element%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lmopt%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3D%20self.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20vmmax%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3D%20self.P%5B%22vmmax%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fmlen%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fmlen%20%3D%20self.P%5B%22fmlen%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20af%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20af%20%3D%20self.P%5B%22af%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3D%20vmmax%20*%20lmopt%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20vm%20%3C%3D%200%3A%20%20%23%20isometric%20and%20concentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fvm%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20af%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20a%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20fl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20(4%20*%20vm%20%2B%20vmmax%20*%20(3%20*%20a%20%2B%201))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%20(-4%20*%20vm%20%2B%20vmmax%20*%20af%20*%20(3%20*%20a%20%2B%201))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%20%20%23%20eccentric%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fvm%20%3D%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20fl%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20*%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20af%20*%20vmmax%20*%20(3%20*%20a%20*%20fmlen%20-%203%20*%20a%20%2B%20fmlen%20-%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%208%20*%20vm%20*%20fmlen%20*%20(af%20%2B%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2F%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20af%20*%20vmmax%20*%20(3%20*%20a%20*%20fmlen%20-%203%20*%20a%20%2B%20fmlen%20-%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%2B%208%20*%20vm%20*%20(af%20%2B%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20fvm%0A%0A%20%20%20%20%20%20%20%20def%20lmt_eq(self%2C%20t%2C%20lmt0%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Equation%20for%20muscle-tendon%20length.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lmt0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmt0%20%3D%20self.S%5B%22lmt0%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20lmt0%0A%0A%20%20%20%20%20%20%20%20def%20vm_eq(self%2C%20t%2C%20lm%2C%20lm0%2C%20lmt0%2C%20lmopt%2C%20ltslack%2C%20alpha0%2C%20vmmax%2C%20fm0)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Equation%20for%20muscle%20velocity.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lm%20%3C%200.1%20*%20lmopt%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%200.1%20*%20lmopt%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20lt0%20%3D%20lmt0%20-%20lm0*np.cos(alpha0)%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20self.activation(t)%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt%20%3D%20self.lmt_eq(t%2C%20lmt0)%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3D%20self.penn_ang(lmt%3Dlmt%2C%20lm%3Dlm%2C%20lm0%3Dlm0%2C%20alpha0%3Dalpha0)%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3D%20lmt%20-%20lm%20*%20np.cos(alpha)%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20self.force_se(lt%3Dlt%2C%20ltslack%3Dltslack)%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%20self.force_pe(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3D%20self.force_l(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fce_t%20%3D%20fse%20%2F%20np.cos(alpha)%20-%20fpe%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20if%20fce_t%20%3C%200%3A%20fce_t%3D0%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20self.velo_fm(fm%3Dfce_t%2C%20a%3Da%2C%20fl%3Dfl)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20vm%0A%0A%20%20%20%20%20%20%20%20def%20lm_sol(%0A%20%20%20%20%20%20%20%20%20%20%20%20self%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fun%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t0%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t1%3D3%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dt%3D0.001%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20lm0%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt0%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20ltslack%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20lmopt%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha0%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20vmmax%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fm0%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20show%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%3DNone%2C%0A%20%20%20%20%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Forward%20Euler%20ODE%20solver%20for%20muscle%20length.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lm0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm0%20%3D%20self.S%5B%22lm0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lmt0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmt0%20%3D%20self.S%5B%22lmt0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20ltslack%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20ltslack%20%3D%20self.P%5B%22ltslack%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20alpha0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha0%20%3D%20self.P%5B%22alpha0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lmopt%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3D%20self.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20vmmax%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3D%20self.P%5B%22vmmax%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fm0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fm0%20%3D%20self.P%5B%22fm0%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fun%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fun%20%3D%20self.vm_eq%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20nsteps%20%3D%20int(round((t1%20-%20t0)%20%2F%20dt))%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20lm0%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(nsteps)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t%20%3D%20t0%20%2B%20i%20*%20dt%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20max(lm%2C%200.1%20*%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.append(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.calc_data(t%2C%20lm%2C%20lm0%2C%20lmt0%2C%20ltslack%2C%20lmopt%2C%20alpha0%2C%20fm0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20fun(t%2C%20lm%2C%20lm0%2C%20lmt0%2C%20lmopt%2C%20ltslack%2C%20alpha0%2C%20vmmax%2C%20fm0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20lm%20%2B%20dt%20*%20vm%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20np.array(data)%0A%20%20%20%20%20%20%20%20%20%20%20%20self.lm_data%20%3D%20data%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20show%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.lm_plot(data%2C%20axs)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20data%0A%0A%20%20%20%20%20%20%20%20def%20calc_data(self%2C%20t%2C%20lm%2C%20lm0%2C%20lmt0%2C%20ltslack%2C%20lmopt%2C%20alpha0%2C%20fm0)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Calculus%20of%20muscle-tendon%20variables.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20self.activation(t)%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt%20%3D%20self.lmt_eq(t%2C%20lmt0%3Dlmt0)%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3D%20self.penn_ang(lmt%3Dlmt%2C%20lm%3Dlm%2C%20lm0%3Dlm0%2C%20alpha0%3Dalpha0)%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3D%20lmt%20-%20lm%20*%20np.cos(alpha)%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3D%20self.force_l(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%20self.force_pe(lm%3Dlm%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20self.force_se(lt%3Dlt%2C%20ltslack%3Dltslack)%0A%20%20%20%20%20%20%20%20%20%20%20%20fce_t%20%3D%20fse%20%2F%20np.cos(alpha)%20-%20fpe%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20self.velo_fm(fm%3Dfce_t%2C%20a%3Da%2C%20fl%3Dfl%2C%20lmopt%3Dlmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fm%20%3D%20self.force_vm(vm%3Dvm%2C%20fl%3Dfl%2C%20lmopt%3Dlmopt%2C%20a%3Da)%20%2B%20fpe%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lmt%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lt%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20vm%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fm%20*%20fm0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fse%20*%20fm0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20*%20fl%20*%20fm0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fpe%20*%20fm0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20data%0A%0A%20%20%20%20%20%20%20%20def%20muscle_plot(self%2C%20a%3D1%2C%20axs%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Plot%20muscle-tendon%20relationships%20with%20length%20and%20velocity.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20%20%20%20%20%20%20%20%20except%20ImportError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(%22matplotlib%20is%20not%20available.%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20axs%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fig%2C%20axs%20%3D%20plt.subplots(nrows%3D1%2C%20ncols%3D3%2C%20figsize%3D(9%2C%204))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20lmopt%20%3D%20self.P%5B%22lmopt%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20ltslack%20%3D%20self.P%5B%22ltslack%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20vmmax%20%3D%20self.P%5B%22vmmax%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha0%20%3D%20self.P%5B%22alpha0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20fm0%20%3D%20self.P%5B%22fm0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20lm0%20%3D%20self.S%5B%22lm0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt0%20%3D%20self.S%5B%22lmt0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20lt0%20%3D%20self.S%5B%22lt0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20np.isnan(lt0)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lt0%20%3D%20lmt0%20-%20lm0%20*%20np.cos(alpha0)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20np.linspace(0%2C%202%2C%20101)%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3D%20np.linspace(0%2C%201%2C%20101)%20*%200.05%20%2B%201%0A%20%20%20%20%20%20%20%20%20%20%20%20vm%20%3D%20np.linspace(-1%2C%201%2C%20101)%20*%20vmmax%20*%20lmopt%0A%20%20%20%20%20%20%20%20%20%20%20%20fl%20%3D%20np.zeros(lm.size)%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe%20%3D%20np.zeros(lm.size)%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20np.zeros(lt.size)%0A%20%20%20%20%20%20%20%20%20%20%20%20fvm%20%3D%20np.zeros(vm.size)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20fl_lm0%20%3D%20self.force_l(lm0%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fpe_lm0%20%3D%20self.force_pe(lm0%20%2F%20lmopt)%0A%20%20%20%20%20%20%20%20%20%20%20%20fm_lm0%20%3D%20fl_lm0%20%2B%20fpe_lm0%0A%20%20%20%20%20%20%20%20%20%20%20%20ft_lt0%20%3D%20self.force_se(lt0%2C%20ltslack)%20*%20fm0%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(101)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fl%5Bi%5D%20%3D%20self.force_l(lm%5Bi%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fpe%5Bi%5D%20%3D%20self.force_pe(lm%5Bi%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fse%5Bi%5D%20%3D%20self.force_se(lt%5Bi%5D%2C%20ltslack%3D1)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fvm%5Bi%5D%20%3D%20self.force_vm(vm%5Bi%5D%2C%20a%3Da%2C%20fl%3Dfl_lm0)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3D%20lm%20*%20lmopt%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3D%20lt%20*%20ltslack%0A%20%20%20%20%20%20%20%20%20%20%20%20fse%20%3D%20fse%20*%20fm0%0A%20%20%20%20%20%20%20%20%20%20%20%20fvm%20%3D%20fvm%20*%20fm0%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20xlim%20%3D%20self.margins(lm%2C%20margin%3D0.05%2C%20minmargin%3DFalse)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.set_xlim(xlim)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(%5B0%2C%202%5D%2C%20margin%3D0.05)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(lm%2C%20fl%2C%20%22b%22%2C%20label%3D%22Active%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(lm%2C%20fpe%2C%20%22b--%22%2C%20label%3D%22Passive%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(lm%2C%20fl%20%2B%20fpe%2C%20%22b%3A%22%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(%5Blm0%2C%20lm0%5D%2C%20%5Bylim%5B0%5D%2C%20fm_lm0%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(%5Bxlim%5B0%5D%2C%20lm0%5D%2C%20%5Bfm_lm0%2C%20fm_lm0%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.plot(lm0%2C%20fm_lm0%2C%20%22o%22%2C%20ms%3D6%2C%20mfc%3D%22r%22%2C%20mec%3D%22r%22%2C%20mew%3D2%2C%20label%3D%22fl(LM0)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.legend(loc%3D%22best%22%2C%20frameon%3DTrue%2C%20framealpha%3D0.5)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.set_xlabel(%22Length%20%5Bm%5D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.set_ylabel(%22Scale%20factor%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.xaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.yaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%5D.set_title(%22Muscle%20F-L%20(a%3D1)%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20xlim%20%3D%20self.margins(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5B0%2C%20np.min(vm)%2C%20np.max(vm)%5D%2C%20margin%3D0.05%2C%20minmargin%3DFalse%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.set_xlim(xlim)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(%5B0%2C%20fm0%20*%201.2%2C%20np.max(fvm)%20*%201.5%5D%2C%20margin%3D0.025)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.plot(vm%2C%20fvm%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.set_xlabel(r%22%24%5Cmathbf%7B%5E%7BCON%7D%7D%5C%3B%24%20Velocity%20%5Bm%2Fs%5D%20%24%5C%3B%5Cmathbf%7B%5E%7BEXC%7D%7D%24%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.plot(%5B0%2C%200%5D%2C%20%5Bylim%5B0%5D%2C%20fvm%5B50%5D%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.plot(%5Bxlim%5B0%5D%2C%200%5D%2C%20%5Bfvm%5B50%5D%2C%20fvm%5B50%5D%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.plot(0%2C%20fvm%5B50%5D%2C%20%22o%22%2C%20ms%3D6%2C%20mfc%3D%22r%22%2C%20mec%3D%22r%22%2C%20mew%3D2%2C%20label%3D%22FM0(LM0)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.plot(xlim%5B0%5D%2C%20fm0%2C%20%22%2B%22%2C%20ms%3D10%2C%20mfc%3D%22r%22%2C%20mec%3D%22r%22%2C%20mew%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.text(vm%5B0%5D%2C%20fm0%2C%20%22FM0%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.legend(loc%3D%22upper%20right%22%2C%20frameon%3DTrue%2C%20framealpha%3D0.5)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.set_ylabel(%22Force%20%5BN%5D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.xaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.yaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%5D.set_title(%22Muscle%20F-V%20(a%3D1)%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20xlim%20%3D%20self.margins(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%5Blt0%2C%20ltslack%2C%20np.min(lt)%2C%20np.max(lt)%5D%2C%20margin%3D0.05%2C%20minmargin%3DFalse%0A%20%20%20%20%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.set_xlim(xlim)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(%5Bft_lt0%2C%200%2C%20np.max(fse)%5D%2C%20margin%3D0.05)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.plot(lt%2C%20fse%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.set_xlabel(%22Length%20%5Bm%5D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.plot(%5Blt0%2C%20lt0%5D%2C%20%5Bylim%5B0%5D%2C%20ft_lt0%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.plot(%5Bxlim%5B0%5D%2C%20lt0%5D%2C%20%5Bft_lt0%2C%20ft_lt0%5D%2C%20%22k%3A%22%2C%20lw%3D2%2C%20label%3D%22%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.plot(lt0%2C%20ft_lt0%2C%20%22o%22%2C%20ms%3D6%2C%20mfc%3D%22r%22%2C%20mec%3D%22r%22%2C%20mew%3D2%2C%20label%3D%22FT(LT0)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.legend(loc%3D%22upper%20left%22%2C%20frameon%3DTrue%2C%20framealpha%3D0.5)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.set_ylabel(%22Force%20%5BN%5D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.xaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.yaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%5D.set_title(%22Tendon%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.suptitle(%22Muscle-tendon%20mechanics%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.tight_layout(w_pad%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20axs%0A%0A%20%20%20%20%20%20%20%20def%20lm_plot(self%2C%20x%2C%20axs%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Plot%20the%20muscle-tendon%20simulation%20results.%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20%5Bt%2C%20lmt%2C%20lm%2C%20lt%2C%20vm%2C%20fm*fm0%2C%20fse*fm0%2C%20fl*fm0%2C%20fpe*fm0%2C%20alpha%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20%20%20%20%20%20%20%20%20except%20ImportError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(%22matplotlib%20is%20not%20available.%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20axs%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fig%2C%20axs%20%3D%20plt.subplots(nrows%3D3%2C%20ncols%3D2%2C%20sharex%3DTrue%2C%20figsize%3D(9%2C%206))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%201%5D%2C%20%22b%22%2C%20label%3D%22LMT%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt%20%3D%20x%5B%3A%2C%202%5D%20*%20np.cos(x%5B%3A%2C%209%5D)%20%2B%20x%5B%3A%2C%203%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20np.sum(x%5B%3A%2C%209%5D)%20%3E%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20lmt%2C%20%22g--%22%2C%20label%3Dr%22%24LM%20%5Ccos%20%5Calpha%20%2B%20LT%24%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20lmt%2C%20%22g--%22%2C%20label%3Dr%22LM%2BLT%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%201%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%200%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%200%5D.legend(framealpha%3D0.5%2C%20loc%3D%22best%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%201%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%203%5D%2C%20%22b%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20axs%5B0%2C%201%5D.plot(x%5B%3A%2C%200%5D%2C%20lt0*np.ones(len(x))%2C%20'r')%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%203%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B0%2C%201%5D.set_ylim(ylim)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%202%5D%2C%20%22b%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%23%20axs%5B1%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20lmopt*np.ones(len(x))%2C%20'r')%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%202%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%2C%200%5D.set_ylim(ylim)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%2C%201%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%204%5D%2C%20%22b%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%204%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B1%2C%201%5D.set_ylim(ylim)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%205%5D%2C%20%22b%22%2C%20label%3D%22Muscle%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%200%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%206%5D%2C%20%22g--%22%2C%20label%3D%22Tendon%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%20%5B5%2C%206%5D%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%200%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%200%5D.set_xlabel(%22Time%20(s)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%200%5D.legend(framealpha%3D0.5%2C%20loc%3D%22best%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%201%5D.plot(x%5B%3A%2C%200%5D%2C%20x%5B%3A%2C%208%5D%2C%20%22b%22%2C%20label%3D%22PE%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20ylim%20%3D%20self.margins(x%5B%3A%2C%208%5D%2C%20margin%3D0.1)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%201%5D.set_ylim(ylim)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%201%5D.set_xlabel(%22Time%20(s)%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%5B2%2C%201%5D.legend(framealpha%3D0.5%2C%20loc%3D%22best%22)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20ylabel%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24L_%7BMT%7D%5C%2C(m)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24L_%7BT%7D%5C%2C(m)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24L_%7BM%7D%5C%2C(m)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24V_%7BCE%7D%5C%2C(m%2Fs)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24Force%5C%2C(N)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20r%22%24Force%5C%2C(N)%24%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%2C%20axi%20in%20enumerate(axs.flat)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.set_ylabel(ylabel%5Bi%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20axi.yaxis.set_major_locator(plt.MaxNLocator(4))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fig.align_ylabels(axs)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%23%20axi.yaxis.set_label_coords(-.2%2C%200.5)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.suptitle(%22Simulation%20of%20muscle-tendon%20mechanics%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.tight_layout()%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20axs%0A%0A%20%20%20%20%20%20%20%20def%20penn_ang(self%2C%20lmt%2C%20lm%2C%20lt%3DNone%2C%20lm0%3DNone%2C%20alpha0%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Pennation%20angle.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20lmt%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle-tendon%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20lt%20%3A%20float%2C%20optional%20(default%3DNone)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20tendon%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20lm%20%3A%20float%2C%20optional%20(default%3DNone)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20lm0%20%3A%20float%2C%20optional%20(default%20from%20states%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial%20muscle%20fiber%20length%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha0%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial%20pennation%20angle%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20pennation%20angle%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20lm0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20lm0%20%3D%20self.S%5B%22lm0%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20alpha0%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha0%20%3D%20self.P%5B%22alpha0%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3D%20alpha0%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20alpha0%20!%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20w%20%3D%20lm0%20*%20np.sin(alpha0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20lm%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cosalpha%20%3D%20np.sqrt(1%20-%20(w%20%2F%20lm)%20**%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elif%20lmt%20is%20not%20None%20and%20lt%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20cosalpha%20%3D%201%20%2F%20(np.sqrt(1%20%2B%20(w%20%2F%20(lmt%20-%20lt))%20**%202))%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3D%20np.arccos(cosalpha)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20alpha%20%3E%201.4706289%3A%20%20%23%20np.arccos(0.1)%2C%2084.2608%20degrees%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20alpha%20%3D%201.4706289%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20alpha%0A%0A%20%20%20%20%20%20%20%20def%20excitation(self%2C%20t%2C%20u_max%3DNone%2C%20u_min%3DNone%2C%20t0%3D0%2C%20t1%3D5)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Excitation%20signal%2C%20a%20square%20wave.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20t%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20time%20instant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20u_max%20%3A%20float%20(0%20%3C%20u_max%20%3C%3D%201)%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20maximum%20value%20for%20muscle%20excitation%0A%20%20%20%20%20%20%20%20%20%20%20%20u_min%20%3A%20float%20(0%20%3C%20u_min%20%3C%201)%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20minimum%20value%20for%20muscle%20excitation%0A%20%20%20%20%20%20%20%20%20%20%20%20t0%20%3A%20float%2C%20optional%20(default%3D0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial%20time%20instant%20for%20muscle%20excitation%20equals%20to%20u_max%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20t1%20%3A%20float%2C%20optional%20(default%3D5)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20final%20time%20instant%20for%20muscle%20excitation%20equals%20to%20u_max%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20u%20%3A%20float%20(0%20%3C%20u%20%3C%3D%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20excitation%20signal%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20u_max%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20u_max%20%3D%20self.P%5B%22u_max%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20u_min%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20u_min%20%3D%20self.P%5B%22u_min%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20u%20%3D%20u_min%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t%20%3E%3D%20t0%20and%20t%20%3C%3D%20t1%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20u%20%3D%20u_max%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20u%0A%0A%20%20%20%20%20%20%20%20def%20activation_dyn(self%2C%20t%2C%20a%2C%20t_act%3DNone%2C%20t_deact%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Thelen%20(2003)%20activation%20dynamics%2C%20the%20derivative%20of%20%60a%60%20at%20%60t%60.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20t%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20time%20instant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3A%20float%20(0%20%3C%3D%20a%20%3C%3D%201)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20muscle%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20t_act%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20activation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20t_deact%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20deactivation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20adot%20%3A%20float%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20derivative%20of%20%60a%60%20at%20%60t%60%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t_act%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_act%20%3D%20self.P%5B%22t_act%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t_deact%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_deact%20%3D%20self.P%5B%22t_deact%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20u%20%3D%20self.excitation(t)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20u%20%3E%20a%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20adot%20%3D%20(u%20-%20a)%20%2F%20(t_act%20*%20(0.5%20%2B%201.5%20*%20a))%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20adot%20%3D%20(u%20-%20a)%20%2F%20(t_deact%20%2F%20(0.5%20%2B%201.5%20*%20a))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20adot%0A%0A%20%20%20%20%20%20%20%20def%20activation_sol(%0A%20%20%20%20%20%20%20%20%20%20%20%20self%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20fun%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t0%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t1%3D3%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20dt%3D0.001%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20a0%3D0%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20u_min%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t_act%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20t_deact%3DNone%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20show%3DTrue%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%3DNone%2C%0A%20%20%20%20%20%20%20%20)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Forward%20Euler%20ODE%20solver%20for%20activation%20dynamics.%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Parameters%0A%20%20%20%20%20%20%20%20%20%20%20%20----------%0A%20%20%20%20%20%20%20%20%20%20%20%20fun%20%3A%20function%20object%2C%20optional%20(default%20is%20None%20and%20%60activation_dyn%60%20is%20used)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20function%20with%20ODE%20to%20be%20solved%0A%20%20%20%20%20%20%20%20%20%20%20%20t0%20%3A%20float%2C%20optional%20(default%3D0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial%20time%20instant%20for%20the%20simulation%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20t1%20%3A%20float%2C%20optional%20(default%3D3)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20final%20time%20instant%20for%20the%20simulation%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20dt%20%3A%20float%2C%20optional%20(default%3D0.001)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fixed%20integration%20time%20step%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20a0%20%3A%20float%2C%20optional%20(default%3D0)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20initial%20muscle%20activation%0A%20%20%20%20%20%20%20%20%20%20%20%20u_min%20%3A%20float%20(0%20%3C%20u_min%20%3C%201)%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20minimum%20value%20for%20muscle%20excitation%0A%20%20%20%20%20%20%20%20%20%20%20%20t_act%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20activation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20t_deact%20%3A%20float%2C%20optional%20(default%20from%20parameter%20file)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20deactivation%20time%20constant%20%5Bs%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20show%20%3A%20bool%2C%20optional%20(default%20%3D%20True)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20True%20(1)%2C%20plot%20data%20in%20matplotlib%20figure%0A%20%20%20%20%20%20%20%20%20%20%20%20axs%20%3A%20a%20matplotlib.axes.Axes%20instance%2C%20optional%20(default%20%3D%20None)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20Returns%0A%20%20%20%20%20%20%20%20%20%20%20%20-------%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3A%202-d%20array%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20array%20with%20columns%20%5Btime%2C%20excitation%2C%20activation%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20u_min%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20u_min%20%3D%20self.P%5B%22u_min%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t_act%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_act%20%3D%20self.P%5B%22t_act%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t_deact%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t_deact%20%3D%20self.P%5B%22t_deact%22%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20fun%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20fun%20%3D%20self.activation_dyn%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20nsteps%20%3D%20int(round((t1%20-%20t0)%20%2F%20dt))%0A%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20a0%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20i%20in%20range(nsteps)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20t%20%3D%20t0%20%2B%20i%20*%20dt%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data.append(%5Bt%2C%20self.excitation(t)%2C%20max(a%2C%20u_min)%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20adot%20%3D%20fun(t%2C%20a%2C%20t_act%2C%20t_deact)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20a%20%2B%20dt%20*%20adot%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20np.array(data)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20show%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self.activation_plot(data%2C%20axs)%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.act_data%20%3D%20data%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20data%0A%0A%20%20%20%20%20%20%20%20def%20activation(self%2C%20t%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Activation%20signal.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20self.act_data%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20t%20is%20not%20None%20and%20len(data)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20t%20%3C%3D%20self.act_data%5B0%2C%200%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20self.act_data%5B0%2C%202%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elif%20t%20%3E%3D%20self.act_data%5B-1%2C%200%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20self.act_data%5B-1%2C%202%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%20np.interp(t%2C%20self.act_data%5B%3A%2C%200%5D%2C%20self.act_data%5B%3A%2C%202%5D)%0A%20%20%20%20%20%20%20%20%20%20%20%20else%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20a%20%3D%201%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20a%0A%0A%20%20%20%20%20%20%20%20def%20activation_plot(self%2C%20data%2C%20axs%3DNone)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Plot%20the%20activation%20dynamics%20results.%22%22%22%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20try%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%20%20%20%20%20%20%20%20%20%20%20%20except%20ImportError%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20print(%22matplotlib%20is%20not%20available.%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20return%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20axs%20is%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_%2C%20axs%20%3D%20plt.subplots(nrows%3D1%2C%20ncols%3D1%2C%20figsize%3D(6%2C%204))%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20axs.plot(data%5B%3A%2C%200%5D%2C%20data%5B%3A%2C%201%5D%2C%20color%3D%5B1%2C%200%2C%200%2C%200.6%5D%2C%20label%3D%22Excitation%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs.plot(data%5B%3A%2C%200%5D%2C%20data%5B%3A%2C%202%5D%2C%20color%3D%5B0%2C%200%2C%201%2C%200.6%5D%2C%20label%3D%22Activation%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs.set_xlabel(%22Time%20%5Bs%5D%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs.set_ylabel(%22Level%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20axs.legend()%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.title(%22Activation%20dynamics%22)%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.tight_layout()%0A%20%20%20%20%20%20%20%20%20%20%20%20plt.show()%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20axs%0A%0A%20%20%20%20%20%20%20%20def%20margins(self%2C%20x%2C%20margin%3D0.01%2C%20minmargin%3DTrue)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%22%22%22Calculate%20plot%20limits%20with%20extra%20margins.%22%22%22%0A%20%20%20%20%20%20%20%20%20%20%20%20rang%20%3D%20np.nanmax(x)%20-%20np.nanmin(x)%0A%20%20%20%20%20%20%20%20%20%20%20%20if%20rang%20%3C%200.001%20and%20minmargin%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rang%20%3D%200.001%20*%20np.nanmean(x)%20%2F%20margin%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20rang%20%3C%201%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20rang%20%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20lim%20%3D%20%5Bnp.nanmin(x)%20-%20rang%20*%20margin%2C%20np.nanmax(x)%20%2B%20rang%20*%20margin%5D%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20lim%0A%0A%20%20%20%20return%20(Thelen2003%2C)%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Checkpoint%20questions%0A%0A%20%20%20%20Pause%20here%20and%20answer%20these%20before%20moving%20on.%20They%20tie%20together%20the%20pieces%20you%20have%20simulated.%0A%0A%20%20%20%201.%20What%20exactly%20makes%20this%20a%20*musculoskeletal*%20simulation%20rather%20than%20the%20muscle%20simulation%20of%20the%20previous%20notebook%3F%20Point%20to%20the%20single%20variable%20that%20changed%20role.%0A%20%20%20%202.%20The%20state%20vector%20is%20%24%5BL_M%2C%20%5Ctheta%2C%20%5Comega%5D%24.%20Why%20is%20%24%5Comega%24%20in%20there%2C%20when%20the%20physical%20question%20we%20asked%20was%20only%20about%20the%20knee%20angle%3F%0A%20%20%20%203.%20Muscle%20activation%20was%20held%20at%20%24a%20%3D%201%24%20and%20was%20*not*%20a%20state%20variable%20here.%20Under%20what%20circumstance%20would%20you%20have%20to%20promote%20it%20to%20a%20fourth%20state%3F%0A%20%20%20%204.%20The%20muscle%20force%20falls%20during%20the%20movement%20even%20though%20activation%20never%20changes.%20Which%20two%20properties%20of%20the%20contractile%20element%20are%20responsible%3F%0A%20%20%20%205.%20A%20moment%20arm%20does%20two%20jobs%20in%20these%20equations%20at%20once.%20Name%20both%2C%20and%20explain%20why%20making%20a%20moment%20arm%20larger%20is%20not%20automatically%20an%20advantage.%0A%20%20%20%206.%20In%20the%20previous%20notebook%20we%20integrated%20with%20a%20hand-written%20forward%20Euler%20loop%3B%20here%20we%20used%20%60odeint%60.%20What%20does%20an%20adaptive%20solver%20buy%20you%20in%20a%20problem%20where%20the%20muscle%20force%20can%20change%20very%20quickly%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Checkpoint%20answers%0A%0A%20%20%20%201.%20Joint%20angle%20is%20solved%20from%20muscle%20torque%20and%20feeds%20back%20into%20musculotendon%20length.%0A%20%20%20%202.%20A%20second-order%20joint%20equation%20needs%20both%20angle%20and%20velocity%20as%20initial%20data.%0A%20%20%20%203.%20When%20excitation-driven%20activation%20dynamics%20are%20modeled%20rather%20than%20prescribing%20activation.%0A%20%20%20%204.%20Active%20force%E2%80%93length%20and%20force%E2%80%93velocity%2C%20with%20passive%20force%20and%20tendon%20compliance%20also%20contributing.%0A%20%20%20%205.%20Force-to-torque%20conversion%20and%20angle-to-length%20conversion.%0A%20%20%20%206.%20An%20estimate%20of%20local%20numerical%20error%3B%20physical%20validity%20still%20requires%20model%20and%20state%20checks.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%20Use%20these%20as%20independent%20investigations.%20State%20the%20parameter%20choices%20and%20numerical%20tolerances%20with%20each%20result.%0A%0A%20%20%20%201.%20**Activation%20level.**%20The%20helper%20functions%20fix%20%24a%20%3D%201%24.%20Change%20%60a%60%20to%20%240.5%24%20and%20then%20%240.1%24%20in%20both%20%60muscle_velocity%60%20and%20%60muscle_force%60%2C%20and%20re-run.%20Does%20the%20knee%20still%20reach%20full%20extension%3F%20Is%20the%20relationship%20between%20activation%20and%20final%20angle%20linear%3F%0A%20%20%20%202.%20**Gravity.**%20Set%20%60G%20%3D%200%60%20and%20re-run.%20How%20much%20of%20the%20movement%20was%20being%20resisted%20by%20the%20weight%20of%20the%20leg%3F%20Then%20set%20%60MASS%20%3D%2020%60%20and%20explain%20the%20result%20using%20both%20terms%20of%20the%20Newton-Euler%20equation.%0A%20%20%20%203.%20**Starting%20posture.**%20Start%20the%20simulation%20from%20a%20more%20extended%20knee%2C%20%60state0%20%3D%20%5B0.087%2C%202*np.pi%2F3%2C%200%5D%60.%20Careful%3A%20the%20initial%20muscle%20length%20is%20no%20longer%20consistent%20with%20that%20angle.%20Work%20out%20the%20correct%20%24L_%7BM0%7D%24%20from%20%24L_%7BMT%7D%20%3D%20L_%7BMT0%7D%20-%20r_M(%5Ctheta%20-%20%5Cpi%2F2)%24%2C%20assuming%20the%20tendon%20starts%20at%20slack%20length.%0A%20%20%20%204.%20**Simulation%20duration.**%20Extend%20%60time%60%20to%20%240.3%24%20s%20and%20re-run%20with%20the%20constant%20moment%20arm.%20What%20happens%2C%20and%20why%20is%20the%20result%20no%20longer%20physically%20meaningful%3F%20Relate%20your%20answer%20to%20Challenge%205.%0A%20%20%20%205.%20**A%20stronger%20muscle.**%20Double%20%60fm0%60%20in%20the%20parameters.%20Does%20the%20knee%20extend%20twice%20as%20fast%3F%20Explain%20any%20nonlinearity%20using%20the%20force-velocity%20relationship.%0A%20%20%20%206.%20**Tendon%20compliance.**%20Make%20the%20tendon%20more%20compliant%20by%20increasing%20%60epst0%60%20to%20%240.08%24.%20How%20does%20the%20extra%20tendon%20stretch%20change%20the%20fiber%20velocity%20early%20in%20the%20movement%3F%0A%20%20%20%207.%20**Moment%20arm%20sensitivity.**%20Multiply%20the%20output%20of%20%60rm_const%60%20by%20%241.5%24%20and%20re-run.%20Compare%20against%20the%20measured%2C%20angle-dependent%20moment%20arm.%20Does%20a%20uniformly%20larger%20moment%20arm%20reproduce%20the%20measured%20result%3F%20What%20does%20this%20tell%20you%20about%20the%20value%20of%20measured%20musculoskeletal%20geometry%3F%0A%20%20%20%208.%20**Adding%20an%20antagonist.**%20Sketch%20(you%20do%20not%20have%20to%20code%20it)%20how%20you%20would%20extend%20%60onelink_eq%60%20to%20include%20a%20hamstring%20acting%20as%20a%20knee%20flexor.%20What%20new%20parameters%20would%20you%20need%2C%20and%20how%20many%20state%20variables%20would%20the%20system%20have%3F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20original%20Problems%0A%0A%20%20%20%201.%20Final%20angle%20is%20not%20generally%20proportional%20to%20activation%3B%20muscle%20force%2C%20geometry%2C%20gravity%20and%20the%20chosen%20duration%20interact.%20%E2%80%9CFull%20extension%E2%80%9D%20is%20not%20a%20guaranteed%20endpoint%20of%20this%20unconstrained%20model.%0A%0A%20%20%20%202.%20Setting%20gravity%20to%20zero%20removes%20the%20gravity%20moment.%20Increasing%20mass%20changes%20the%20gravitational%20demand%3B%20a%20physically%20consistent%20mass%20change%20must%20also%20update%20%60INERTIA%60%2C%20otherwise%20the%20comparison%20isolates%20gravity%20rather%20than%20representing%20a%20heavier%20geometrically%20similar%20shank.%0A%0A%20%20%20%203.%20With%20the%20notebook%E2%80%99s%20constant%20moment%20arm%2C%20%24L_%7BM0%7D%3D0.310-0.033(2%5Cpi%2F3-%5Cpi%2F2)-0.223%3D0.0697212%24%20m%20for%20zero%20pennation%20and%20a%20slack%20tendon.%0A%0A%20%20%20%204.%20The%20unconstrained%20constant-arm%20model%20can%20pass%20the%20anatomical%20knee%20range%3B%20it%20has%20no%20joint%20stop%20or%20range-limited%20geometry.%20Extending%20time%20does%20not%20validate%20that%20extrapolation.%0A%0A%20%20%20%205.%20Doubling%20%60fm0%60%20does%20not%20generally%20double%20speed%3B%20velocity-dependent%20force%20and%20tendon%2Ffiber%20states%20change%20during%20the%20motion.%0A%0A%20%20%20%206.%20Greater%20compliance%20allows%20more%20early%20fiber%20shortening%20while%20tendon%20force%20develops%3B%20the%20exact%20transient%20depends%20on%20initial%20tendon%20stretch%20and%20activation.%0A%0A%20%20%20%207.%20A%20uniform%20multiplier%20cannot%20reproduce%20an%20arbitrary%20angle-dependent%20moment-arm%20curve.%20The%20length%20function%20must%20change%20consistently%20with%20the%20integral%20of%20that%20moment%20arm.%0A%0A%20%20%20%208.%20With%20activation%20prescribed%2C%20add%20one%20antagonist%20fiber-length%20state%3A%20four%20states%20total.%20Add%20flexor%20geometry%2C%20force%E2%80%93length%2Fvelocity%20curves%2C%20tendon%20parameters%2C%20initial%20fiber%20length%20and%20activation.%20Dynamic%20activation%20for%20both%20muscles%20adds%20two%20more%20states%2C%20for%20six%20total.%0A%20%20%20%20%2F%2F%2F%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20-%20%5BMuscle%20modeling%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_modeling.py)%20%E2%80%94%20where%20the%20force-length%2C%20force-velocity%2C%20and%20activation%20functions%20used%20here%20were%20derived.%0A%20%20%20%20-%20%5BMuscle%20simulation%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fmuscle_simulation.py)%20%E2%80%94%20the%20same%20muscle%20model%2C%20but%20with%20the%20muscle-tendon%20length%20prescribed%20instead%20of%20produced%20by%20the%20movement.%0A%20%20%20%20-%20%5BIntroduction%20to%20numerical%20solution%20of%20Ordinary%20Differential%20Equations%5D(https%3A%2F%2Fmolab.marimo.io%2Fgithub%2FBMClab%2FBMC%2Fblob%2Fmaster%2Fnotebooks%2Fordinary_differential_equation.py)%20%E2%80%94%20how%20systems%20of%20first-order%20ODEs%20are%20set%20up%20and%20solved.%0A%20%20%20%20-%20%5BOpenSim%5D(https%3A%2F%2Fsimtk.org%2Fhome%2Fopensim)%20%E2%80%94%20the%20musculoskeletal%20modeling%20software%20the%20moment-arm%20data%20came%20from%2C%20and%20the%20natural%20next%20tool%20once%20the%20models%20grow%20beyond%20one%20link%20and%20one%20muscle.%0A%0A%20%20%20%20%23%23%20References%0A%0A%20%20%20%20-%20Nigg%20BM%20and%20Herzog%20W%20(2006)%20%5BBiomechanics%20of%20the%20Musculo-skeletal%20System%5D(https%3A%2F%2Fbooks.google.com.br%2Fbooks%3Fid%3DhOIeAQAAIAAJ%26dq%3Deditions%3AISBN0470017678).%203rd%20Edition.%20Wiley.%0A%0A%20%20%20%20-%20Thelen%20DG%20(2003)%20%5BAdjustment%20of%20muscle%20mechanics%20model%20parameters%20to%20simulate%20dynamic%20contractions%20in%20older%20adults%5D(http%3A%2F%2Fhomepages.cae.wisc.edu%2F~thelen%2Fpubs%2Fjbme03.pdf).%20Journal%20of%20Biomechanical%20Engineering%2C%20125(1)%3A70-77.%0A%0A%20%20%20%20-%20Zajac%20FE%2C%20Gordon%20ME%20(1989)%20%5BDetermining%20muscle's%20force%20and%20action%20in%20multi-articular%20movement%5D(https%3A%2F%2Fdrive.google.com%2Fopen%3Fid%3D0BxbW72zV7WmUcC1zSGpEOUxhWXM%26authuser%3D0).%20Exercise%20and%20Sport%20Sciences%20Reviews%2C%2017%2C%20187-230.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20%5BMIT%20OpenCourseWare%5D(https%3A%2F%2Focw.mit.edu%2Fcourses%2F2-003sc-engineering-dynamics-fall-2011%2Fpages%2Ffree-body-diagrams-and-fictitious-forces%2F)%20%E2%80%94%20Free-body%20diagrams%3A%20practice%20selecting%20a%20body%20and%20frame%20before%20writing%20force%20and%20moment%20equations.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20References%0A%0A%20%20%20%20-%20Yamaguchi%20GT%20(2001).%20*Dynamic%20Modeling%20of%20Musculoskeletal%20Motion%3A%20A%20Vectorized%20Approach%20for%20Biomechanical%20Analysis%20in%20Three%20Dimensions*.%20Springer.%20Chapter%202.%20%5BRepository%20reading%20copy%5D(..%2Fcourses%2Frefs%2FYamaguchi_ch2.pdf).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
ba0fd60279f4da988377ad982c4100ac