%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()%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%20Read%20Zebris%20pressure%20platform%20ASCII%20files%0A%0A%20%20%20%20%3E%20Marcos%20Duarte%2C%20Renato%20Naville%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%20notebook%0A%0A%20%20%20%20Read%20the%20APD%20header%20before%20looking%20at%20the%20foot%20image.%20Then%20compare%20the%20raw%20grid%2C%20display%20interpolation%2C%20spline%20surface%20and%20resized%20steps.%20Each%20representation%20answers%20a%20different%20question.%20Predict%20a%20numerical%20quantity%20or%20a%20visual%20change%20before%20expanding%20a%20worked%20solution.%0A%0A%20%20%20%20%23%23%20Opening%20challenge%0A%0A%20%20%20%20A%20colourful%20footprint%20looks%20like%20a%20pressure%20snapshot.%20Is%20it%3F%20If%20each%20sensor%20stores%20its%20maximum%20over%20an%20entire%20step%2C%20what%20happens%20when%20you%20sum%20those%20values%20and%20call%20the%20result%20peak%20force%3F%0A%0A%20%20%20%20%23%23%20Setup%0A%0A%20%20%20%20NumPy%20reads%20the%20ASCII%20arrays%3B%20Matplotlib%20draws%20them%3B%20SciPy%20demonstrates%20spline%20fitting%20and%20resizing.%20The%20retained%20%60MDwalk2%60%20APD%20files%20are%20bundled%20examples.%20Their%20header%20distances%20are%20in%20mm%20and%20pressures%20in%20N%2Fcm%C2%B2.%20The%20figures%20convert%20distances%20to%20cm.%20No%20platform%20connection%20is%20needed.%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%20Zebris%20Medical%20GmbH%20(https%3A%2F%2Fwww.zebris.de%2Fen%2F)%20builds%20devices%20for%20measuring%20pressure%20on%20the%20foot%2Fplatform%20interface.%3Cbr%3E%0A%20%20%20%20The%20BMClab%20(https%3A%2F%2Fbmclab.pesquisa.ufabc.edu.br%2F)%20originally%20recorded%20the%20following%20setup%20notes%20for%20its%20two%20Zebris%20FDM%201.5%20platforms.%20These%20are%20historical%20laboratory%20notes%2C%20not%20specifications%20for%20every%20model%20or%20firmware%3A%0A%20%20%20%20-%20Measuring%20principle%3A%20capacitive%20force%20measurement%0A%20%20%20%20-%20Dimensions%3A%20158%20x%2060.5%20x%202.1%20cm%20(L%20x%20W%20x%20H)%0A%20%20%20%20-%20Sensor%20area%3A%20149%20x%2054.2%20cm%20(L%20x%20W)%0A%20%20%20%20-%20Number%20of%20sensors%3A%2011264%0A%20%20%20%20-%20Physical%20resolution%3A%201.4%20sensors%20%2Fcm2%20%20(0.714%20cm2)%0A%20%20%20%20-%20Sampling%20frequency%3A%20100%20Hz%0A%20%20%20%20-%20Measuring%20Range%3A%201%20-%20120%20N%2Fcm2%0A%20%20%20%20-%20Accuracy%20of%20the%20calibrated%20measuring%20range%3A%20(1%20%E2%80%93%2080%20N%2Fcm2)%2C%20%C2%B15%25%20(FS)%0A%20%20%20%20-%20Hysteresis%3A%20%3C%203%20%25%20(FS)%0A%0A%20%20%20%20The%20%5Bmanufacturer's%202015%20hardware%20manual%5D(https%3A%2F%2Fwww.zebris.de%2Ffileadmin%2FEditoren%2Fzebris-PDF-Manuals%2FMedizin%2FHardware%2FAlte_Versionen%2FFDM_Hardware-Manual_151203_en.pdf)%20lists%20a%201440%20%C3%97%20560%20mm%20sensor%20area%20and%20120%20Hz%20standard%20sampling%20for%20its%20FDM%201.5%20version%2C%20which%20differs%20from%20some%20historical%20notes%20above.%20Use%20the%20manual%20for%20your%20model%20and%20the%20acquisition%20metadata.%20The%20sample%20APD%20files%20provide%20sensor%20spacing%20but%20no%20pressure%20time%20series.%0A%0A%20%20%20%20The%20two%20pressure%20platforms%20can%20be%20synchronized%20and%20used%20as%20a%20single%203-m%20platform.%0A%0A%20%20%20%20The%20proprietary%20software%20to%20operate%20the%20pressure%20device%20saves%20files%20in%20ASCII%20and%20binary%20formats%20with%20the%20pressure%20data.%20Here%20are%20functions%20for%20reading%20most%20of%20the%20files%20saved%20in%20ASCII%20format.%20These%20files%20have%20headers%20with%20metadata%20about%20the%20patient%20and%20acquisition%20conditions%20and%20the%20data%20of%20pressure%2C%20force%2C%20or%20center%20of%20pressure%20%20depending%20on%20the%20type%20of%20acquisition%20and%20chosen%20option%20to%20export%20the%20data.%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%20APD%20file%0A%0A%20%20%20%20The%20.apd%20file%20in%20ASCII%20contains%20the%20metadata%20and%20the%20maximum%20values%20of%20pressure%20over%20the%20trial%20in%20the%20exported%20foot%20region.%20The%20original%20notes%20stated%20a%20nominal%201%20N%2Fcm%C2%B2%20threshold%2C%20but%20the%20supplied%20file%20also%20contains%200.5%20N%2Fcm%C2%B2%20entries%3B%20do%20not%20impose%20that%20historical%20threshold%20as%20a%20property%20of%20every%20export.%20This%20file%20can%20be%20used%20for%20making%20insoles.%3Cbr%3E%0A%20%20%20%20Here%20is%20a%20typical%20.apd%20file%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%20%23%20'%25matplotlib%20inline'%20command%20supported%20automatically%20in%20marimo%0A%20%20%20%20return%20np%2C%20plt%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_(repo_file)%3A%0A%20%20%20%20filename%20%3D%20str(repo_file('data%2FMDwalk2.apd'))%0A%20%20%20%20with%20open(file%3Dfilename%2C%20mode%3D'rt'%2C%20newline%3D'')%20as%20f%3A%0A%20%20%20%20%20%20%20%20print(f.read())%0A%20%20%20%20return%20(filename%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**Exercise%201%20%E2%80%94%20inspect%20the%20header.**%20The%20first%20file%20has%20%60SensCountX%3D32%60%2C%20%60SensCountY%3D15%60%20and%20spacing%208.46591%20mm%20in%20each%20direction.%20What%20shape%20and%20footprint%20bounds%20should%20the%20raw%20array%20have%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%201%20%E2%80%94%20inspect%20the%20header%0A%0A%20%20%20%20The%20array%20has%2032%20rows%20and%2015%20columns.%20Spacing%20is%200.846591%20cm%2C%20so%20the%20rectangular%20bounds%20are%2027.090912%20cm%20in%20X%20and%2012.698865%20cm%20in%20Y.%20The%20rectangle%20includes%20unoccupied%20sensors%3B%20its%20area%20is%20not%20necessarily%20contact%20area.%20The%20reader%20maps%20the%20export%20sentinel%20%E2%88%921%20to%20zero%20for%20these%20displays%2C%20so%20distinguish%20unreported%20cells%20from%20measured%20zero%20pressure%20in%20later%20analyses.%0A%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%20Here%20is%20a%20function%20for%20reading%20an%20.apd%20file%20from%20Zebris%20pressure%20platform%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np)%3A%0A%20%20%20%20def%20read_zebris_apd(filename)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Reads%20Zebris%20pressure%20platform%20ASCII%20files%20.apd.%0A%20%20%20%20%20%20%20%20%22%22%22%0A%20%20%20%20%20%20%20%20import%20pprint%0A%20%20%20%20%20%20%20%20sections%20%3D%20%5B'General'%2C%20'Customer'%2C%20'Technical'%2C%20'Data'%5D%0A%20%20%20%20%20%20%20%20_s%20%3D%200%0A%20%20%20%20%20%20%20%20info%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20with%20open(file%3Dfilename%2C%20mode%3D'rt'%2C%20newline%3D'')%20as%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20linea%20in%20f%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20line%20%3D%20linea.strip('%5Cr%5B%5D%5Cn')%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20if%20line%20%3D%3D%20sections%5B_s%5D%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20info%5Bsections%5B_s%5D%5D%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20_s%20%2B%3D%201%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elif%20line%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20info%5Bsections%5B_s%20-%201%5D%5D%5Bline.split('%3D')%5B0%5D%5D%20%3D%20line.split('%3D')%5B1%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20elif%20_s%20%3D%3D%203%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20%20%20%20%20f.readline()%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20np.loadtxt(f%2C%20delimiter%3D'%5Ct')%0A%20%20%20%20%20%20%20%20%20%20%20%20data%5Bdata%20%3D%3D%20-1%5D%20%3D%200%0A%20%20%20%20%20%20%20%20%20%20%20%20print('File%20%25s%20successfully%20open.'%20%25%20filename)%0A%20%20%20%20%20%20%20%20%20%20%20%20print('Data%20has%20%25d%20rows%20and%20%25d%20columns.'%20%25%20data.shape)%0A%20%20%20%20%20%20%20%20return%20(info%2C%20data)%0A%0A%20%20%20%20return%20(read_zebris_apd%2C)%0A%0A%0A%40app.cell%0Adef%20_(filename%2C%20read_zebris_apd)%3A%0A%20%20%20%20info%2C%20data%20%3D%20read_zebris_apd(filename)%0A%20%20%20%20return%20data%2C%20info%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%20Simple%202D%20plot%20of%20the%20raw%20data%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20info%2C%20np%2C%20plt)%3A%0A%20%20%20%20from%20matplotlib%20import%20cm%0A%20%20%20%20dx%20%3D%20float(info%5B'Technical'%5D%5B'LDistX'%5D)%20%2F%2010%0A%20%20%20%20dy%20%3D%20float(info%5B'Technical'%5D%5B'LDistY'%5D)%20%2F%2010%0A%20%20%20%20x%20%3D%20np.arange(1%20%2F%202%2C%20data.shape%5B0%5D%20%2B%201%20%2F%202%2C%201)%20*%20dx%0A%20%20%20%20y%20%3D%20np.arange(1%20%2F%202%2C%20data.shape%5B1%5D%20%2B%201%20%2F%202%2C%201)%20*%20dy%0A%20%20%20%20(X%2C%20Y)%20%3D%20np.meshgrid(y%2C%20x)%0A%20%20%20%20print('Shapes%3A')%0A%20%20%20%20print('X%3A'%2C%20X.shape%2C%20'Y%3A'%2C%20Y.shape%2C%20'data%3A'%2C%20data.shape)%0A%20%20%20%20(_fig%2C%20_ax)%20%3D%20plt.subplots(figsize%3D(6%2C%207))%0A%20%20%20%20_img%20%3D%20_ax.pcolormesh(X%2C%20Y%2C%20data%2C%20cmap%3Dcm.jet)%0A%20%20%20%20_ax.set_aspect('equal')%0A%20%20%20%20_fig.colorbar(_img%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)')%0A%20%20%20%20_ax.set_xlabel('Y%20(cm)')%0A%20%20%20%20_ax.set_ylabel('X%20(cm)')%0A%20%20%20%20_ax.set_title('Plantar%20pressure%20during%20walking')%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20X%2C%20Y%2C%20cm%2C%20dx%2C%20dy%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%23%202D%20display%20interpolation%0A%0A%20%20%20%20Let's%20use%20the%20matplotlib%20function%20%5B%60imshow%60%5D(https%3A%2F%2Fmatplotlib.org%2Fstable%2Fapi%2F_as_gen%2Fmatplotlib.axes.Axes.imshow.html)%20to%20compare%20nearest-neighbour%20and%20bilinear%20display%20interpolation.%20This%20changes%20how%20the%20same%20array%20is%20drawn%2C%20not%20the%20stored%20pressure%20measurements.%3Cbr%3E%0A%20%20%20%20The%20%60extent%60%20argument%20maps%20the%20image%20bounds%20to%20physical%20centimetres%3B%20without%20it%2C%20labelled%20axes%20would%20still%20count%20array%20indices.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cm%2C%20data%2C%20dx%2C%20dy%2C%20plt)%3A%0A%20%20%20%20(_fig%2C%20_ax)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%207))%0A%20%20%20%20_extent%20%3D%20(0%2C%20data.shape%5B1%5D*dy%2C%200%2C%20data.shape%5B0%5D*dx)%0A%20%20%20%20_img0%20%3D%20_ax%5B0%5D.imshow(data%2C%20extent%3D_extent%2C%20vmin%3D0%2C%20vmax%3D40%2C%20cmap%3Dcm.jet%2C%20aspect%3D'equal'%2C%20origin%3D'lower'%2C%20interpolation%3D'nearest')%0A%20%20%20%20_ax%5B0%5D.set_xlabel('Y%20(cm)')%0A%20%20%20%20_ax%5B0%5D.set_ylabel('X%20(cm)')%0A%20%20%20%20_img1%20%3D%20_ax%5B1%5D.imshow(data%2C%20extent%3D_extent%2C%20cmap%3Dcm.jet%2C%20aspect%3D'equal'%2C%20origin%3D'lower'%2C%20interpolation%3D'bilinear'%2C%20vmin%3D0%2C%20vmax%3D40)%0A%20%20%20%20_ax%5B1%5D.set_xlabel('Y%20(cm)')%0A%20%20%20%20_ax%5B1%5D.set_ylabel('X%20(cm)')%0A%20%20%20%20_fig.colorbar(_img1%2C%20ax%3Dlist(_ax)%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)')%0A%20%20%20%20_fig.suptitle('Plantar%20pressure%20during%20walking'%2C%20fontsize%3D16)%0A%20%20%20%20plt.show()%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%20peak%20map%20versus%20force.**%20Two%201%20cm%C2%B2%20sensors%20have%20pressures%20(10%2C0)%20N%2Fcm%C2%B2%20at%20one%20instant%20and%20(0%2C10)%20at%20another.%20What%20is%20the%20peak%20actual%20force%2C%20and%20what%20would%20summing%20an%20APD%20maximum%20map%20give%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%202%20%E2%80%94%20peak%20map%20versus%20force%0A%0A%20%20%20%20Both%20instantaneous%20forces%20are%2010%20N.%20The%20per-sensor%20maximum%20map%20is%20(10%2C10)%2C%20whose%20area-weighted%20sum%20is%2020%20N.%20Maxima%20at%20different%20times%20cannot%20be%20added%20as%20though%20they%20were%20simultaneous.%20APD%20data%20alone%20also%20cannot%20recover%20impulse%2C%20contact%20duration%20or%20cadence.%0A%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%23%23%203D%20plots%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X%2C%20Y%2C%20cm%2C%20data%2C%20plt)%3A%0A%20%20%20%20from%20mpl_toolkits.mplot3d%20import%20Axes3D%0A%20%20%20%20_fig%20%3D%20plt.figure(figsize%3D(14%2C%206))%0A%20%20%20%20_ax%20%3D%20_fig.add_subplot(projection%3D'3d')%0A%20%20%20%20_surf%20%3D%20_ax.plot_surface(X%2C%20Y%2C%20data%2C%20cmap%3Dcm.jet%2C%20rcount%3Ddata.shape%5B0%5D%2C%20ccount%3Ddata.shape%5B1%5D%2C%20linewidth%3D0%2C%20antialiased%3DTrue)%0A%20%20%20%20_ax.view_init(60%2C%20200)%0A%20%20%20%20_fig.colorbar(_surf%2C%20orientation%3D'vertical'%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)')%0A%20%20%20%20_ax.set_xlabel('Y%20(cm)')%0A%20%20%20%20_ax.set_ylabel('X%20(cm)')%0A%20%20%20%20plt.show()%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%23%203D%20spline%20surface%0A%0A%20%20%20%20This%20fits%20a%20smoother%20surface%20on%20a%20denser%20grid.%20It%20does%20not%20add%20measured%20spatial%20resolution.%20Inspect%20overshoot%2C%20including%20negative%20values%2C%20before%20interpreting%20an%20interpolated%20peak.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X%2C%20Y%2C%20data%2C%20dx%2C%20dy%2C%20np)%3A%0A%20%20%20%20from%20scipy%20import%20interpolate%0A%20%20%20%20%23%20interpolate%20data%20over%20a%20four%20times%20denser%20grid%0A%20%20%20%20x2%20%3D%20np.arange(1%2F8%2C%20data.shape%5B0%5D%20%2B%201%2F8%2C%201%2F4)*dx%0A%20%20%20%20y2%20%3D%20np.arange(1%2F8%2C%20data.shape%5B1%5D%20%2B%201%2F8%2C%201%2F4)*dy%0A%20%20%20%20X2%2C%20Y2%20%3D%20np.meshgrid(y2%2C%20x2)%0A%20%20%20%20tck%20%3D%20interpolate.bisplrep(X%2C%20Y%2C%20data)%0A%20%20%20%20data2%20%3D%20interpolate.bisplev(X2%5B0%2C%3A%5D%2C%20Y2%5B%3A%2C0%5D%2C%20tck).T%0A%20%20%20%20print('Shapes%3A')%0A%20%20%20%20print('X2%3A'%2C%20X2.shape%2C%20'Y2%3A'%2C%20Y2.shape%2C%20'data2%3A'%2C%20data2.shape)%0A%20%20%20%20return%20X2%2C%20Y2%2C%20data2%0A%0A%0A%40app.cell%0Adef%20_(X2%2C%20Y2%2C%20cm%2C%20data2%2C%20plt)%3A%0A%20%20%20%20_fig%20%3D%20plt.figure(figsize%3D(14%2C%206))%0A%20%20%20%20_ax%20%3D%20_fig.add_subplot(projection%3D'3d')%0A%20%20%20%20_surf%20%3D%20_ax.plot_surface(X2%2C%20Y2%2C%20data2%2C%20cmap%3Dcm.jet%2C%20rcount%3Ddata2.shape%5B0%5D%2C%20ccount%3Ddata2.shape%5B1%5D%2C%20linewidth%3D0%2C%20antialiased%3DFalse)%0A%20%20%20%20_ax.view_init(60%2C%20200)%0A%20%20%20%20_fig.colorbar(_surf%2C%20orientation%3D'vertical'%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)')%0A%20%20%20%20_ax.set_xlabel('Y%20(cm)')%0A%20%20%20%20_ax.set_ylabel('X%20(cm)')%0A%20%20%20%20plt.show()%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%20Loading%20several%20steps%20of%20a%20trial%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cm)%3A%0A%20%20%20%20def%20plot_apd(info%2C%20data%2C%20ax%2C%20title)%3A%0A%20%20%20%20%20%20%20%20dx%20%3D%20float(info%5B'Technical'%5D%5B'LDistX'%5D)%20%2F%2010%0A%20%20%20%20%20%20%20%20dy%20%3D%20float(info%5B'Technical'%5D%5B'LDistY'%5D)%20%2F%2010%0A%20%20%20%20%20%20%20%20x0%20%3D%20int(info%5B'Technical'%5D%5B'StartSensY'%5D)%20*%20dy%0A%20%20%20%20%20%20%20%20y0%20%3D%20int(info%5B'Technical'%5D%5B'StartSensX'%5D)%20*%20dx%0A%20%20%20%20%20%20%20%20xlen%20%3D%20int(info%5B'Technical'%5D%5B'SensCountY'%5D)%0A%20%20%20%20%20%20%20%20ylen%20%3D%20int(info%5B'Technical'%5D%5B'SensCountX'%5D)%0A%20%20%20%20%20%20%20%20_img%20%3D%20ax.imshow(data%2C%20cmap%3Dcm.jet%2C%20aspect%3D'auto'%2C%20origin%3D'lower'%2C%20extent%3D%5Bx0%2C%20x0%20%2B%20xlen%20*%20dy%2C%20y0%2C%20y0%20%2B%20ylen%20*%20dx%5D%2C%20interpolation%3D'nearest'%2C%20vmin%3D0%2C%20vmax%3D40)%0A%20%20%20%20%20%20%20%20ax.set_title(title)%0A%20%20%20%20%20%20%20%20ax.set_xlabel('Y%20(cm)')%0A%20%20%20%20%20%20%20%20return%20_img%0A%0A%20%20%20%20return%20(plot_apd%2C)%0A%0A%0A%40app.cell%0Adef%20_(plot_apd%2C%20plt%2C%20read_zebris_apd%2C%20repo_file)%3A%0A%20%20%20%20steps%20%3D%20%5B'MDwalk2'%20%2B%20_step%20for%20_step%20in%20%5B''%2C%20'_1'%2C%20'_2'%2C%20'_3'%2C%20'_4'%5D%5D%0A%20%20%20%20(infos%2C%20datas)%20%3D%20(%7B%7D%2C%20%7B%7D)%0A%20%20%20%20(_fig%2C%20_axs)%20%3D%20plt.subplots(1%2C%20len(steps)%2C%20figsize%3D(14%2C%207))%0A%20%20%20%20for%20(_s%2C%20_step)%20in%20enumerate(steps)%3A%0A%20%20%20%20%20%20%20%20(infos%5B_step%5D%2C%20datas%5B_step%5D)%20%3D%20read_zebris_apd(str(repo_file('data%2F'%20%2B%20_step%20%2B%20'.apd')))%0A%20%20%20%20%20%20%20%20_img%20%3D%20plot_apd(infos%5B_step%5D%2C%20datas%5B_step%5D%2C%20_axs%5B_s%5D%2C%20_step)%0A%20%20%20%20_axs%5B0%5D.set_ylabel('X%20(cm)')%0A%20%20%20%20_fig.colorbar(_img%2C%20ax%3Dlist(_axs)%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)'%2C%20orientation%3D'horizontal'%2C%20pad%3D0.1%2C%20aspect%3D40)%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20datas%2C%20infos%2C%20steps%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%20It%20seems%20the%20Zebris%20software%20when%20exporting%20the%20pressure%20data%20to%20.apd%20files%20of%20a%20trial%20with%20a%20sequence%20of%20steps%2C%20saves%20first%20the%20data%20of%20the%20right%20foot%20and%20then%20of%20the%20left%20foot.%0A%0A%20%20%20%20The%20origin%20of%20the%20pressure%20platform%20was%20at%20the%20far%20right%20corner%20in%20relation%20to%20the%20walking%20direction%20of%20the%20subject%20in%20this%20trial%20(see%20the%20values%20at%20the%20x%20and%20y%20axes).%20So%2C%20the%20order%20of%20the%20subject's%20foot%20steps%20were%3A%20MDwalk2_4%2C%20MDwalk2_1%2C%20MDwalk2_3%2C%20MDwalk2%2C%20and%20MDwalk2_2.%0A%0A%20%20%20%20The%20size%20of%20the%20pressure%20data%20across%20steps%20is%20not%20constant%2C%20the%20width%20varies%20from%2012%20to%2015%20columns%20and%20the%20length%20varies%20from%2030%20to%2032%20rows%20of%20data.%20Multiply%20these%20numbers%20by%200.846591%20cm%20to%20have%20the%20size%20of%20the%20pressure%20data%20in%20centimeters.%20Possible%20reasons%20for%20this%20variation%20are%3A%201.%20foot%20rotation%2C%202.%20differences%20at%20how%20the%20foot%20is%20supported%20at%20the%20ground%20at%20each%20step%2C%20and%203.%20perhaps%20measurement%20noise.%20So%2C%20one%20can't%20directly%20compare%20the%20images%20(the%20pressures)%2C%20for%20example%2C%20we%20can't%20average%20the%20data%20in%20order%20to%20get%20the%20mean%20foot%20pressure%20(or%20other%20statistics%20related%20to%20the%20positions%20of%20the%20steps)%3B%20we%20will%20have%20first%20to%20align%20the%20data%20(each%20step)%20and%20account%20for%20the%20different%20sizes.%20In%20image%20processing%2C%20this%20procedure%20is%20part%20of%20what%20is%20known%20as%20%5Bimage%20registration%5D(https%3A%2F%2Fen.wikipedia.org%2Fwiki%2FImage_registration).%20For%20the%20application%20of%20image%20registration%20to%20foot%20plantar%20pressure%2C%20see%20Pataky%20et%20al.%20(2008)%2C%20Oliveira%20et%20al.%20(2010).%0A%0A%20%20%20%20For%20now%2C%20given%20that%20there%20are%20only%20few%20steps%20and%20they%20seemed%20to%20be%20similar%2C%20we%20will%20only%20transform%20the%20images%20to%20have%20the%20same%20size.%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%20registration.**%20Two%20foot%20images%20have%20the%20same%20dimensions%20after%20resizing%2C%20but%20one%20toe%20is%20shifted%20five%20pixels.%20Can%20the%20pixels%20now%20be%20averaged%20anatomically%3F%20What%20does%20the%20maximum-preserving%20rescaling%20in%20the%20next%20cell%20guarantee%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Worked%20solution%20%E2%80%94%20Exercise%203%20%E2%80%94%20registration%0A%0A%20%20%20%20Equal%20dimensions%20only%20make%20array%20arithmetic%20possible%3B%20corresponding%20pixels%20need%20not%20represent%20corresponding%20anatomy.%20Registration%20must%20establish%20that%20spatial%20correspondence.%20Multiplying%20the%20resized%20image%20by%20its%20original%20maximum%20divided%20by%20its%20new%20maximum%20restores%20that%20peak%20value%20only%3B%20it%20does%20not%20conserve%20pressure%20integral%2C%20force%2C%20area%20or%20anatomy.%0A%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%23%20Image%20resize%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(datas%2C%20infos%2C%20plot_apd%2C%20plt%2C%20steps)%3A%0A%20%20%20%20from%20scipy.ndimage%20import%20zoom%0A%20%20%20%20datas2%20%3D%20%7B%7D%0A%20%20%20%20(_fig%2C%20_axs)%20%3D%20plt.subplots(1%2C%20len(steps)%2C%20figsize%3D(14%2C%207))%0A%20%20%20%20for%20(_s%2C%20_step)%20in%20enumerate(steps)%3A%0A%20%20%20%20%20%20%20%20maxdata%20%3D%20datas%5B_step%5D.max()%0A%20%20%20%20%20%20%20%20datas2%5B_step%5D%20%3D%20zoom(datas%5B_step%5D%2C%20(120%20%2F%20datas%5B_step%5D.shape%5B0%5D%2C%2060%20%2F%20datas%5B_step%5D.shape%5B1%5D)%2C%20order%3D1)%20%20%23%20bilinear%0A%20%20%20%20%20%20%20%20datas2%5B_step%5D%20%3D%20maxdata%20*%20(datas2%5B_step%5D%20%2F%20datas2%5B_step%5D.max())%0A%20%20%20%20%20%20%20%20print('%25s%20has%20%25d%20rows%20and%20%25d%20columns.'%20%25%20(_step%2C%20*datas2%5B_step%5D.shape))%0A%20%20%20%20%20%20%20%20_img%20%3D%20plot_apd(infos%5B_step%5D%2C%20datas2%5B_step%5D%2C%20_axs%5B_s%5D%2C%20_step)%0A%20%20%20%20%20%20%20%20_axs%5B_s%5D.set_aspect('equal')%0A%20%20%20%20_axs%5B0%5D.set_ylabel('X%20(cm)')%0A%20%20%20%20_fig.colorbar(_img%2C%20ax%3Dlist(_axs)%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)'%2C%20orientation%3D'horizontal'%2C%20pad%3D0.1%2C%20aspect%3D40)%0A%20%20%20%20plt.show()%0A%20%20%20%20return%20(datas2%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%20We%20can%20now%20calculate%20for%20instance%20the%20left%20and%20right%20steps%20with%20the%20maxium%20pressure%20of%20all%20corresponding%20steps%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cm%2C%20datas2%2C%20np%2C%20plt%2C%20steps)%3A%0A%20%20%20%20max_step_r%20%3D%20np.max(np.stack((datas2%5Bsteps%5B0%5D%5D%2C%20datas2%5Bsteps%5B1%5D%5D)%2C%202)%2C%202)%0A%20%20%20%20max_step_l%20%3D%20np.max(np.stack((datas2%5Bsteps%5B2%5D%5D%2C%20datas2%5Bsteps%5B3%5D%5D%2C%20datas2%5Bsteps%5B4%5D%5D)%2C%202)%2C%202)%0A%20%20%20%20(_fig%2C%20_axs)%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%207))%0A%20%20%20%20_img0%20%3D%20_axs%5B0%5D.imshow(max_step_l%2C%20cmap%3Dcm.jet%2C%20aspect%3D'equal'%2C%20origin%3D'lower'%2C%20interpolation%3D'nearest'%2C%20vmin%3D0%2C%20vmax%3D40)%0A%20%20%20%20_axs%5B0%5D.set_xlabel('Y')%0A%20%20%20%20_axs%5B0%5D.set_ylabel('X')%0A%20%20%20%20_img1%20%3D%20_axs%5B1%5D.imshow(max_step_r%2C%20cmap%3Dcm.jet%2C%20aspect%3D'equal'%2C%20origin%3D'lower'%2C%20interpolation%3D'nearest'%2C%20vmin%3D0%2C%20vmax%3D40)%0A%20%20%20%20_axs%5B1%5D.set_xlabel('Y')%0A%20%20%20%20_fig.colorbar(_img1%2C%20ax%3Dlist(_axs)%2C%20label%3D'Pressure%20(N%2Fcm%24%5E2%24)')%0A%20%20%20%20_fig.suptitle('Plantar%20pressure%20during%20walking%20(maximum%20values%20across%20steps)'%2C%20fontsize%3D16)%0A%20%20%20%20plt.show()%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%20It%20doesn't%20work!%3Cbr%3E%0A%20%20%20%20We%20need%20to%20perform%20image%20registration...%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%20Checkpoint%20questions%0A%0A%20%20%20%20-%20Which%20coordinates%20correspond%20to%20array%20rows%20and%20columns%20in%20these%20figures%3F%0A%20%20%20%20-%20Does%20bilinear%20display%20interpolation%20increase%20sensor%20resolution%3F%0A%20%20%20%20-%20Why%20is%20the%20final%20left%2Fright%20maximum%20image%20presented%20as%20an%20unsuccessful%20anatomical%20comparison%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Checkpoint%20answers%0A%0A%20%20%20%20Rows%20follow%20the%20file's%20X%20direction%20and%20columns%20its%20Y%20direction%3B%20plotted%20horizontal%20coordinates%20are%20Y.%20Display%20interpolation%20does%20not%20create%20measurements.%20The%20final%20example%20preserves%20the%20original%20warning%3A%20resized%20steps%20can%20still%20have%20different%20orientation%20and%20anatomical%20alignment%2C%20so%20their%20elementwise%20maxima%20need%20not%20refer%20to%20matching%20foot%20locations.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Problems%0A%0A%20%20%20%201.%20Convert%20a%20pressure%20of%2020%20N%2Fcm%C2%B2%20over%20one%20square%20sensor%20of%20side%200.846591%20cm%20into%20force%2C%20assuming%20that%20pressure%20applies%20at%20one%20instant%20across%20the%20sensor.%0A%20%20%20%202.%20For%20the%20first%20supplied%20APD%20file%2C%20state%20the%20array%20shape%20and%20maximum%20recorded%20pressure.%20Can%20you%20determine%20when%20that%20maximum%20occurred%3F%0A%20%20%20%203.%20A%203%C3%972%20array%20has%20X%20spacing%202%20mm%20and%20Y%20spacing%203%20mm.%20With%20zero%20local%20origin%2C%20give%20the%20%60imshow%60%20extent%20in%20cm%20using%20the%20notebook's%20row%2Fcolumn%20convention.%0A%20%20%20%204.%20Which%20operation%20is%20sufficient%20to%20make%20anatomical%20pixelwise%20comparison%20valid%3A%20changing%20a%20colour%20map%2C%20resizing%20to%20equal%20array%20dimensions%2C%20or%20establishing%20anatomical%20registration%3F%0A%0A%20%20%20%20%2F%2F%2F%20details%20%7C%20Final%20answers%20to%20the%20problems%0A%0A%20%20%20%201.%20Approximately%2014.3343%20N.%0A%20%20%20%202.%20%60(32%2C%2015)%60%3B%2036.5%20N%2Fcm%C2%B2%3B%20its%20time%20is%20unavailable%20from%20this%20APD%20file.%0A%20%20%20%203.%20%60(0%2C%200.6%2C%200%2C%200.6)%60.%0A%20%20%20%204.%20Anatomical%20registration%2C%20with%20its%20alignment%20accuracy%20assessed.%0A%0A%20%20%20%20%2F%2F%2F%0A%0A%20%20%20%20%23%23%20Go%20deeper%0A%0A%20%20%20%20Read%20Pataky%20et%20al.%20and%20Oliveira%20et%20al.%20below%20for%20registration%20approaches.%20Compare%20a%20raw%20pressure%20time%20series%20with%20its%20per-sensor%20maximum%20image%20and%20show%20which%20temporal%20information%20is%20lost.%20Keep%20original%20physical%20spacing%20separate%20from%20any%20resized%20display%20grid.%0A%0A%20%20%20%20%23%23%23%20Video%20lectures%20on%20the%20Internet%0A%0A%20%20%20%20-%20%5BMIT%208.01SC%20Classical%20Mechanics%5D(https%3A%2F%2Focw.mit.edu%2Fcourses%2F8-01sc-classical-mechanics-fall-2016%2F)%20%E2%80%94%20the%20force%20and%20impulse%20lessons%20provide%20the%20mechanical%20background%20for%20distinguishing%20instantaneous%20force%20from%20a%20map%20of%20maxima.%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%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%20References%0A%0A%20%20%20%20-%20%5BPataky%20TC%2C%20Goulermas%20JY%2C%20Crompton%20RH.%20(2008)%20A%20comparison%20of%20seven%20methods%20of%20within-subjects%20rigid-body%20pedobarographic%20image%20registration.%20J%20Biomech.%2C%2020%3B41(14)%3A3085-9.%20doi%3A%2010.1016%2Fj.jbiomech.2008.08.001%5D(https%3A%2F%2Fpubmed.ncbi.nlm.nih.gov%2F18790481%2F).%0A%0A%20%20%20%20-%20%5BOliveira%20FP%2C%20Pataky%20TC%2C%20Tavares%20JM%20(2010)%20Registration%20of%20pedobarographic%20image%20data%20in%20the%20frequency%20domain.%20Comput%20Methods%20Biomech%20Biomed%20Engin.%2C%2013(6)%3A731-40.%20doi%3A%2010.1080%2F10255840903573020%5D(https%3A%2F%2Fpubmed.ncbi.nlm.nih.gov%2F20526916%2F).%20%5BDOI%5D(https%3A%2F%2Fdoi.org%2F10.1080%2F10255840903573020)%0A%0A%20%20%20%20-%20%5BZebris%20FDM%20hardware%20manual%2C%202015%5D(https%3A%2F%2Fwww.zebris.de%2Ffileadmin%2FEditoren%2Fzebris-PDF-Manuals%2FMedizin%2FHardware%2FAlte_Versionen%2FFDM_Hardware-Manual_151203_en.pdf)%20%E2%80%94%20historical%20model%20specifications%3B%20consult%20the%20%5Bmanufacturer's%20manuals%20index%5D(https%3A%2F%2Fwww.zebris.de%2Fservice%2Fdownloads)%20for%20your%20hardware.%0A%0A%20%20%20%20-%20%5BMatplotlib%20%60imshow%60%5D(https%3A%2F%2Fmatplotlib.org%2Fstable%2Fapi%2F_as_gen%2Fmatplotlib.axes.Axes.imshow.html)%20%E2%80%94%20coordinate%20extent%20and%20interpolation%20semantics.%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
4219152d88563758738b3b097d438f0b