From c3e273284d38e06aed6a744e187db29857e2fd22 Mon Sep 17 00:00:00 2001 From: Raymond Chia <rqchia@janus0.ihpc.uts.edu.au> Date: Thu, 16 Nov 2023 19:12:23 +1100 Subject: [PATCH] e4 time data --- __pycache__/config.cpython-38.pyc | Bin 1480 -> 1072 bytes config.py | 31 +-- .../__pycache__/ardregression.cpython-38.pyc | Bin 3092 -> 3108 bytes models/__pycache__/elasticnet.cpython-38.pyc | Bin 2849 -> 2865 bytes models/__pycache__/knn.cpython-38.pyc | Bin 3270 -> 3286 bytes models/__pycache__/lda.cpython-38.pyc | Bin 3126 -> 3142 bytes .../linearregression.cpython-38.pyc | Bin 2753 -> 2769 bytes .../logisticregression.cpython-38.pyc | Bin 3244 -> 3260 bytes models/__pycache__/neuralnet.cpython-38.pyc | Bin 12748 -> 12764 bytes models/__pycache__/resnet.cpython-38.pyc | Bin 9355 -> 9371 bytes models/__pycache__/ridgeclass.cpython-38.pyc | Bin 2766 -> 2782 bytes models/__pycache__/svm.cpython-38.pyc | Bin 3008 -> 3024 bytes models/__pycache__/svr.cpython-38.pyc | Bin 2906 -> 2922 bytes .../__pycache__/xgboostclass.cpython-38.pyc | Bin 3520 -> 3536 bytes .../__pycache__/datapipeline.cpython-38.pyc | Bin 33291 -> 25874 bytes .../digitalsignalprocessing.cpython-38.pyc | Bin 27533 -> 27016 bytes .../__pycache__/evaluations.cpython-38.pyc | Bin 3866 -> 3842 bytes modules/__pycache__/utils.cpython-38.pyc | Bin 11294 -> 11310 bytes modules/datapipeline.py | 249 +----------------- modules/digitalsignalprocessing.py | 40 +-- modules/evaluations.py | 2 - regress_rr.py | 77 +++--- 22 files changed, 71 insertions(+), 328 deletions(-) diff --git a/__pycache__/config.cpython-38.pyc b/__pycache__/config.cpython-38.pyc index da6e31c3da59664bc76d25f4e1570bf3e01dc3f9..5bb18e1613b8d7cef640aae6b04dcc3e7fb98408 100644 GIT binary patch delta 549 zcmZWkyG|QH6rI^wn-$oAAJ`@d;Sm~3AxlA%2tjNXBNreCyv;P$#&<D8*1MZoBOVRk zVC@eiC0$BBfCBi0X{q>y6e!mQSy6IFb6ztVow=R(WmtAPJx*{Q?rir5LmrsFM@RD+ zcXW#YgcG2gg2pvqoFVI=_pOCXNW&ydb#$JFX~;mP!}ug*ku^RAImmm{JOeXs<~R$5 zb@HN$s7k|Zc9gvusn;X*2GtzT!CRikx8}W>Zh;plfd#klEh(>IkuMef6f6zx4ZPz; z$RCjMa_upTr5|AcXYo(kjGt(KUc9G-C>HviGF3+CIlaR`c2&X?{>j-zCC;+d(u#DW zP)MgI0)M6Lc&1{f!oT<u+w9|}`Ol&F`h2lmQVDCjYVW8-b-z_R;K|C?7P3m#ckQ8X zG<I6G_@4FRJ-vFVnANEBv05F&-KJvEc_asgm0?wym6lcCzanxGgCYE0GmnC<Ys&BK zBjK2#436D)FESk|od4>!1OHHTK7{AWSnmdK;<+36X%c-x(CPEa>Dr4NaVqX7aw$x; K6g6m4Gw2^|wvF-t delta 938 zcmZXR%TgLa6oz}I2L$9Y2nym2yu@G(n!85I1R2mN9WjhVt2a|r4pJnD7GOo)@Cr#L z%WSjADn3T?0NKnoD|Xo?o1_m=#8kSgzyANz=S=r>Upc-EDg}?nMR@!8UMV$fgnUPH zy#=^=%146<gaBa#1SWvUM4*g<#3T^kD$y46fQNa(3qFv+UzV5;hL{Wi2tu$-nIDGv zEV3aOflxKTf)FkRUk<})lJr!BtFcaOydRtBtI58a;%X405QAx$fmxV?8!!*8n?S(@ zaae#`un4yy0ZZio8v!>g!yO3o1BH0{9AI7o?w0K=-0_qjZWI+iT!gR2d3^%zbuz~I zr~46JG0q*<QZ@ni*(5w*Q~Y-xR-?zUCoCoqcvOnLvcD1PTd=~WYhGCG`RDMMO+!d0 z@wIH_2PLF^&Tq6mgaE{VX%qGx+gB?eetxSyF%N}zt+t2@PQ)O>jqo762p>X5_z}a1 z5kv?PMvNjNh%tnO;4e(tlZbJS$|8SLi=M(!T(BIc)nfDLq<(DKs+F2_c7B;Oo#Jx9 zXq1Z05-cgjX3?UrE49m2^O?AsjL%p$C9_f3v~0Wi+=0%VS}MPt$s1YSvTfkR?5T7b ztzFd$I6HTZZjSj?Z2G)fE}hylcur==&=oUD(=F!R$sHJ5-8w^6EZ1(XYgL8Gy$w`d zFJyE>%QN4<k^cgk<-)DI1(y4-Hg=fjn$z+YRrXZ2FpyO@jjXnB(Z)riKF{ySaww_& zl%c5kPo%!a10DRDH9ynH`qGP&+EJyPIK8kO$>S3^tCrUJm6FCGha_C<Vo&#Hw<wu@ eDKHxqM8f-TNpw?La0w1k7G&zeJkia)osU1L+T?2h diff --git a/config.py b/config.py index 7a405df..0e64588 100644 --- a/config.py +++ b/config.py @@ -1,10 +1,8 @@ DEBUG = False -NROWS = 1008 -MARKER_FS = 120 BR_FS = 18 ACC_FS = 100 IMU_FS = 120 -N_MARKERS = 7 +PPG_FS = 100 ACC_THOLD = 10 WIN_THOLD = 0.03 @@ -18,39 +16,24 @@ MAX_RESP_RATE = 45 # BPM TIME_COLS = ['Timestamps', 'Event', 'Text', 'Color'] -MOCAP_ACCEL_SD = 0.00352 - TRAIN_VAL_TEST_SPLIT = [0.6, 0.2, 0.2] TRAIN_TEST_SPLIT = [0.8, 0.2] import matplotlib as mpl -mpl.rcParams['figure.titlesize'] = 6 +mpl.rcParams['figure.titlesize'] = 6 mpl.rcParams['axes.titlesize'] = 6 mpl.rcParams['axes.titleweight'] = 'bold' mpl.rcParams['axes.labelsize'] = 6 mpl.rcParams['xtick.labelsize'] = 6 mpl.rcParams['ytick.labelsize'] = 6 -LOW_HACC_FS_ID = [1, 2, 9, 11, 12, 13, 14, 15, 16, 17, 18, 20, 21, 22, 23, 24, - 25, 26, 27] -NO_HACC_ID = [3, 4, 5, 6] - -# issues with marker data on MR conditions: -MARKER_ISSUES_MR = [12, 14, 17, 18, 26, 30] -MARKER_ISSUES_R = [12, 14, 18] -MARKER_ISSUES_M = [12, 14] -# issues with imu data on MR and L0-3 conditions: -IMU_ISSUES = [17, 21, 23, 26, 28, 30] -IMU_ISSUES_L = [15, 17, 21, 23, 26, 28] - -# issues with imu data on MR: -IMU_ISSUES_MR = [17, 26, 30] - DPI = 300 -FIG_FMT = 'pdf' +FIG_FMT = 'png' from sys import platform if 'linux' in platform: - DATA_DIR = '/projects/CIBCIGroup/00DataUploading/rqchia/aria_seated/Data' + DATA_DIR = "/projects/CIBCIGroup/00DataUploading/rqchia/"\ + "aria-respiration-cal/" elif 'win' in platform: - DATA_DIR = 'D:/Raymond Chia/UTS/Howe Zhu - Data/1stExperiment_sitting' + DATA_DIR = 'D:/Raymond Chia/UTS/Howe Zhu - ' \ + 'Data/1stExperiment_sitting/respiration-calibration' diff --git a/models/__pycache__/ardregression.cpython-38.pyc b/models/__pycache__/ardregression.cpython-38.pyc index 44a34a21a2c188b4f8fe15656377cd2e5f00972e..623dec49edcd93f7734e1624faade447c65721f8 100644 GIT binary patch delta 130 zcmbOtu|$G9l$V!_0SK0?3f;(kk(tqH@?B;r0o|h1;)2Yg#FEVXJl*8PoXy{vqge%_ zc=O^j^V0H*a)A<MsZpDgIQtpp{eik~am2^xCT8Zv$7@R7V#zE>NxH?FSDIT;S>!lb efLor?bFu-qA!F3!ByI~JIh$LT(SPzuZf^jaNhzKH delta 113 zcmZ1?F-3wql$V!_0SIE<MK^L^WM(v)e3w~jGdoK(tH3SZy!gz#wEUvn#FEUi)LWa2 zIQtpp1A&Tfam2^xCT8Zv$7@R7V#zE>NxH?FSDIT;S>!xffm@!@d$I$!A>*ydMcfuZ Oay7RuW8mbQ+};3u*(1{c diff --git a/models/__pycache__/elasticnet.cpython-38.pyc b/models/__pycache__/elasticnet.cpython-38.pyc index 5201bebcea6d268e52f185dd3958282a29cddda8..d0c83c0abefc1c8776068d987e4f095e7e2d26da 100644 GIT binary patch delta 69 zcmZ1|wo!~bl$V!_0SK0?3f;)f!>nzupOK%Ns$W!?oROKRUr>~vm6}{qte;qvnW$To XT3nD>lvt9PpQoFgn6uf4`8_)T%YPQv delta 53 zcmdlewor^al$V!_0SJCJxoqU-VV2g{&&bbB)h{Yc&d5yEFDS~-N=+^))=w<TOx*0m H{GJ^EjFS+l diff --git a/models/__pycache__/knn.cpython-38.pyc b/models/__pycache__/knn.cpython-38.pyc index abf30b8ab2d7016cee9424f1d9f6939f1b07a579..a274e6e23cb14cdf25a14d6b68a0b165a2ae3e51 100644 GIT binary patch delta 69 zcmX>mc}<c#l$V!_0SK0?3f;)<%c5<epOK%Ns$W!?oROKRUr>~vm6}{qte;qvnW$To XT3nD>lvt9PpQoFgn6tT<C71&M>|PfM delta 53 zcmca6c}$W!l$V!_0SI=sxNPM1Ws%m<&&bbB)h{Yc&d5yEFDS~-N=+^))=w<TOx)be H63hVrn-CD4 diff --git a/models/__pycache__/lda.cpython-38.pyc b/models/__pycache__/lda.cpython-38.pyc index e3e967574042540a88a8df29240db0a4c2a0f825..5231a52ca76b1fdedac034d67c4e2bd4759ab679 100644 GIT binary patch delta 75 zcmdlcaZG|cl$V!_0SK0?3f;*4npxXIKO;XkRlle(IU_Sszn~~TD>b>KSU<5SGf}rF dwYVU&D6u3nKTkI~F=w+NOF27Z)Z|X?wE&ZT8FT;u delta 59 zcmX>mu}y+Il$V!_0SIbr)Hia!W|r2_&&bbB)h{Yc&d5yEFDS~-N=+^))=w<TOx&!< NQqInJYw}F)wE+4567~Q9 diff --git a/models/__pycache__/linearregression.cpython-38.pyc b/models/__pycache__/linearregression.cpython-38.pyc index 3ae3c03e38afb0f891cd328d5b1330b4856c5f5b..5af69ede993292168663e1df6cdf342d2e918b5b 100644 GIT binary patch delta 54 zcmX>odQp@+l$V!_0SK0?3f;)f%*^OInV(roK({EhxFEAAu_QA;Pd7O+XR{_VD?4M< IWPPql0DcD!nE(I) delta 37 rcmca8dQg-*l$V!_0SLU@MK^LYGc%e_=4Y1LY{|^Z&UkCGJ=Y`vjx`73 diff --git a/models/__pycache__/logisticregression.cpython-38.pyc b/models/__pycache__/logisticregression.cpython-38.pyc index 524dd77bd435b5a55c557bcce13715362dd509bc..1123200fa3a91bcd964aadab525b1a2ca168260c 100644 GIT binary patch delta 54 zcmZ1@xkr*al$V!_0SK0?3f;&p!oui2S%F1LK({EhxFEAAu_QA;Pd7O+XR{Sc8#`mv I<b&L=0fM&>8~^|S delta 37 rcmdlZxki#Zl$V!_0SI*5MK^MburQiWR$!6Z?8VZ?&UkC`Mef%CkI@N7 diff --git a/models/__pycache__/neuralnet.cpython-38.pyc b/models/__pycache__/neuralnet.cpython-38.pyc index aae3d8b200118e5ce56a46201c442b275453ebb1..02fcc1fffdf3521fed55f79a6cb176a8e820878c 100644 GIT binary patch delta 48 zcmX?;d?%SZl$V!_0SK0?3f;&(m6_3Q@<L`Q0o|h1;)2Yg#FEVXJl*8PoXxwL1@!=I Cx({>! delta 31 lcmcbUd?uMYl$V!_0SKH+9X4`LWoFcyypUOH^J!*5Jphbj2!8+o diff --git a/models/__pycache__/resnet.cpython-38.pyc b/models/__pycache__/resnet.cpython-38.pyc index 997d4faf545fc18d31cfa4a588a7f19135466105..ff17be87b4954de445b870d25f0cf8f6bd67ad48 100644 GIT binary patch delta 291 zcmeD7obAaS%FD~e00c``g>K|t&%|gwc{h`kfNoK0aY1HLVo7Fxo^Ent&gQF3f4GdI zm{SUJqPR+m5;ODSQ;Op&kl2;CIAG#Y9A$|)5c$o_d@+oSZIcuDE!cX1wrppZ?5`{~ zc?*9UW6$IsWr@wk0&<+(oj{qQE)dZ-d7`o~P^v)EiE%PW0ps+^XC$S8WPm`}W;>~$ zETS_&>fAttJBaWA5i=+I$eS_F0%_hnO@1mf78AXc9U&&l&IalzU}Rt@<^wV~n1KWX b!+$P5jubAPqS=!VDz~sr2Z{ih-YO0N{x($Z delta 274 zcmbR3+3m?4%FD~e00g@87&mgSXJXWzyqigC^HZijTt>H;Qwnl!ag`J$X6D7G6vtN} zu`6$Jz{GEHlqKds<TnfR#V|5<PcGoMV4DaubUVZ3cxAE4NBGkiCr+NDEV0>HK#r5U z4=7XA4<aT{UZ^Y#lxmQ4Vw?d|z&K~}9Z6{*nII6h*-z>xi|AaCIyVsE4kA22#JtHd z@@9<lL7F!&lb_0r#l$FOM~I2C3xGNb7#SFf`G5=#W+1`9@Sls1BZW(+Xu;%*$}Mbj LfFeL<w2A`&I^<FN diff --git a/models/__pycache__/ridgeclass.cpython-38.pyc b/models/__pycache__/ridgeclass.cpython-38.pyc index 87bc5cbb037961543d9bb233ae017c2a17dd5de7..6cb74a1220e288f5ef83b1e9b349edb87b6e0ff6 100644 GIT binary patch delta 69 zcmX>ndQX%)l$V!_0SK0?3f;)f&a7>(pOK%Ns$W!?oROKRUr>~vm6}{qte;qvnW$To XT3nD>lvt9PpQoFgn6p`zc_BLh;W8H2 delta 53 zcmca7dQOx(l$V!_0SLsJT{d#FGfV61XXNLm>K7FzXJjVo7Zl}Zr6!jY>n9dvCT_N6 HUdRprdBqRM diff --git a/models/__pycache__/svm.cpython-38.pyc b/models/__pycache__/svm.cpython-38.pyc index b4557be071ba83d26bcee4d2972778b589c96442..c7a4837d50c610588b2c2fd7cb525e3d66719b45 100644 GIT binary patch delta 69 zcmX>genFf&l$V!_0SK0?3f;)PmRZ|EKO;XkRlle(IU_Sszn~~TD>b>KSU<5SGf}rF XwYVU&D6u3nKTkI~F=z8-=C|ws{lFMd delta 53 zcmca0en6Z%l$V!_0SKI0T{d#BWtP^^&&bbB)h{Yc&d5yEFDS~-N=+^))=w<TOx*mK H`7JvDl@Sqc diff --git a/models/__pycache__/svr.cpython-38.pyc b/models/__pycache__/svr.cpython-38.pyc index bf9763815f158510f638928fd6c517c0d683c37c..42f47b85e381881482dc4bdebc4ccaae6189656e 100644 GIT binary patch delta 75 zcmca5_DYO9l$V!_0SK0?3f;(^#jI_ipOK%Ns$W!?oROKRUr>~vm6}{qte;qvnW$To dT3nD>lvt9PpQoFgn6r5Tvm85P)a3PCs{xG!8Gir( delta 59 zcmaDQc1w&ql$V!_0SG$WL^pD0F-vRcXXNLm>K7FzXJjVo7Zl}Zr6!jY>n9dvCT?E9 NEXU4xYw~`s)d2V>69oVO diff --git a/models/__pycache__/xgboostclass.cpython-38.pyc b/models/__pycache__/xgboostclass.cpython-38.pyc index 4e8ed4221b837e31ab20581b164e21975fde3637..64985e5a3d5d0000725338d7d6a4ebda1faa7123 100644 GIT binary patch delta 48 zcmX>geL<Q#l$V!_0SK0?3f;&(g@w^^@&Xnq0o|h1;)2Yg#FEVXJl*8PoXxvf*f;@B Cg$|zp delta 31 lcmca0eL$K!l$V!_0SNS3T{d!0VPQ0!ynsb&^C=cKP5^lM2dMx6 diff --git a/modules/__pycache__/datapipeline.cpython-38.pyc b/modules/__pycache__/datapipeline.cpython-38.pyc index 0adbf5175d6feae368455db0e588886d4cea42ee..527236c49a3e1e135556397291a90d4d3a38c2f8 100644 GIT binary patch delta 9259 zcmb_hd2m$6nV)_$8jWUjp#uqtL*g)u1PCF-B@hUZFp?051jb{`_-Xn{8kmcIBaj4m zjE#*GpP>_H9Up-tUWaVrW99hRxN4Isuj6CwtP_`=efGw+<-I6xymlPtaBQ>Ruixlk zkgNPhQ1MNlU;p~M`s;qTozl*{#Pav#<#`?S@AZG$V?25IYxy(Tna68eSc*A#C!fZP zPO-omUd&5QIRa~WDW6WiO~yK2c0c3ge8wqPU_I3;s8-2mQmvV9PuJ)0s#95k4e44n zpG&<Pd6&_`=h5i-d;#@t;#cs6{aPPOw=Uv-YTe9t7^!u<hKAMh#niBc@8nB)9YJa3 z%XmFOXyeOy1O0C0yLcmCNj+Ec*_`nee4%3KGPcpetM1qMYQBazv{Rqmqfz@>;@rg7 zQG3VacIsJAGn)B^Q(3zMoqQv2p(VC&b?{Am^C<`4e3KUFqS_YTO0`z1?Vws4-%7Qu zM%PWwz)q@P$+uB`8};s@T08HcS_jp3kG`NWR_wI0wzO{Av(?J!*|xnkxOqos_vk0i z&5Q+PbJoYpmXRtx*;F?Wj~aF2aA+W`*Cj;!pb<)%b-D=aON3!2!a`4m<FO?nJtDi^ zepV$<xL2{|^2hG2^>xHRfQwD)sbm$HMktt!2f3a!lHsVaff`MXh=Yknxg`6A8cgtO zmbP@6rG*AE=X=*h!e%lQk0zQo%Q>DUwBUA6WYq$iBx*3zX}Q2x)S_i71m38g1OfuG zNq*p|WE*5|P7m?XbBg<Cf`wZ&(T~M;2eeKC(OFObms7bxf$=-VM(Pe^M~8zv97<Zw zNN*$)W?m>B<5(r4_ZpFI8gIIZI9L($Fma`PE2nMyTB?g`5JrTyoMk2=;iM=)(>9O{ z+2!{e$sibqA#!sc4H*+%=V;7Z&6ZbDQ<sfW6RW6Vxgz11k;y1$UB3}Ch7zJVD1YW# zPJ92oubr)z8**na>!ewJuV}|)uX!k(2r3O*p0F8A3OyVXyU^u6bW|7prs$S;<j$<l z09vRv5)7F~f>9$m5a-v(mvS4~b!YOf-n)}#i`^hSL`ay}hPWC;E$vcEi~VRg01^br zSfD@{I-kUUP(GSBgX!|cyq}Qq-kiTdS<z%c*t{-fBi0b>Tjl%t+Ztgg=gH`Lhpp^z zED_N|hCfFXW9jQabdW-jX+$h%R8NR~GEz|4-;2fokw5{D2cv_LWSG1pWSFMfgXOj* zV6lXi&HI9|-hi75q=Bh0S*4LUZLKdHG0aK2J}%!cn8Ok>zwqT$2rIULz-~kp5mK1K zdMQkCkh;h`jhK~V#0JSJ$mzshOj?f~S2z+6(Nt`~aw|2PB8u)9NF2>9tWa7kqVz7h z9o5uzsT{35g;^(yH)G+%opN~EEOu0WbJ~-<Qn5DUB582T)gOuX`dwlOjZU-oV8Bgs zpf-izGN!P0$U({MKAK}f0S<DYd@Wb=up-T?6=~w6e7xw5BIQg~)a}m}Mf4+tytjA( zYnK05T*(IITg5fLNuXt6$#nJuxv->~ojH?NBCjp^ZUrWvXO>GJ3Y&h9xEV}t1vw}y zO1I7X3W}3hP}Rx<#Bg*lNWx7FKP_)5t!59(@0T8EY@lvJ0%K8}ET1lfJ{+_?9Q&~C z{t!w~lRrxwkWJI)6)MqBT1UpFSCl?SBTO$52XnJr=4CUPI5+yh^jzjMsL_sd{ql*j zg(Ua4%gSqP&5w{ND)&;$L@*NDBE_5J$0|79B4?McNqrYx%H@>O^OU0_M(aV|XXPdh zGdWfhXE7EiEoU;C2;|0(7$Tx4f_)LaKT|-{ARwEW&7<#SnrO}?;vgM*X*b$Mw<g~x zFROTz+9(M622CTFH2dgq8Bif2lqCzVE+3sU;{n!9wnxhnCNV;#^Gw{JCW$2d2yB9^ z>m<q#gM1%EvGrQn=3p<5F7X%|5qi{kk(33M<rRO2`VT>V1TtCtEtMtgUAeb%p65yG z@-xvhda`l}O96`bdk{boqjskP0>So(exm2IY&b_T<WfzLi9JEBRxTVMn9!5tnlT%g zV)A25QMjOz%R)r~=H@8BgPOACx>+-do}oq(p+_msObXE>Pgc&7r)Ke~;P!|~wu3dE z!gL#!_y;s7F-?JnBAIO(lO;tHtZ53+fG%Pb|CGhdWXf-4|LkJ+tUNaRG#xh1IW>hH z;C~v#b~L$uPVMSRatF6Ob6~Kqj{<=5nk6<T>QEj~#PV4od4iXT=jGWsvskBmys=S! zG^gCv?eG`Lx~fI&fZSI#^BTu-N6?kb;@Tn2TuQ&rLz-C0UDWE1xp@|T)4iSP-X89z z)@<s{#xHjeM^BgKu(Ieh9UQXU>Swu_EC0Q!)$OrzC<e&2)yw6P>SeVVoA3mK;aE5s z46X+L=>#7>Z2!qOtLMuTD+}eBng+d!dQ?QefI(!)IA<x|k|46lCqnUvsm@L689y>{ zypx`<qCw}K;#U~!LCB2h6ztXMISGv{tSw{ha#8IHdE<r|a!p-R>rR^C*VH0Hm7U^W zsA*yW@oQ8kF~Jgf;b?*)x}DpYJLNNVPp7PG0yr3rnf@Fri!!WL4Wbldb9#moMyn8U zp_p1ZTgY<S1n^a$-=ilIkzpLCDl%o8hX)N~#Gr79-H3lxJZx)2u9bz{&b(}EjuK*3 zkcNf)4m0+hslTW86>#|vka3~WhR1nN-kSVbeJL|W->lDJGyfYiRLHMF=^I4+x#FKu z-X}j@KD*={6u${_h=}FlBA$>-8s@K=V6Ei;6ZAR<xR|^W+Q!i0_yF37{A$CYHY+O} z<Hiu3L+-c;8?oeAf^-3MNbrL};uY*u3jQUvWv~_hOKn4P&5Av&LEg1u;f$%q{DH<C zlfPK8kon{vS1h>Zb?~u3-U3n5`cITT00BpVDU+5`22qc;pA%U%=9wPmDe|~I9#5Vp z+mq{Yil4(X<ztP<Y8q%934RIYECrbg7=WbYo|QN4`Vd3z0SOZ!A-spOY6Xk5vD>Lh z783EkN$3EKg2!+yMD0N{sf*+(>0fp7z+b?mib$7ov^Mc6mC2tJAO&rF8ERFUR7$)H z^F9a3@C4u3B1VkgCOxZ9HdKM5Q<xY$vDwe2n46uRD@UJQ{TSP{mWEvT{NlxnHb6=q zZowqw6;8d^w6cy47{VX}F=Kjcg15ie2Kuf;KC*T<TOwK0+G@3-46I(0&f?zqV2qpJ zVsd{IZ}}q@_!G#VL6jL>M9D!46%51+GQns<@1M}P>m^%P%swF<mo&Mkj(_Ig5-}VB z#vK8Tvw)K?I_>CV+{Lp_<pf-uLMmNkv$&t<a4+4J-MmKfb%`0L9WF<pl;Uiy<?FVO zYD9{W>*T!k^JLfhX4WL{SU;EDDj!>adW(w4E?bKh>mG6L=e7P4x<Cyk3}J7ihj6G9 zHsDPk{lPG|li!8tS|o38o>z4O#n*^fzOhj}Y=<fV7nfFZZ3F33*}^zWa?hM#Fci`0 zkPF)4fz7FfUx71J$o37h<e?2mc0;Y=1tMfnYQ8%7aC$3nY1USjO8CXKXrB<bZOCJ{ zK9vl=!(_w8KWxDm;+Ti=*n{QjjmINm5t`FCKgQ2%_SUk5(Qgb*!ijs&drU@KwpBqE zh~3cy9UCH>YT|k@Nyp#U<Qpy3a}=UkFa;YC4xJ#$i|)U|{4X{-ebcvD4PelUs}#d@ zXU1OCh3n5uzO&iv_z+9|4ohivXhwufV-Mtx2Rfj-R3M7UUm#`J91=(w+gu@^+R|A2 zTkw2;f{*w=G)yu5GbYPgJJvxtv?QJ%th_!EkA}^7UtG`ulHQ1D{sIOUnS8LdWBmmm z^^-MZ4a5h9Ny@CjcqjN}<H#mo6aGtGNEr$g;E)frR?DqzHP@zLEXQ1B9t&s+CAZ2- z6#DT=8etvZx4^_M6)$LMHClj2Ax)>-tFqa-^3}HL#&@YXK!_sHm>9&MiJdJ4K&4n; zXut>^3aT^qBPQo>y-NOQN1lAB{kDQCnlqBUX?M+1y48!dazjVi{31-82XYu3m!qT{ z3Kk?%ARTg~qq0yTQKRQ#%oXyXj>U^ERf|=G@RXpe-y9T%eZcv!*>d^nu1Z<b`C>^G zF&xS59*jnHF+7Ij!_LwzUj_%jC<(nvB?_*WL2BP#y?6!CW#F0yT&BIK4XbhtR+)Tc z`&+4bV8}!@=F)%rfa#%@I;xGh$dYT6qQrdE^UV-Fy&MU1Bfd16SmF1HFM(d=9ls~u zmX9t913`nXs7X`&0xK7#6+KzJMLQNQS_V8Ak-4EfYzY3Pl89QV@AzF&6^$G5wuC}P zWK6Ke&cJGAnDj~*i65n~Iv%;wUOH8@QqI{SKi=8)<*XyPtNe27IK6Auf~izNZ->dC z4v;qX^`kHD%4fFw6xf!hq%dKA6%fKJ5CZZU%LmKGgBbD!T#>~FkPksrE_W|Va33*^ z2+TyT=x(2tVG_B(F~(|#ysvv-?tGef+;P@%j*d?GS$FvkoKT{HS}965g5gRK+yTTo zkY8e@48H1wR$4KGurUvf!E*=w$%lJtyof8C>Ay+uhds5av)XaT!R&L4t|%T_JLjBZ zKeYtC^xrqJe6HHMXvU%{y=y?J7zC~$N>FM7DFyieZPTel?_hSaIVIGBNW6-ksgSt# zA(=M~0JdK!ymT|epKQ9SX0-C^e3qI^Of4;HhX04QV7YqmK3hj^{sQp{)>CNSMrkjI z(gN{why_F}UpPj0<3v1y*DDoZmFiTuRQbuc!c@*e4_a_;D+l0$NV43P3%4ivaA57+ z43QVABy2qF@V<y9FYLc!)PGG0OKm1Gj6qbw`67s78$|b|p^0`3?*Qop*$&bLvIAr% z$S&qs;s|(cYlp368jGFZ+Woxm25t1h{<<{ed|RqYvtJ1LuZ`9b$TJ7)Rcy8okW9b@ zO4MVKl=pod7Bf@+c7NIEI|m+TJ(85xL!m`^BeH%a(C{(>IuTb@B((}55X$SL3A$Uu zHpD`bndL$ANSxlgYaqf}a>e?#N_p|Rc?EbpppXm?LiCdLdRc)o1)O^-Xgw!?Ls`UO zeRm4&G*$`diw^JS0bb=F4$Xdk^H<t#<D@rL`>IQ?Y%$&5j<V?Yu+&6S@79GL>o@GP z(?s77h*+-ns6qL?vMA*oE!dhXF`OI`d$BF$7>iKCZtN$@FK`2SdvAH+-Qeo!C2v&^ z_U-bC-o<uA+Xp5P042Y;EWzP<-@}^xthZlwRpqdaG8U>&opm9qQH06DuS&f&JN2e7 zCCc|UfYEM{9*}Mj17xZwXRoD4C>QB_8Dh*O1P)eW2Rfo7W!)1OfTgAv(Cp#z&PWft zQob8$+CJfrkZn4R9`hG?d)oiivq^^2tM4dj&!HIcD@_{FB`LCtCSoOW3Amqi`B|HP zy14X;WMv0~JRYK)|8<O1r;EyemSeM1g?S~Jjp*G3qGY7RqXea7)Q64%79cg`r7sn9 z!bQd|77BYA#wb(uQRyZ6Z{o!9Fqf8J<jMBtdCNV8^jAcGg>(bY_LR_Hv1h)=BYaGr zn^P>?;!m*_`FXsB?Ufr7bLJyPia7Wl2Dwy3YJYEQqc<hm858o=!?PEw@js<W78|DL z4m>+uI>*XBM5zsV<GY%y5JwxpJFORic>%he^#;?|5H(eqUJhD&^<-$^Lrp#>zULkR zoM9O=8=9+Vn*H`dpJtMMmQNUbFl5k2B|SzSdgOB8mS<f=kM?rC`BP24W3J2t3xA%t z9z(w(=O+DJ?KwepdMcwMC5X4D<LEvHqJ(jfCRrXj75WUqHTD$nQ)(6TF`AAtO6xN= z@53z(Cl2KXA8Yc_<fGm8nwWGWI6s7viPHC|lx7-m4F$OwaM25fDNds^gKsXq;g9h( z9rE$PdLx2iQ6ex=Plk!wmN|qWYE!qO^i_}v#^b^lhp6K%_@I{{d6+lblkahPeblaO zCUE4HGUR|GdGrxW#}#$yK{FmB?6=G2qswP2o4EZ_=E_Rp9zJ>J(Y>o0uvcc~<0~>Q zAM^wt7sKRhYVO@r%)N`+rpd~o+uZ6daku>8(5zB5`s*2^<!^>&uoC&Fp|yEHNfvPj zjR<Knv9(-YHQX6QD`nzVb~2ve@uL8a5h91$h2nM?^V~KVbXnTbqoSG`VdBCRk6`44 z<dns_RRYatIHfjnKU*umJ>pNb(6}CPhB(m0ORaG)l~qKy6H}~4-@KB-${Ha-MyzS+ zZ|M_45%@wpWymbWikFR_NAcgxr#TKLw;t<nRibv<%iWLF?*yE*q}#zeV<YP8%$R2J z31VQeQ+{;pwUS{PJmRiV%I*=zFjbSkKE8OJ(ufkAeY-=Cx>fC=lI4PN(33QMz!b_V zaG;TeD&;*bH=bBnel4{G+@ZdHI=Cmpk*O19+A^p7n-ll7KM3q#D9%D?E>0iU6u+@( zqV@t#lQ~e8-u(0<hz_=`Haq2s>l;#EgA|xb9Q^qi-U2PtHz5_xE5Q)PC%yq<XQC)Q z0HQ#B2c?HVCL}rGOt(=7a&)thIMGK+cdpZ$RVbIHJPXkUZ*_|8)YsGH*Sg3q>5LIK zQk{OjgP(4BZK^i^0FAZW3Hq9<oAlUxPpXbxFP~2}`|!*va9D~HvfzfEikneXdUzP6 ze*;lZTW95o8#+@Tqps921EmTOwMUgWH=?R;Ki>k|D^cwPxei1Jc@rc7aunnw$Qh6a zLC%3Z3Q`FMPone;$g?2NJBYV>9JX^&99t^d2#8`T@loWC#`$2xXr=)UGbZmj*{GFh U@|BZyzODJ4g(*kMQJi1*|Fk-+ApigX literal 33291 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 E0W8rtt^fc4 diff --git a/modules/__pycache__/digitalsignalprocessing.cpython-38.pyc b/modules/__pycache__/digitalsignalprocessing.cpython-38.pyc index 15c4e5aac44dbc2d66247bd0293dd784e3ef8947..fca6f3076758c0f03a274c04595a7f65e80cc225 100644 GIT binary patch delta 7101 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 delta 7750 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 diff --git a/modules/__pycache__/evaluations.cpython-38.pyc b/modules/__pycache__/evaluations.cpython-38.pyc index 150f75a863075a6551abc9303dc695a4fd2022aa..1e72d2c91b98da466c7b08f0bb2136901b06b1b8 100644 GIT binary patch delta 1353 zcmaJ=%}*0S6z^{Lt6xBCAwUKBFp?D!!NeE^qahI$Z-OzEWHWZBwPAPJye%k3L!ur{ zOfx4m{sG)gJQ`1)_2wkr{0F>xa^5Vov=ZCQuW#mk|K97n(U+sSwOlTp5FhR98hzf( zjVMo>(+?+>6Rzg!uM@8RN-g(^o8g+`W{O+hRqiEhtNGDkW6IA0IzvXlegb;L&z~Et zR~_z~0UCvMAdUKFFjFBOv(<4W%U0B2y5(W3kP{wU13#kDIfh;gSrCwCztlT(DIwWO zQ1P|pyRS&!ZZ9<IXHN3&?17io;RPq~ie<Jl@uW}aAmhmwldb5-*?}(HO6-|-UrDiV zT5;;X*4(53PSkKuv8?`ksbBbV&8H-YTNuC+kToz6OaXQ}X2aNcLZBAG5GsZdN(d*} zb)z)gReGvM8zKp5L=$Yw`20Yo(Fp+AX;a0ORT#kpTAaX)h#z`1;u_hmMO=65)oRpD zO7@XQ0@op4!zaNd_Qu@J6tN6hc!3RA=U3!?5Fc??az2MC^vWi!R$)xMmo0zCq1(j! zCxt9tY8KdA>%q;wj!+=OBj+G<OrUfQVHTlHgp}mUSVECuGpUk}Ql*(6V%605-AS}R zgK%1aZSkZ>1FlDpNk~C5W&jN-X>e04t$b~bmK%XXJ?bAc)+QA$W59M5vH<Mhwm1>i zo=}QPS{YQ>r}T$qnOOs@>qrdj>5#HyJ#e`m6E%)zU9r)2mA%jGQMuVB*MS5z8rRVo zmm4GuY2Zqx4&s;dK7kDi@hBX(UTJV8fGfvjLVnlTUiQnb%#?zwXe9gX%oC4e0kudY zObM{f_<wm;$XvtKf<@F}qOvI#&e^7wvMCfObT^6ft%wt0^9lANH@|*C2r!2*k06&s z?t)wcxe#rpq$EdiQ5fG6C&H2~#mb~D%LIJ23tSJj{BQ^QS*?dG#X~{Ok!o6jxV7MK Xx?3K-reHMObP?_Fs}_}_+Ozl<0M_|R delta 1416 zcmZuwJ8u&~5Wc;)9oyt#2m}%l9)eQ{CV>J(hyV#iB7q`6gbc*m_%@EgcQ$h-C<TfH zh?=k!NKli8nwEb6?IL~yqNQSH4{Tz^r~7VpXXe{)XU5OR-i_t&<nvhrf0G}Wc(;`w zWiPiT?wt;e&~Efc1LXl`%o(8*x-X5;ePNadapi?Ru6$e#h3u9QWVSw5@&Qwso0S_^ z7U!=m-jW{sajFklA&0PSz#jbko+_<1BT<6K)wMb=wV?S>RNG03L!HaR<~S?Jt7bgW zNefIUV4AWaN`z)ep`Un%5QgM;^ZFF24=gZgx0AcgbZ&1J1r5t3YoYWv%ifU%MOu>9 z?n%muxEPV&tY=3%?7PK*gK4AkvAr~-xgBN3EoCL`P+5E>=}OxzS$P7Wg0bV$a(->@ zLn>uQg2!pvFe#!+f=l2b1lhDW?xUw1Y6*;x;~>Eyf>8v;D#~uH^G4Z;=%bvZ&D%-u z{W3Mt#-q`543iQ}mx=p%Tx)PR0N?0pSL`;7VN_s4K`wYBqdm3Ctu%NXR(PWw@%X%a z;cfQqB{}*6Lo)B5p4aOGv`H=0Z6h|cl~Zks)m0cryX;3B6@j96m#aOq@|AygWnc#t zXnJY|=rfLzHA!%Wpet8fdXh5e$m5#~BKXXAeA~D1AuReXWaQ<{&rPZgoFF)k5ctY! zh!`un##;h(ty~Z-!Q09Mk?wZJMY(ZBG(`0Gp51c71tRQ<(t7AZ^Y|t-j0P*REZfiI zr|kPVeX<QC_&*N1;=c-7^*B^cTDKz<*27J)OY%+M+i5+co^pW4HIeGr$*Wx6YKb`1 zh130hkQ+I0aTijm?6Q2F`?9G?GcZFz`f58V(?(n(FI5aqA_QLgN1Z@h*<l^~KTAG3 zsO<6eT4h~S%N{z&=)DhhR^Xe^{220Ue)|3t8Zb?8mOzh(o&r4pdK9`v=}y5p48D$U z;v?V`^kseD1KJIW%88#utqs^GmkWGRxz%R8TCV{`rp=(R|D<(Tl|K_T!zT?f%P>MW Q6si9`W|0-moLRW^2X?pvTL1t6 diff --git a/modules/__pycache__/utils.cpython-38.pyc b/modules/__pycache__/utils.cpython-38.pyc index 3779f2328d7e4b76f6393ce35d676cd00db208ed..29f9b792e78cd77fbddf620dbd8b764782742cce 100644 GIT binary patch delta 48 zcmbOiu`Yr;l$V!_0SK0^3f;(ko`unR@@*C=0o|h1;)2Yg#FEVXJl*8PoXuZZG}QrR Ca}UA* delta 31 lcmZ1%F)xBUl$V!_0SM-Ab=b&#o`q3+@@*EW&8)1N>Hv$Q2x$NS diff --git a/modules/datapipeline.py b/modules/datapipeline.py index d66fbc5..819ebf0 100644 --- a/modules/datapipeline.py +++ b/modules/datapipeline.py @@ -27,8 +27,7 @@ from sklearn.cluster import MiniBatchKMeans import cv2 -from config import DEBUG, NROWS, N_MARKERS\ - ,TIME_COLS, NO_HACC_ID, DATA_DIR +from config import DEBUG, TIME_COLS, DATA_DIR def datetime_to_sec(time_in, is_iso=False): dstr = datetime.today() @@ -312,14 +311,10 @@ def shuffle_split(x): class DataImporter(): def __init__(self): self.imu_fname = '' - self.marker_fname = '' self.timeline_fname = '' self.summary_fname = '' self.video_fname = '' - if DEBUG: - self.nrows_to_import = NROWS - else: - self.nrows_to_import = None + self.nrows_to_import = None if platform =='linux' or platform == 'linux2': self.sep = "/" @@ -331,110 +326,12 @@ class DataImporter(): else: self.parent_dir = 'D:\\Raymond Chia\\UTS\\Howe Zhu - Data\\' - def import_rigid_body_data(self): - col_keys = ['frame', 'time (seconds)', 'mean marker error', - 'marker quality', 'rigid body', 'position', 'rotation', - 'x', 'y', 'z'] - filename = self.marker_fname - header = pd.read_csv(self.marker_hdr_fname, nrows=1, usecols=list(range(0,22)), - header=None) - header = dict(header.values.reshape((11,2)).tolist()) - if self.nrows_to_import is None: - df = pd.read_csv( - filename, header=list(range(0,5)) - ) - else: - df = pd.read_csv( - filename, nrows=self.nrows_to_import, header=list(range(0,5)) - ) - shape = df.shape - if shape[1] > 10: - diff = shape[1] - 10 - df = df.drop(df.columns[-diff::], axis=1) - cols = df.columns.values - new_cols = [] - for i, lstr in enumerate(cols): - col_val = [] - lstr_list = [ls for ls in lstr] - if 'Rigid Body Marker' in lstr_list: continue - for j, str_val in enumerate(lstr): - if str_val.lower() in col_keys or 'glasses' in str_val.lower(): - if ' ' in str_val: - str_val = str_val.replace(' ', '_') - col_val.append(str_val) - new_cols.append('_'.join(col_val)) - df.columns = new_cols - - return df, header - - def cleanup_marker_data(self, filename): - chunksize = 10 - file_size_mb = stat(filename).st_size/(1024*1024) - ff = filename.split(self.sep)[:-1] - if file_size_mb > 0.5: - print("processing: ", filename) - header = pd.read_csv( - filename, nrows=1, usecols=list(range(0,22)), header=None) - hdr_name = path_join(self.sep.join(ff), - filename[:-4] + '_header.csv') - header.to_csv(hdr_name, index=False) - df_hdr = pd.read_csv(filename, skiprows=2, header=list(range(0,5)), - nrows=0) - df = pd.read_csv(filename, skiprows=6, usecols=list(range(38))) - df.columns = df_hdr.columns[:38] - amended_df_name = path_join( - self.sep.join(ff), filename[:-4] + '_amended.csv') - df.to_csv(amended_df_name, index=False) - print("saved: ", amended_df_name) - - def import_marker_file(self, filename): - if self.nrows_to_import is None: - df = pd.read_csv( - filename, header=list(range(0,5)) - ) - else: - df = pd.read_csv( - filename, nrows=self.nrows_to_import, - header=list(range(0,5)) - ) - return df def import_header_file(self, filename): df = pd.read_csv(filename, skiprows=1, nrows=1, usecols=list(range(0,22)), header=None) return df -# Import .mat files from markers - def import_marker_data(self): - col_keys = ['frame', 'time (seconds)', 'mean marker error', - 'marker quality', 'marker', 'position', 'rotation', - 'x', 'y', 'z'] - filename = self.marker_fname - header = self.import_header_file(self.marker_hdr_fname) - df = self.import_marker_file(filename) - - shape = df.shape - if shape[1] > 38: - diff = shape[1] - 38 - df = df.drop(df.columns[-diff::], axis=1) - cols = df.columns.values - new_cols = [] - for i, lstr in enumerate(cols): - col_val = [] - if type(lstr[0]) is str and "('" in lstr[0]: - tmp = lstr[0][1:-1].split(',') - lstr = [ll.replace(" '", '').replace("'", "") for ll in tmp] - for j, str_val in enumerate(lstr): - if str_val.lower() in col_keys or 'glasses' in str_val.lower(): - if ' ' in str_val: - str_val = str_val.replace(' ', '_') - col_val.append(str_val) - new_cols.append('_'.join(col_val)) - df.columns = new_cols - - header = dict(header.values.reshape((11,2)).tolist()) - return df, header - # Import labels from csv def import_labels(self, filename): if self.nrows_to_import is None: @@ -559,7 +456,7 @@ class DataSynchronizer(): self.end_ind = end_ind class SubjectData(DataImporter): - ''' Loads in data for the rigid body, marker, breathing rate, summary files + ''' Loads in data for the rigid body, breathing rate, summary files and syncs them accordingly ''' def __init__(self, condition='M', subject='S01'): super().__init__() @@ -574,14 +471,11 @@ class SubjectData(DataImporter): self.subject_dir = path_join(self.parent_dir, self.subject) - self.marker_df = pd.DataFrame() self.pressure_df = pd.DataFrame() self.summary_df = pd.DataFrame() self.accel_df = pd.DataFrame() self.imu_df = pd.DataFrame() - self.read_marker_data = False - def get_cond_file(self, files): for f in files: if self.condition in f.split(sep)[-1] and \ @@ -626,30 +520,6 @@ class SubjectData(DataImporter): sel_dir = sub_dirs[i] return sel_dir - def set_marker_fname(self): - subject_dir = self.subject_dir - data_dir = path_join(subject_dir, 'Motive Logs') - if not path_exists(data_dir): - data_dir = subject_dir - data_glob = path_join(data_dir, "*Take*_amended.csv") - else: - data_glob = path_join(data_dir, "*_amended.csv") - - data_files = sorted(glob.glob(data_glob)) - if self.subject_id > 16: - condition_chk = self.condition in 'MR' - if not condition_chk: - data_files = [dg for dg in data_files if 'MR' not in dg] - else: - data_files = [dg for dg in data_files if 'MR' in dg] - self.marker_fname = data_files[-1] - if len(data_files)> 1: - # Check directory times with timeline - self.marker_fname = self.check_times(data_files) - # set marker header name - self.marker_hdr_fname = self.marker_fname.split('_amended')[0] + \ - '_header.csv' - def set_pressure_fname(self): subject_dir = self.subject_dir sub_dirs = self.list_sub_dirs(subject_dir) @@ -735,56 +605,17 @@ class SubjectData(DataImporter): self.study_end = mat_end def set_fnames(self): - if self.read_marker_data: - self.set_marker_fname() self.set_pressure_fname() self.set_summary_fname() - if self.subject_id > 11: - self.set_imu_fname() - if self.subject_id not in NO_HACC_ID: - self.set_accel_fname() + self.set_imu_fname() + self.set_accel_fname() def load_dataframes(self): self.timeline_df = self.import_time_data() self.pressure_df = self.import_labels(self.pressure_fname) self.summary_df = self.import_labels(self.summary_fname) - if self.read_marker_data: - try: - self.marker_df, self.mkr_hdr = self.import_marker_data() - self.rb_df, self.rb_hdr = self.import_rigid_body_data() - except: - print("error reading marker data on {0} - {1}".format( - self.subject_id, self.condition)) - if self.subject_id not in NO_HACC_ID: - try: - self.accel_df = self.import_labels(self.accel_fname) - except: - print("error reading accel data on {0} - {1}".format( - self.subject_id, self.condition)) - if self.subject_id > 11: - try: - self.imu_df, self.imu_hdr = self.import_imu_data() - except: - print("error reading imu data on {0} - {1}".format( - self.subject_id, self.condition)) - - def sync_marker_df(self): - data_sync = DataSynchronizer() - - cst = self.mkr_hdr['Capture Start Time'] - - time_start = datetime_to_sec(cst) - marker_time = self.marker_df['Time_(Seconds)'].values + time_start - time_end = marker_time[-1] - - self.marker_df['Time_(Seconds)'] = marker_time - self.marker_df['sec'] = marker_time - self.rb_df['Time_(Seconds)'] = marker_time - self.rb_df['sec'] = marker_time - data_sync.set_bounds(marker_time, self.study_start, self.study_end) - - self.marker_df = data_sync.sync_df(self.marker_df).fillna(0) - self.rb_df = data_sync.sync_df(self.rb_df) + self.accel_df = self.import_labels(self.accel_fname) + self.imu_df, self.imu_hdr = self.import_imu_data() def sync_pressure_df(self): data_sync = DataSynchronizer() @@ -886,67 +717,8 @@ class SubjectData(DataImporter): self.set_timeline() self.sync_pressure_df() self.sync_summary_df() - if self.subject_id not in NO_HACC_ID: - try: - self.sync_accel_df() - except: - print("Error syncing accel data on {0} - {1}".format( - self.subject_id, self.condition)) - self.marker_df = pd.DataFrame() - if self.read_marker_data: - try: - self.sync_marker_df() - except: - print("Error syncing marker data on {0} - {1}".format( - self.subject_id, self.condition)) - self.marker_df = pd.DataFrame() - if self.subject_id > 11: - try: - self.sync_imu_df() - except: - print("Error syncing imu data on {0} - {1}".format( - self.subject_id, self.condition)) - self.imu_df = pd.DataFrame() - - def get_rigid_body_data(self, col_str='Rigid_Body'): - data_cols = [col for col in self.marker_df.columns.values \ - if col_str in col] - marker_data = np.zeros((marker_df.shape[0], 3)) - for col in data_cols: - if 'position_x' in col.lower(): - marker_data[:, 0] = marker_df[col].values - elif 'position_y' in col.lower(): - marker_data[:, 1] = marker_df[col].values - elif 'position_z' in col.lower(): - marker_data[:, 2] = marker_df[col].values - return marker_data - - def get_marker_data(self, col_str='Marker'): - data_cols = [col for col in self.marker_df.columns.values \ - if col_str in col] - marker_data = np.zeros((self.marker_df.shape[0], N_MARKERS, 3)) - for col in data_cols: - for i in range(N_MARKERS): - if str(i+1) not in col: - continue - if 'position_x' in col.lower(): - marker_data[:, i, 0] = self.marker_df[col].values - elif 'position_y' in col.lower(): - marker_data[:, i, 1] = self.marker_df[col].values - elif 'position_z' in col.lower(): - marker_data[:, i, 2] = self.marker_df[col].values - return marker_data - - def get_marker_quality(self, col_str='quality'): - data_cols = [col for col in self.marker_df.columns.values \ - if col_str in col.lower()] - marker_quality = np.zeros((self.marker_df.shape[0], N_MARKERS)) - for col in data_cols: - for i in range(N_MARKERS): - if str(i+1) not in col: - continue - marker_quality[:, i] = self.marker_df[col].values - return marker_quality + self.sync_accel_df() + self.sync_imu_df() def get_accel_data(self): accel_cols = self.accel_df.columns @@ -956,9 +728,6 @@ class SubjectData(DataImporter): data_cols = ['X Data', 'Y Data', 'Z Data'] return self.accel_df[data_cols].values - def get_marker_sec(self): - return self.marker_df['Time_(Seconds)'].values - class TFDataPipeline(): def __init__(self, window_size=60, batch_size=32): self.window_size = window_size diff --git a/modules/digitalsignalprocessing.py b/modules/digitalsignalprocessing.py index 7731f26..c3ffa19 100644 --- a/modules/digitalsignalprocessing.py +++ b/modules/digitalsignalprocessing.py @@ -17,7 +17,7 @@ from skimage.feature import corner_harris, corner_shi_tomasi, peak_local_max from ssqueezepy import cwt as sqz_cwt from config import WIN_THOLD, WINDOW_SIZE, WINDOW_SHIFT, MQA_THOLD, ACC_THOLD -from config import MARKER_FS, ACC_FS, IMU_FS, FS_RESAMPLE, BR_FS +from config import ACC_FS, IMU_FS, FS_RESAMPLE, BR_FS from config import MIN_RESP_RATE, MAX_RESP_RATE def butter_lowpass(lowcut, fs, order=5): @@ -200,16 +200,6 @@ def attenuate_edges(signal, nsamples): return(signal*e_arr.T) return(signal*edge_attenuator) -def marker_quality_processing(marker_quality): - new_arr = [] - for i in range(marker_quality.shape[1]): - new_arr.append( - linear_interp( - marker_quality[:,i], MARKER_FS, FS_RESAMPLE - ) - ) - return np.array(new_arr).T - def std_scaler(data, **kwargs): mu = np.mean(data, **kwargs) sd = np.std(data, **kwargs) @@ -268,8 +258,8 @@ def imu_signal_processing(data, fs:int=IMU_FS): ma = movingaverage(bp, 8, axis=0) return ma -def roddiger_sp(data=None, fs:int=MARKER_FS, is_marker:bool=True): - ''' Run markers through the following steps: +def roddiger_sp(data=None, fs:int=IMU_FS): + ''' Run data through the following steps: * Second order taylor estimation * 3 sample mov mean subtraction * 2s mov mena @@ -280,22 +270,11 @@ def roddiger_sp(data=None, fs:int=MARKER_FS, is_marker:bool=True): triang_window = 2 thold = 2 - # get accelaration profile - if is_marker: - mkr_shape = data.shape - accel = second_order_diff(data, fs) - accel = data - else: - accel = data.astype(float) + accel = data.astype(float) # movmean ma = accel - movingaverage(accel, 3, axis=0) - if is_marker and len(accel.shape) > 2: - for i in range(accel.shape[1]): - for j in range(3): - ma[:,i,j] = movingaverage(ma[:,i,j], 2*fs, axis=0) - else: - ma = movingaverage(ma, 2*fs, axis=0) + ma = movingaverage(ma, 2*fs, axis=0) # cubic interp accel = cubic_interp(accel, fs, FS_RESAMPLE) @@ -318,8 +297,8 @@ def roddiger_sp(data=None, fs:int=MARKER_FS, is_marker:bool=True): return accel, smth -def hernandez_sp(data=None, fs:int=MARKER_FS, is_marker:bool=True): - ''' Run markers through the following steps: +def hernandez_sp(data=None, fs:int=IMU_FS): + ''' Run data through the following steps: * Second order taylor estimation * Cubic interpolation (~256Hz) * Max Resp Rate mov mean @@ -329,10 +308,7 @@ def hernandez_sp(data=None, fs:int=MARKER_FS, is_marker:bool=True): # max_br = MAX_RESP_RATE #bpm max_br = 45 #bpm - if is_marker: - accel = second_order_diff(data, fs) - else: - accel = data.astype(float) + accel = data.astype(float) # cubic interp accel = cubic_interp(accel, fs, FS_RESAMPLE) diff --git a/modules/evaluations.py b/modules/evaluations.py index 6d6c833..c92c371 100644 --- a/modules/evaluations.py +++ b/modules/evaluations.py @@ -8,8 +8,6 @@ import ipdb from sklearn.metrics import r2_score, mean_squared_error, mean_absolute_error from scipy.stats import pearsonr, f_oneway, mannwhitneyu -from config import N_MARKERS - class Evaluation(): def __init__(self, y_true, y_pred): self.y_true = y_true diff --git a/regress_rr.py b/regress_rr.py index c087390..282fe46 100644 --- a/regress_rr.py +++ b/regress_rr.py @@ -1,3 +1,4 @@ +import glob from os import makedirs, mkdir from os.path import join, exists import pandas as pd @@ -8,6 +9,7 @@ import re import pickle import sys import time +from zipfile import ZipFile import argparse from datetime import datetime, timedelta, timezone, timedelta @@ -62,14 +64,18 @@ from sktime.transformations.panel.rocket import ( MiniRocketMultivariateVariable, ) -from config import WINDOW_SIZE, WINDOW_SHIFT, IMU_FS, DATA_DIR, IMU_ISSUES_L,\ - IMU_ISSUES, BR_FS +from config import WINDOW_SIZE, WINDOW_SHIFT, IMU_FS, DATA_DIR, BR_FS IMU_COLS = ['acc_x', 'acc_y', 'acc_z', 'gyr_x', 'gyr_y', 'gyr_z'] def utc_to_local(utc_dt, tz=None): return utc_dt.replace(tzinfo=timezone.utc).astimezone(tz=tz) +def datetime_from_utc_to_local(utc_datetime): + now_timestamp = time.time() + offset = datetime.fromtimestamp(now_timestamp) - datetime.utcfromtimestamp(now_timestamp) + return utc_datetime + offset + # Load data def load_bioharness_file(f:str, skiprows=0, skipfooter=0, **kwargs): df_list = [] @@ -157,6 +163,31 @@ def load_imu_files(f_list:list): data_df = pd.concat(data, axis=0) return data_df, hdr +def load_e4_file(e4_file:str): + ''' First row is the initial time of the session as unix time. + Second row is the sample rate in Hz''' + zip_file = ZipFile(e4_file) + dfs = {csv_file.filename: pd.read_csv(zip_file.open(csv_file.filename) + ,header=None) + for csv_file in zip_file.infolist() + if csv_file.filename.endswith('.csv')} + bvp = dfs["BVP.csv"] + t0 = bvp.iloc[0].values[0] + fs = bvp.iloc[1].values[0] + nsamples = len(bvp) - 2 + + t0_datetime = datetime.utcfromtimestamp(t0) + t0_local = datetime_from_utc_to_local(t0_datetime) + ipdb.set_trace() + time = [t0_local.timestamp() + ind*(1/fs) for ind in + range(nsamples)] + tmp = [np.nan, np.nan] + time = tmp + time + bvp['sec'] = np.array(time) + + return bvp + + # Synchronising data def sync_to_ref(df0, df1): dsync0 = DataSynchronizer() @@ -395,6 +426,7 @@ def load_and_sync_xsens(subject): return xsens_df + def load_tsfresh(subject, project_dir, window_size=12, window_shift=0.2, fs=IMU_FS, overwrite=False): @@ -648,8 +680,8 @@ def arg_parser(): 'elastic'], ) parser.add_argument("-s", '--subject', type=int, - default=12, - choices=list(range(12,31))+[-1], + default=1, + choices=list(range(1,3))+[-1], ) parser.add_argument("-f", '--feature_method', type=str, default='minirocket', @@ -677,30 +709,13 @@ def arg_parser(): if __name__ == '__main__': # choose either intra or inter subject features to use for model training # '[!M]*' - ''' - Dataset time per subject (s): - S12: 2658.65 - S13: 2937.76 - S14: 3009.97 - S15: 1525.07 - S16: 1576.35 - S17: Error - S18: 2413.58 - S19: 3282.91 - S20: 2218.55 - S21: 824.58 - S22: 3325.08 - S23: 2751.38 - S24: 3153.87 - S25: 2974.67 - S26: Error - S27: 2608.63 - S28: 1586.10 - S29: 3289.75 - S30: 1984.31 - ''' np.random.seed(100) - imu_issues = [17, 26] + n_subject_max = 2 + + e4_glob = join(DATA_DIR, 'Pilot02', 'e4', '*') + e4_file = glob.glob(e4_glob)[0] + bvp_df = load_e4_file(e4_file) + ipdb.set_trace() args = arg_parser() @@ -716,16 +731,18 @@ if __name__ == '__main__': print(args) assert train_len>0,"--train_len must be an integer greater than 0" + subject_pre_string = 'Pilot' + if subject > 0: - subject = 'S'+str(subject).zfill(2) + subject = subject_pre_string+str(subject).zfill(2) imu_rr_model(subject, window_size=window_size, window_shift=window_shift, lbl_str=lbl_str, mdl_str=mdl_str, overwrite=overwrite, feature_method=feature_method, train_len=train_len ) else: - subjects = ['S'+str(i).zfill(2) for i in range(12,31) \ - if i not in imu_issues] + subjects = [subject_pre_string+str(i).zfill(2) for i in \ + range(1, n_subject_max+1) if i not in imu_issues] imu_rr_func = partial(imu_rr_model, window_size=window_size, window_shift=window_shift, -- GitLab