From 8faa7c2b7916e55f017c098a38647315dc136d8a Mon Sep 17 00:00:00 2001 From: SebastianBruijns <> Date: Fri, 2 Jun 2023 19:04:43 +0200 Subject: [PATCH] code save --- __pycache__/analysis_pmf.cpython-310.pyc | Bin 0 -> 7658 bytes __pycache__/analysis_pmf.cpython-37.pyc | Bin 6865 -> 9525 bytes .../dyn_glm_chain_analysis.cpython-37.pyc | Bin 54310 -> 58714 bytes __pycache__/simplex_plot.cpython-310.pyc | Bin 0 -> 3059 bytes __pycache__/simplex_plot.cpython-37.pyc | Bin 2990 -> 3111 bytes analysis_pmf.py | 140 +++++- behavioral_state_data.py | 12 +- behavioral_state_data_easier.py | 200 +++++++++ behaviour_overview.py | 57 ++- brain_wide_download.py | 77 ++++ bwm_mice_stats.py | 1 + canonical_infos.json | 2 +- dyn_glm_chain_analysis.py | 185 ++++++-- dynamic_GLMiHMM_fit (copy).py | 407 ++++++++++++++++++ dynamic_GLMiHMM_fit.py | 32 +- index_mice.py | 8 - pmf_weight_analysis.py | 242 +++++++++-- process_many_chains.py | 2 +- simplex_animation.py | 6 +- simplex_plot.py | 16 +- state_dict_KS014 | Bin 0 -> 153288 bytes state_dict_ZFM-04019 | Bin 0 -> 166660 bytes state_dict_ZFM-05236 | Bin 0 -> 245334 bytes 23 files changed, 1248 insertions(+), 139 deletions(-) create mode 100644 __pycache__/analysis_pmf.cpython-310.pyc create mode 100644 __pycache__/simplex_plot.cpython-310.pyc create mode 100644 behavioral_state_data_easier.py create mode 100644 brain_wide_download.py create mode 100644 dynamic_GLMiHMM_fit (copy).py create mode 100644 state_dict_KS014 create mode 100644 state_dict_ZFM-04019 create mode 100644 state_dict_ZFM-05236 diff --git a/__pycache__/analysis_pmf.cpython-310.pyc b/__pycache__/analysis_pmf.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..9444f63cd5c90bb3a9aa6b583c61b347d9bbe11b GIT binary patch literal 7658 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%0DRZN5?thS zX}jR$vb}jv6O%=T`9+GS<#s!rwx%877AO~8$ph`(-u!ZuhNu(mIJGG#t?9IrM^BN0 zu1MLm93FfAnZx}@lbWYad0Kj*NC9HjogTk%ssHFek-j%CH(uQ@D83hL!Q5oA8+}RD zGhAnxdy&&Yf)qQbJJ?4l6vTeNLndu`gIaFli*_cT=G|mq_kbCprL6veV@1kiv(cGM zTgajU&sqaVHq0KZ9Uj>*Je1VLVOn_~t*jLZ?IL{>hqiUoPKp$kJ}lC1hb(v)FE1o* z^YlV4f38T8UZm76k|4-CKvN<jhpi7DNQV3^g0^Qtl2f>G{n3xE<$62oWbCxtJy2;5 zR+>XaVyw_dmbXpau(K&An=1LLrMkn)+8ItBY@Q&nN<$QyuCx?}g{E@poG7+JuvuSn zhAa9&7b&uq8_R4I4#g%Kp#1g2q7ps5d6+95*Nf2!Xqiq+C%MZFPmT8v9PtS=B#9t@ zemE*9L_BqJxrI5?(_HXu!ND=%yLS*ElgQ+CFPwL#X4Bl;p0Nx0bgqzgCUJOB3q$@} z&!-DsC_A6YFZtVRoy+aXoXDEGn{~Y?Ma-Zy*9+M~*h?nqXweq!3bIRXYhnkrTIfMr zs@$u}IYxk5mS?1MHuH>Jo@dSWE%QxKNPF6}Yqrrk6{yOIW=3d$a5bB#RY@|j7rbV@ zFB>M|zao6v$#NE)ymIUH3~7I8;RbN?jHR@b@r*@!hL_UzBu{(c#o)bE0DL%AQd71U zb$P*BlpXjN4tMjA>%|I`qE^~o%FP$NI@i95^-{>v8@UBDoV7%5!KF9wbG?W=KS@iw zo@${uSaiL54kfvO=RDQ%^jW^-FB9mYVaHQvJk|EXayi#)ASG@(F7g$-01;Asshh8? zSx+ija+?U-0&&jG?b2b@F>khR?DC@?JFAnL2P~n2Q@|4XvV&@d{0HNF?L9SbMkPLS z5#I$BFTntSVEOFoqOYVx*9Xu?)|i`jfY(%Rp0-*~$Eu={d>5W~xdpRz+UE6)lQrw$ zXsgn|SVKCOa;EIGWoMb7QmyI;pgl&&V?S~tlVkH~ev)=Uw;N}AM2X=jji@obNo~?1 zT9c7bqgup>M59e{Esj$m-WgZ%o;I}I>VBLP^o(gSoEl9i7CI$&l#b*7YJ4-!h~9z~ z=oH$E_chh{gjQ}*V=8o^el3A@jE|uct)`V`lLm%%zw*WPIB<%pJAqOZwhZD1zR(%A z;@yc~lZJEmlZY<y(+!M7V7DRXM>O)wxd4s0oKHOTOUNJjB@XG$kV_JxYFIUZWrS9M qlx`z}o`lw{HLKmg*7$2Y9tS5$XjTd1CP`JdX-(2rd5M0;@BR&@97MnX literal 0 HcmV?d00001 diff --git a/__pycache__/analysis_pmf.cpython-37.pyc b/__pycache__/analysis_pmf.cpython-37.pyc index e1ab5f64794b712fd3d7753bfc894d24535085b8..f9fd33bf94c4befd1c5937c83c151a084e749d91 100644 GIT binary patch literal 9525 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 literal 6865 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 diff --git a/__pycache__/dyn_glm_chain_analysis.cpython-37.pyc b/__pycache__/dyn_glm_chain_analysis.cpython-37.pyc index 740060e1aee1c905d0d6e98e7fb190b6806d36f6..4a89c93f30137d03c0b66cc48856b5c8f6b5a111 100644 GIT binary patch delta 26257 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⪚< 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 delta 22045 zcmb_^2Yg(`)$hG`i&oOAT3wbU%d(m+_m08c7!1a^;%j4hrMX(|YPBoPuCZk9vKRva zf<b1CF(t4Hp@td}N+_Y2V&Z@a2_YLGgce!|q<kqK3GaXA?yAM`lJ|S^@1C7LXU?2+ z=FFKHCtkGOdb=%qX;xN-g1?V5{?%F)*q>dZU7UA+{cKJBgV?TZR6iFFXm#or;tg$n z?2l|c+i;<(uVsH?8`&m=&SZaPo7q_itz&;-TbPc}dbX8qyHL?Lu>WCav+YRPXl!E5 z9a^7*U&3}U4{KqqjCmbQDOL2%#%AV0o{a~L()d}%7G|)vy;{Gj>&dt`8Q&TUHlpwj zS@>Wwvwc)yU#hUN&Cug#_bYo<eY;Q5x3Z;rv(Zc_4A1FPd$t+dmn(hh+3WNj#*Vm$ z`TNyATllaHcTkvr&}ZvDY_zagV6UnwMvJjS{_4h#QiXNmn}l(+8df}*j58L}4I^ES zs4L!P>@YSPhQW;1eh2H8<MSqS`EhgGleyuc+}N<nzGQY}D0^70-|#Y(sTXN%C&4xi z2zrh7e@kmOeE*i_GyMOS<~KGPUL%I$2AcMF(9E&%WePiIpJSV*2lP&()7Wb4Sg06* zBpr4wRETVwiC$YJy{vh5@C}%{AWG3p_ka=_Xi6ztk>X9I1g9jY+QBbKm5;IZRQ6y6 z-(X5;uc9ifm+c1Yb+L1qiQjG(W#{3Svlu%czhU-QwufB+mW;5y>_VjMWPf89vu`2g zoFtRx@e96&Nn=`{le^LNH*)D9lREjFWZAD}Qg#Wu)T`;chO;E-wVmk2LhLg3ZFV_R z*gmh5C?3-dc7@)<uGD*tUavy`Sl<nHeYatcpUd_`WK0=qKq%@}^z-n=@STru555cV z?Uf~}QQ|^&m41;GGcIZ)fxB471VZ0pdHN+NeJLd8GJM}g_;PPd(f1*61->is_2Ju( z?<#x(-vNAA_qlpLkOJj8`;DYP9e@y}g|m$v>}rT^8lTda)}5V_qCRJDTauLzTCCi! zCFSEFMD7|%iRJn=R3-)nIW(%!p=9N2N2OnDoM{|n*Rks_RE%qvLkk#(K*%bV$8Ol? z+~(4+)34WW(7&VKsNbZ=^?u`2<2vJd<A%L9{kz81@tckB_G1eA(spGVs|Ryp-!l#% z>wA=CNOtoo#<z*<dnOy#FIUd4(Ql!6se)3s(2N0AK~fMR0;54!w*raSkNmi7<tl`3 zlA(UD(qZd!@wJ9PTE9%Y(70)?qF-o)35C5{45D_cep}Bx<2H0Q4V~R?b%W8}0n)no z#pobl^r3+rvVkiRx`jfNj*f3NE|ciCNOX0ya7C&_&ngR9w7gKi)3_YzcamZQ1o|Zk zT8SyfJ|x@Y-?tL20>vOJWhc9NZZmau4?5e6vNy_9BBP}Vzk_MIi*#YXEji1n3B2*& za_)vy*yH!Go8%-O^xqpJO#Jr|R{r~GPWx48_a9(h)xbdK0~+MN^N0F_n4G(fyIH(c zsZjL0jR*Y?Suv#A{SO;=C)HOK>)!{xSfa4+vYYp5`a|q{`Xea)BjX`<3%d%Oa_c_3 z{-}`_e~jHGk&EqM-|e^2h>-YrKe|g|czX)N<0ELK`JZ4lXz&i!02Y-0ybhnr?quKJ zXUC-eSbq|OxGSJ^Ht9`}e1+W|aCAPUKZS|Ydb*6K**)xDHZI1#=e6%uv07<o>!|jO zewZY7a76d932i`6e-@*7&UnZ;%<gAD*k{w9$GBfGo=3+6`!v)$qQ407JL2z<YPkh% z{KR;XXo&$GW)E~Y`!e}y5aw%prWw<XBgTt+HE>1swwR_L)qiSSD|z50<9Xv~2e_KX zEN3~R`*qUx?1!?UbZGQzA+Qe)o7abu+MY!7;Sr+wh%9v&vY&^4KZ1yAB%;Ps@t1+# zF)6x_#)$a(D+XaTgFU(zU9&N)j!j^XvGHsoi2FFkSPfFwvU*m)o?t)r=IzzMBR^x4 z^jF!Fvdf>N_KU_5N+%wowT?}?$c7d22z%-qOF;j<*rN|4$!WlnDDqSGbcY>8`_Oom zRY783P2&9v;692@#`6~Ym4jx+vlb1pQf7942--bqJj1GriOF9xo@LLl!|d68HdX1V zF@Asv7#q`nIjqR*#xL1(?D>6IKKtC=n}%19|H><;WT<pJF*?QnYxV+&eg|g!z5*#r zY(G09Tg&KX)S6`G*C0D7L}E%$mBgfk5Rus<k$5XrZ3qD>6;BvH7$UQjAFK8o!_(P| zR`*uR@i&nNL1&7z4`lh6|1I_tb~ITm&Ho$rQ})t6OB~;p;z+Xkvc+)hSidd)TlNb3 zS-(`hDUpSG!t!HRjCVRR`f~V(s-nM3Vz#>;GVw04uGIQ1?A4@nz^o|+eIOe#8Du~2 zaP(#I&%x=xNEHvd5POYc5Sx2pRBkt(2A>RCgvk(WMT_lVZZ04J#>ZeeK9jPUN)-rS zHecG8-966O&3-9Yl4m5vcC%niMp-h7#vq8TGG-~)*D>-P5J=0sd=IF+&#LqfdUp5f z>{pbRGC^4au@9iKo%-*LvUpj)qJL<-Z>ebGcUFC{@%tFmuc@R}#)y3gJrA(~DL#;V z{=sG?SOQXh1X5=6f2q)js<Kwuq6D?G6pZ2W%?f*Cc*p&Y)RgESqwzOoTg#32C3jp& zLTJ2)7)ih<64@T(WA@g*H2qWK-uTTi<5L<f5eJO6)VSB!y;su@0`H)45UOU#fJiBt zgYn-RmFzc=@}-iEtoYj_;^X!z!*a*5su8)c7zS&`##<4L3Q9wNck8=nrN#=D0!sGy zJmXTRs7sTp-EWgqaVf_74viHG>)k+B=V$t7pka&gnQ<w#1T!7>0mhz+RZ)yMWn?L= ze<O;GKYlSLs}DBzZ>8dYU{z2)sm^4Z!#f+5KZFd{e~I&`0>e7M_}&YA-uZ?81u*|2 zMGvT{JoY|mGOUDuG%mI3vk#!Qe<xEj<A1Wm*Z*hsA;g=;P2xQi{tNqveY{{$^8bf@ z!ah#L;z`-}KgK>~zeiV}SzX2dN{upgz0&aafpfC1v#Ywu%P&}6%<RkogWt}aEDc)# z2P<J2EE6eCR?4ziHbQC4<^^F`4$DQ%#mcbI6d;t&3Rw~AWUzEJTP}L?-y4V&w5pDT zjT>R{M&T64GVG<7ikzZH)TQD`(R%fafr{dj?0IJ(na>4i&=T5|X?(2+lvk-t>?{9P z^*SUcY`!3CP!slmuQSXWsq`cQ>j4Z!Ou4T}d^T^IlZx^UVoC29C*`!Ia?-_*#!eb1 z8`1(ktNzGFyd#RL>%^2dN*vTiyXdGm3S{Sv8|Nl06VA>MGXmj(=5ZU<yzP{t`V&r! zZ)YF^yq~R{qizsiR-U156sJ{<RW}a!s*Y-7LMW(bwuJ)N)-`iau!A>?RTC;o79)L4 zLl&oo_znWi1kMoA38iHo3N8moq=k33bOl0@guUGtj_{S@z6n$F)>4kMHMBDr2`AKM z-X%VtP^MlrkXiGL>e_<L1{+@|UYl4g2l9aU=fvwUkVCZ<&a<fDZQ{||vFaJ(_1X!} zvngS@Q0r=PR#B^IVb3{6vybtJm{m6^FN!ohJ>u&$nkfUr?5bO!-XXqU=T%F^n0lew z#BKGb#B34OwE3MRnh{q#6JdA18g)fn{;YVm>FQUvY0>m(2J&*ubmXKXC&$cS4(8gY zMKjEFGd-T$uaqmuQO$G+O!`G6>}U_Apdd&Yn3}a`_q(H+XerOkjOSZDiBLmjsT&OJ z4it74MYB*V%XIHm>5FEI+ZyWBZ1J*$OBxG>yV0GV6Df|5>sO+=VtivIa+fsD2Ryg2 zNlh1bG@gucebG2(MP8)N%-c)Y=SRmxiv1-d2qcI-Es+8mF|(H{rsA(H1FkSePK_3z z-O@`GW;Y8cy+APw#PrF9=|eH^qzT3O*2Vy3E6g0y-h_>rEBYtR-&`1}M@_WHN~BNc zD02oiRvInpx&63(_Q^iW%pz857BEM#(hrpaT)!EMGbUH6#UeDh^n_vk%XP%ojRnjs z^iPI(m(y6y!gv!K%PQD7R_V24_DYajX%?F$;+e_Q3)9UEGxHLq%?{D8Uc)aZj@l*C zn*x?pt`+Atl}SeYWZ=4{>(trXr~olmB0U`OM2u!0_HdKpX%MD%PnVH!$RDm#$yx&E z3E$M2YODCp)Z%~?#>{Z5ud8<oH4x_esfZL8XPeKvlN(^;R!<~iaL%b+XHUS>VgwS- zUhCK118u@rQmqRKoJ>GU!bKD!LEt+HoFb~Gt=v}17f|F>fP{_tI(1i9tEc%KqcyC% z8Kjbekq{4aFBMxt#Z(W!j(#=coP^ErdG)+59`d7@FBEL<^hCI?C!zK9^8MoIw7OiW z16ru^E&^+XZTiH*J_?eqOOXkk9vL`s`j6CXQi_oVjZ3X}8EHL9-|3=a=9#%msopFC zl28Sre@=nMw}=BXS2$0j<Tmk}nN!tTkuz&eK4~X3R7UAEaSfRwG^??alr=w-K#)KW zfo~Idkig?&|Eb0Kd?vyt;0xyhxKx*O;KNxxsx|4CiMBb75~<bV>NyKzF{(#1nQ*oE zf>Lww^C+#A0BNO!b7#=kz0;7B-jL4cQ^qrtkrQeO8~hxoPsuJ}{s^UJTfEc8J(8$g z>O@=E=uTvYjc_<s_A+Xwk;aE%Qgi$;0l9`ejL>Z1pWCE9EDp`Bjb$fSKwEMJv@;h= zmn$Kyg9_F`H_O5=Rza|OP9pR4Wv4G|PA&i{8cW!EjqsY*3<T+qe(m^(n&Bq^Ox0AH zp~jd>N~2jd(*QNo4rq(mW2R%T8h0>_+4?mkIZY>E8uXsh>@q1O-LwH_L^3V?fUw&N zlNR!4LEkCO*^wM*Rp*7Im7s+vo%VAwFLy944<+-Vb(Q8ZjF2dZ6q>V?<|2&Ps+vKS zkWp+Z@e*k;C>V448cPb)DHf+rP{jR@*NCR?m#3yZ#fxW)h4XJLdJcn5xLZTP2$;UB z%NO(#*NV^Q7d6ll%RscShJaIPDCM+pCG0^@rvZ*Px@iV^gzpqJ3#v}LnDVkb;jqse zY)&qG4qvb>6i(Qg2L<P$0G~rZvYMRfR*Fi+k`dh5nc|4^#hwMLS0u7zE6rAu;f4%L z#t8@h8i8K|BwWNw5ZN&QIi(R6{1wWuv7Ma%iX^X$MBoe>NDTst=2SCOC;sKDPBH0( ze`ZP<?L`jXJt(LhV)eo$XG%epD4$Q+zaT)8U=hOM;oQ?}jfMnSN=k#nLX((XN{F7` z7Vt!x17sUmir`ITwGVu?@VP-r1d@3~?eGw_cP|j0#kHbvQCZePYU(L~29-Z87A|Uv zNxUT4V048eFf?{{hIe*Kv@Cp{r8*<Um(x`9Jp|-b=oH#UK<d@y6#5nc8gPT#8paw* zI2}OGwWOJ*Tzt65UG_ZXyg)z>^$3MtBygF?UR)-P$*zH>#lKhC(@2GVsCG2uS{TZy zmpDjH_$}3v*wj);qJBPwXqX9SkomAoB;3%*JDXu@`dW>!rIe;nq3a2}EzVoo<&=oD z$vHfT)Jq23%T7>Zl40bm$=-%Kl2nvv5M>e>P-4xrSb&%6snKf)NE*J4P=m{&$Q6`2 z9{@&|(b<(Wx+rlN2`JiV0dZQd%W*BjcZ*k-FP&-Qm}7+>1z3Y7N$2n%6L^vUaVjVN z;G~f_je=iGy1b141mQKP8z!CQQZq_jE?0?bBLB%iWW^1t`kcr+*;DZeRY-P>5b4l_ z);8mL)Z@PwSDqZIm4>$3n^4;z=buvX&j#yAl}mj1lBiiVQ@v80wQB0TLzFEiM$&7D zVX`Sh^1TzGgcFvxfr;9RNJA#yE`GeK;j|ViW38A}CY?98Ll!!H!GtXw3h+U6N8lo{ z&TYd~H+w@N*4*0e@dd+Ah*_u1RR1R0PZ4TDe0fSu?r7RsYu?|{(XWV38Uikr|6Oc3 zbyC(p5J4w$9JixjL)KfVGK$9kS3G~}304_<s!Y!6Vs(kATisL)FN+eUF)CVy>Q?!` z5L(G^79Fe0>+i$rAyqck3qOozrbaWoN;I?2-g6+LndxM5_Sw(ASlqLEeU?9xVM5Kz zL%VGQ*{4;iWA0&N;>BcN!hTd>CEEQZV$JEzu-xxCy~0rvamLHUvC}sWhNg?HYjV|c z5m+<6Vr-;><-!YGOBNt%jzc^Zt`v8!sfbneEB^6pvRPu5VoTTrJHE^;^H;Me@Hy6! z$IL8?Pk;?Ml}%&iEZ6HG>k=hu*mU@4CL$-7d<aOXWi!}Jv_Fe>sOYPX&1Q3~HX`-$ z23mfQ+Q{azd2BvgV3lf*PofOdhNH-zA$u}A0fW^{x9RM+nGUv4qF_hvI}v-liOL3D z2u+c-T)b+KvQy*J*opmWxGFL|J|i-don*Dca$!nqY>{~EjJnv;$gB(0$ZY={vz#qv zOW0DcjV;5F$C_i~bJ^m4H9oIjVM|JtXvJX4{A9{F^t!;T@SlKhp*haKP#WlVf4S+V zJ}@Xrt`wHtRWQFZvDz+QBgMHv`zYTHuHfSVprx-8!L>UeKQFJnG)EvQp<!p74L0IA z!h7bqcH(>S<fcOLzh`Es_2Qa!HKK9dDe5O8vaVX4gt$>~fSUUQ)pc}w{2`A0;*}zI z{dloz{hM=6w5&&|N2LVPQYg)9elvw6n}11_?O`0<@_$m|Sz_ykX{SqVC>5a;=T<7@ zi0teN82kb%CB<DX2y!iu+HwzNoJ`;jDz3GK`JEKIRs3$l`f0aNnk^g*C(@V^h6Q0H zoB<rV1{oi+)gx5?6avRYXyb(3MD~&}Ohz)cS8yKU;+l<3>bv6Eja9j)QmNGhWTk5H zmyL_m55??FCs#-k=7Wy9BN+09jfB0^6Yk(eMA>3-?WUE^j}Z);;{8oc>O3)K^Av0n zmv5c`S4R8h^=h4@)sRA?aV4A{?(OvS@Fwcf(r)6Nv(Bu!l;W3B344prlXPrI)k^w_ zZ$w9H#O5ut%PG`qLmK^M;mg3c3}5&Kaod)P7@VqyBBUf#1~*|+{4d1LTZ_Y1w06#> zi#%fRfC5I-dxB;<cB*aIb!V9Njx^rJRG6R{3l)M6I2oC3u3}RbLgrwwW>6gFD)LH^ zmrRk4I9Q`Gs^(y7hZcSSQ3ndxs9=Y}*O?hnNB27LvJJ>MMk9k}?Zs3Ybx?Y;Y5$s1 zwhlXTorF}>X~GbuVRYbX0<SmIYMC}1<KVnh0Tct)#a6+!;!}P4rX&?4is)2>B8|Eu zPUeiKnJ#84R)BzOG@2|8JNQh~-H#I{Rq39L;lL`lsNJTSX;+JjwuaZs1t8s8uSRkJ zpMkmJYcY$%tRWB5;QBd}Qr8h!51?mSHc*$rAp#r3+HED{{U`_l>g|G2vWW@~@(sU- z+RYPv+a?tFuo#7>A+Bh4)%uqqj%=G?pMibfz#q5GR`W?P$tgsYdI<~}qgRVFw@+19 zh&|hjW}ih_vj_}HvK045>U<t$(C`|v`4URFgc42>N4L+eT|seKvki%QPAC}YZEg$k z=716OM%uYf`D;a8^F;Mhae8x|+AMDD*_SJapU6m>+0A}&EK;7a6=nM|CKwfeiOdsI zVl(rlI+4vMsDF(w5&L(RWN$;sn`!j;p!6QuIY%6eMPi98ZbWwS)J}mDZ7fylvb5K8 zlt6kaVcYHN;*%-*F#&0s$ss0ppfnl_`JoZYNjQgUr^7pE?JGEG;-qmTR`;gopAFP* zCDfeAP}C~5K-BD-E3P_sR=u2ZiPH`g!eFExB<eQUEgDL~wuxWwD$m}IBHyQWXeX%% zXHVS>swD}B#h{s5a9PuF3Z=`cL_to(;e-avrTsgL#koE1;yATLi;1GTG?&fgaM=q~ zZeT7B*{NCaN~BEEAIHW-|LwgOjbDn=!<b?eosv_LL%lsnt>Z)M!qZzOR_wmA*+U3O zvLc`~q>Y*Y-a`4K+Wb#w&s(XYAbZ?NgM362r=7cdWgDf+?!K9}G$z`9j<RPtk^2cv zxXl?BnW?@1j?CXObBYIu5dTJI@4($=mbRESJecTOLScxuCPf=5OSNW`!j_+cX7eX# zk^de^yT^%F&My=>v2|Y~6i%9npK4-%>;Wc;|MlE&5&!>{`$x~fF-<&u{*6=G(Y@T% zfw85=AntB(4rgo{nG`2o73Uu-N|RLog(kkgXYNW_y_!l8o%jR-r36kS@E(A7qx}2D zA}F+zDA7$l<^Uw@UT*Y)fNoKLL6x<Ul}bYrmqaCD^Dt)FGApR+Zvhf%o}TsqEDLLc zx{A`JjdF}aWL99mD)rq`>gc!vMi~-ciM|xXS#{L57H%0at8)918Sr$4;ZgU&q<Kyg zpIlI{1_uiE-jn$?dRm@oe5{GzUvct0no>}<m~b0UxWOQ#FfBp6oInMo+7b@9*#cqw z@X)R>HWdCV=gv~7vdYQGNoc!5-k%<&ziErnAf-tndat{d{yth{k$tnsxNBktQP$Io zVs2sY+gLo#YNv|os03igE8HeLeUrrveRWIajQA*RtVG7rjx<Gl7lE$`&q{!V+Sp)E zXo0YWle5#qJK(i-tMDt05v!Z>M8p149Lg-)KT&!U7mLpQmE*3YMm348HTlFA7?;$+ z6U58+G-|v?ytaRmS}2y>TNbN8pS#m1R<(vWhYvQ9xt51oJT1O}FVf2kkeNtZZ#jB+ zDPlN^vImT|2tQ!;vj{(YvDL+3c%^ij!h8!w+JOt9#K%%)HIWAIEKF3sJ0E8z@Og>r zuG)BNHRYXQId~*bO8I||s+~t51^{1{uQg&xrL-oc{74<~43$|<;ASyjG{vO-Jca6H zl5Z;#f>$gEZyA+%jgrCC=MYmTT%KSsM1FSuC1utE56fh)qfkA81_E*s8l?*o)Dnh> z-Sit2bfLv?m#5XpNH}Sbyo=v1{vb-!J;HUMIu@XIq}0r%&^!Y32`nH$GL^_%=?fTZ zLXnj?ykgQgCud)zIpT|8lQ0$K$Qp<=Cq4FXz){%ONv^m^b1(Vrr&A#~dEs~Wg?%jn z80rx;nn)8j9&j~Hqud->IO1#VkPiQ_lyg3LsCCK;^O@qw1G84ieZ)4RjTHR|g{0I^ z9%kjpEyFT2klZ&=Q|_?Q<>7RK(bd@o<7Vd76DN{QmvY#{iD?;ZWGhH(-{Q~#5xu&) z#!uvMc>)2d9p)!f+p7qiN`O``cuJqSdPW5?cOugh=xX=CnmWe_@HT2ss`Vuz|KL<m zf9b&n?L%##^PpWF`yi^erlSb`Ey0(CPi`3=&J$N%v#}C~Z}D`?TOjwqFqHk7bQ3R{ z!EDh?;XG8=>W*ghtc<uVj{@Dwh-OD|U}t8V?lx(1(@`G2To}hW9jcjw-z+k>=~{`I zRjycDi0)fyFKcGOcF*iSuvv-Z`SZ!EzE8!$Ti>C=ST4)jXN%^UdHzC{&2r>%Q*OM- z%){2jO^1Fg*E;kAcKN22<F<|ihvkeJk%PK}bqdUUe=*Cab80%H-e-r$AeB<gN?fTV zG5Ol^iB?A0zZETGC^}d&aP9P1VYCQ4uM##+x?8fNaFfH^PJ}Esi?PEf#L1n;7vM~; z978V(+CkVNbUb!sIaZGCe<icAD)MQVWBxDsz|X3WD=$_@vVrk%(~Ln^)dkq_j70u8 z-Hj|gY+$Lzzp?F-NJ*sBEXNpeK3TfY0jx)iJX$Coyl#>WBN0=sFBX;8XV@_6R9MXy zjn_BCO4uYenKi*vM82Wv<o#i@*lcfRv=ryU<KmTUjyw~kaFtm~VYt1@K=B<ZmZY2M zNv2Hev-2rn=Nz2%mPf{$3YbybYeVkXXhokIEK0IFE{<5Z7GZ?dlHV&*)o6OeXV;g< z+|hCHAZZ=c==pv2Za+yx&wc22oIhJ0@qQN#S4OMMQQVJ~s`jdu1Ynyz-W>0rKn%gK zf5r9s8Vsz)tTM-&nI*Kvh9iqE9Y(986M7a$CYsge1iDTbJ9`EaYrszxW)badBem$b z&a45-^=2he-7LnAv^*tXK=CsYF{^tLGo<t(CCPa-1jNeX4WL4!Sz(<!BUOViPKr#7 zOh!$(4fm?ZZ;Civ@hN78aDS&X=InWLkl4<%e*m;d17xFk>0TB4ZwG%OGTlETKGQ5U zv&p>>%&_8Y5@dCvnT8UdqV#_}EhA?oMzcxN((_rw%}!vNb)sdRWx;>(8W0+qEGIvy z&)Hr7|7EhAa2UG$vHxJU{_DwdcHcE>vYg#(hD{cRfLm1HIA)7QYkL?bASGQ{QoC3z zcq+#J-?AW#Y_l?2JAzZvx~stjE<erzliI5~GK(Ci(K>d<JhN^vdA3<w3WpHp)D<Ri z$}uaFuBAH5wItK(`c+)usE^Ev%r)!Ti3JKPF9E|s8XC+o;-#C)SAb7gZ3(H2X~Z+M zo{*D9rZupWNIM6gWQ(GWXm36%AM8KVZ0xs1Cn0r#IY~^37sq5xq)qNQFEZI|w0Z(t z1fxw*qw~y3W)s>6Bn?@rcyWAc^*N&d$y6%Ye+nn0S#_**)SO5jU$Y5f*I16yP<$tq z5~{e+jT@opu41t9@?!BtyZ{$Toc$9W?Z_$?$8IW&rL&d5CfNf*>Fi`s0{<@3%xt2d z)fZa@8ekz{i=$J_0{>WC*geIZ!cJwY<+_!cq%t-Z%S$@H6;roxkVb=3hgr(t=kz=X ztuofEu(ZnUl4GW#(P9wsL=#g*`~>l=!*DQ7<%&7gtQ$E!#R`UA&C1M53_aC(W{L!I z#rn_MizP>nQJ%(5XKT!fX65h(fx;R4oFHg=_roA)NxT8PS3w#YX=<<<<2(r*x0aph zg<Fpf0HXEZIFu3G>2DNsZqAu0In5+4qowwn5Fe~9rrlf^vpCekyTQT}wdZ{;8SBBf zQYwaX8b}G{bi8y{4V>1=g)}+t;gSX158qr7%j92TAxLNI!8^bQs&U#kj$qp0RF2|2 z%s`UIP=8U1BUvrdH?WQJ#AJASlKWaD`;8e@VHj)nIl2#G;!-@K#x=GH&s(y>evoNM zyJTWvm=5(eW3Z&f%5Hw6$i1a7wi(*~0&^%g6U$5%uSu<Cy)_X>+!;w@XT@=4BB`-d zvj~SYPI@{Por#OLWp*X97#DBd{7V(vT`-V)*Y~Wex4@;*oN1Alm0OC-oNms5Vw*vB zT5WU&u8e;V1IhO<Vp|3&Lb2MR7&KXNY&y-ZEF-m6WC?Ux$zEE~XGLd&U+Hq2-T|`@ z+^R+An6n0Lfoz_ESUE(EECVaH6|r(FCXt+jOCPcZU4rYUrMb~ewqd2mtR{+~K#o%Y zjblQSd0ty|ZqN?<X)Y^|&I3a7pVuCpk7iG_(CnuhZrRZVNJ(cjODCZGLfBgcSb=6G zPZjX^04wf^rVB{NE&z?@LG#W7x6cE2p9sCEfl6B<OHDV84LWlh$+S7oJP~Heyq-;1 z#<#LeXfwC<T;uGeQYoEe&L_hL)Ucu92XT%0hQY}#H%}tUp#6DZg=~HUPRuAaKW0|q zc>s!TR(b+MHVhVkZP7&-1q>B)k$i?>gR0C9e{L=^7vd6m4lhEj&&>r^K6N{ygU`(q zOt(By06)+fh`A8TXpvMzsE1qf+1;mtL1G2|W%P=ZHA|Tp<6oY794EC)KH?1f4J)?* zF}&WS_nk6#jDH1Q^mztzSKt9(+h9v8hp&6gC)>~Wk4lXtMRg?zU7jp7#(y%%FReMr zoc?50q_PgVvC8+aVga1Jp2C*Xh_F13j29fQ1=dNn7Yh;`r1T_}3^Dqmi_OLHQ-Q`7 zd6+vUz8d5|&BTeQ)kXYt;l5-13HkBWK*Ppry?CsGuJiq;Q;d~+ZILy}vFFFnu%2U> z1@YC?0?HNmss7m5V4*SowJd~KSCa5&#@9vG!<_EkXLVQ*KO@y}vVjeFiVG?Ybri{q zZ<L3?w!S=me#FK&^oi4Y>4OdGCKeu{U(!r_|1uj+pdzwM2P*ZUiOtjmPL%WFXUWDO z|K==nwmCnt#XLdMU>2Ixz)*ABTsY0$DOTNiQr6qpi^E+c4`Sqn9qHS<!Y1yzbE{TE zZm-eTsbX|z;-D?*S;tMO|G@djL*zc_B5*Tmd-2IX_{h2`krSZ%K*^jxFY?ZmfA22h z5z52RQjWq#zLN_6hpxif9p_M0I0~s5a`q*=IJPM1SUj?b_fTFhf!#v|-d@DdrPwon zso!?x)9)|h-{53atHeonFZmj8X*m(>#UX-iz^FZF89!HkL$w;J_TEr66gN@pBLm3@ z%kf0T3wKZItU_`kC+SwB3!SY293tI<R6Qqoh8GIMIp%}AaST%Vf8q({=b<Ey1!7b| zI%ChLkX!7yr(~@3oJtJj(Z*<Z=km-!YU2*TxO=NDzo$-qPv56sef1UQqYz>E@8}+E zmxm4WhVl!jAM%3oy#y=|D8G=xU+Vw`9ZSV;?wvIHdYk0tE<5h!uSwnh#Q}{ZZI^wJ zh51Ej95@Ygn(~XqBloR~NiV5xofQl@5~Xuay5vW>6o<}Gq^I;5Ox4g8I_s`lE2YWf zOUrvo(MxD-mlC*)z_$rVhiZ&Gs{C?_4|-DhK8jvJV3Y&ZpfqxkTK5{HFSmu#MtM=C zXSIpSeT#CXXZJ=#;iKi=a0r(i>3lem6^_KnnV7sO$w&ETucW%t3yYio0lIGd5H)!f zCHE27PvCY+6BOD*p#u~O5I6_`zo@)$O$W-&xWO3aW2n$Iluxc#9y>(vS_0P*AXh8D z9)R4vbfbb#qm;L)){PXJOyDL0GYP~A^b>GVk?&IIIM+1bIfbJ?g8Oji;0UB)$>8Zq zEP1?g9B(VX8I2{fB<gbfaIE8KobSZpGC5tX1Esa-mM)0MGiT{dJ%#cH2%Fm|bUT4N z2;52F`vk}nYk6j!cTxOgapyoqYzGC`5tvW;(&u_BMdeZU;2E%W3MPHFcT?^j0!ygI z)fBpiz`X?SBS4bN@23#CZ}qgWuTwgYe?UnC1Rfx;URA`#2QFCrG8J-3&%TFlcv9^j zQh`PaNgxlD@~nAf<Q)!mbsE9Q<)p|Ci1Z(>&nd&TGPljH7U5Q^3&+r%Kb$1tIPvHY zOXt<7<78f~mX8u=sdKafbrtRr<WoG&sTQbf)eVRtRb8WQQmYZlRTpcb?7@Y&U9|bZ z?dl5y4?cK@HtYtl)B=a>;=D&XT#o@=i26G5#Utf~O9pW#wB;k7>+E9ukBVY~;$H!* zX~?sV4Nsu5R6AksFnYt*dFdW1CPn%z3Q3XX6gruJl;M>W!gFDen82V<KXqwgDWzUQ zg<htR<ej@VQc$+>IECJ#Y~m%$BQF_*7y$1IlIKK3dkjl9Ax9<W0au+naU>uQ1j1L? zMdqW^w4bR1CqBAeD>_0AzewOG1dbB;DJ}SmMpN!lyU2MW*p#9iq45$*kLYf2?j;c) zw~ITUD3?U^{R8@*kE2Q!IrB%6lOLm=YpK8<0z=gFQpSHp(%eDGC6WeEeTb%`sJVd} zACgFUZL^;GA0#e+g^C=XusJEh?!se=_DJ|XySVSi3$#~N@#&8v#f_+lrPI0+Lybso zdYSG9On(yb*X<An(nty}XBVhtDyP&|C#B#o4__v}W%$B}#iLJpV?AF+(o8&O!iM7W zC>|C?vlt!{_1uY6mrT78zEGTbbU67{-4~jU@aGYGMD^qP5S@p3;RnVGM#nxpi$a=u zoHXq?X|}<%n5<0Oq-aL4EP^*tXeNCyTcf5a51Y;`c@?U}%!!g~7V*7WG^_hU>`^lD z4lA2%;0WFW#GUjaifMGEQNGf0ur#D$uP5JFW#K7;%w4E-2RAF*O$Y8*JvKC^k)s(F z!#IY;Faj$kQO`xkE_9MRykiU^OFZy&UHV5eKyGQ1owaJR$bF`1iQ8I7C2P{5C!PUC zJgpr(7vW*Ir{wzi1*Or%$t%Iuqmevu`7;yO{E=!pp;+nG;h(6)p9%bhz;*&H0J;+= zrnpmV3Hkp}@?QyjLV20iMdCoH)e{gUho_DG4e<|I7z$KhHh3ssqhA-)WVUEOTroKp z*ZvoSv-lg}tAwi=Yq&4i+?+`3;)cB6x0$%oGJC~Cha1%~;+?~r#pTalZ?8d)c>CG$ z;<V?UQvWEjpAXl*PnbxtBy$9J{y(CG-w|jhAQe-axb6AMN%I`QO!6^$uUGl|#Mc@M z(I0Vq8a~O_FNiOmzob~fbjS;I%+X<ohepNzM~SD2sv`w<8MyC-VpT@P8!u!bwBtzG z$c$3Qld|CXN5;$SO2AaOOgwgEN-TNDN*-GuLifYYv-1(f6^vl7R6V%2B$rXS$Q~vN zT}H*H0qB`H6ty0D;5vXDFxJG;>mGjsX(tg0h-VaBWhzkZ;{os*Nu7m-szjZk)~a*x ztEu%G!CI9+F|hx|kUD7;etW2Exu_757DHtw@e`AdRu)PGr2-=alS_nXKDt8N;t;nU zt<gSG2aX=~sWE8+N+urJChn~d4p+}JJUrkt@OUh_qJ$F}Z9a}Tod)A|O1mfMg^6Pw z4v+4Z5crVjv5A0O3nZXLNIdXTuGZ-g&%IQmeG2{f(kDeelp4A<qsogDyX%BHwLqxH zirPmlrQf2~hwxuX(IF#Fn&Crd<mq}k&6IUT@l+H|xY~R;&WD9L?3%5dz;$BxvB_G@ zA#Oib<@^jNwQAz?mkPu?$KJwz<*8TZs6P;Ydu7_#KAO;6G^M~G$;RB};!<NHe)-?j zf#pBDN>i^Azx?^E*!|R-J!14kk~_;g7GXgJvb54BcWk@e%jjAJjHjw|qg8T0BX>65 zPtSaK+(n<<|6_0EMV}z}#Ui;{HjJ^>znjstWv7$W4^vChivJsRa)sQeNoq)f&7#EF z1Wu+ZKO-=TbVM~gG+K#5dV0#J!^uAtB?{>dy8AiZ`kBH1igF2O8{W5JAL*t_nN$h) z4LKNt3+HPSwCf#W(rc3ozeMhC=b9}Wo2Jdt)7EcZ);w*-Oc8!<qIy(Z`&#Ar-y)yC zO<*B)7DWiwguE>z!9(Kx*A|r&2SOe=s;XK&!BDW(=Lu9<Z`(xlmlundLOH|il)Ck3 z=N~jtq->m)DTn)5k}=3q=T8Cbt{1s&rD9xXj>vACCSLhfk#N3|EABa|cvw@F)YJjz zU{gR0Rg?EMRsNpH4i--z^d0Dq04B4m!KP=y_7CEfCpJuYmo2HKrw2pL){PG_G1w&j z@VetT9R{ewn}#|}xOe$jq#cj5abY}++xB!{f>!~+rU(HStS0R+>UtBIUhZSzE~B-% zW0$;j1ui3d5kK|#@wUmo&r+TaT%r1hs0xjBNcV$S9a@R2PP<w_hxr96=!R;<UKsE? z>QTCb))8{|4<WbP(R^<7+$c!93_T3d_aj>SK5`StrpgYq$Dcx|6~*MA4G`;=vP|6D zRVcP~6<B+9X?T4?rqOun>an4&j$5<AszvJ}9`&MDKGk}Bs22Z)DqP*wweKN0C3LoP zqZ1J>B#adR-MN8-ox;3AZ0tTQ?WeLaMT8T}vCnxpai~^zo+eoj*97VEl6-t;Y1p4r z^fv@9R>Wn$_Dln{1VtsMkzzvv2?y_@)B=Qdr%$K~wN-WEDHm5YarYZj)oStP8xvwu zs-;o9vca)I3j7A?A6wY~1SumKC65tBQ$HH7LTqJ&wgDgiJM|{B|0eh72@S6h(~RIb zJ{}6<zTM8wu3o7>6M1;)OON*hzLqIny))%IerH!N{YpKPK%_m~*(q;IVKZoWT0%U? zNtNKu1NJ=M6$jotUA;uS^JcXg6^^%B)rG?MR{dmRx<oEra_WLEh=jW6sYBS>jY}Vc zT!W;cbh&u^t%>C?0e`t|*VF075$Tbz<tzBL_~%<QV-HjQPYC>tz~2e{FM)p%ID<wk zw@6zkL>DQ!bbiPkLy)2m5_o~Y&j`FqfQ)Qu5m^t>eoxW)1n4?g!cE$SRyaK4%nRvG zX>=uTY8_L>6Tc~s(R#w?QVsF|CDLeR0eP)EY?3pi{{1DDc%8tn2qXv`qN-%l;s0Ln z1wDag**q@TVRjPs?w!7fw3Va<!9SuJpAw*D3Cj!sRBDx?yP;6zGci2A4qJTq73I#R z=9h{+Zx^-yh&oAb!12Zv>$;_oUZ-@oe0Z9AMEVFNr6>35ctH9bn$q(zfjks$Zt0b) zW-~ptyoWN9?*XuS`NRBos`%<{rrsskZ#x%f(;Sjr+1v)tV_0s&^lVat&7_@tZ9W)H zhD4E&9ke>+I|IC!6Kmd?6ML5WNNY(pK|ZQP1~+hlR=#+(u9tmG)juJylUjR-04+<L z3{xErD_V)bgGQULheMbZ{tgwHMPLho7=hCP^kVD5ersSSxkjh7i$8SZe{Ry+TN7!x zRM_FceaR1~9CmteZZ*TJgZ~Qv|7!;RPZ4_T6T<z|&V;(o+RvYYlDH9Q{nr>_>E20b zcxFRd*fQeUsN-}fMLjRsC1Gkg&U9Csl@{aHp7A*<oJVy@wcuG3`Q)U^`vc|dp~N%} zlfEUi%ks66zegWK|DA_*^^#ET3gBX-T*$FtpandQlIFr*YNL}{4-k;vGU=MQrh($p zk0!lsQz?2Um6qn#s}wqjw1jGiJKmYHC6T_Or`3?ME}tSN9Q5=#`QHu%sdNFY0<8$? zZfgV71FWEI3MoBIC8ULN2Ze4Wa0`J5o-CG#P48x7XCT_%J#*!`uF~wTjPh&;-Up;* zFju*&%2n(dgMZZ-F=ZmYm}1YU&ZtLj4R%A=5#=UfuIkq8E<0RJZsB-u0Ui@Bey>8c ziyiNs*sf)3MXFt+ZBvQdJe8;=&MBH3)$Q<6;oY<yPfyhveDa^>vNl`Dr4A@B11Ux7 zWc=E9m0=@KUMsiSNd77^`?XrF1|7c~E_XJ%3e;IJf5X$TM|<<V1uN2A*tAhEx%kR# ox%kb-=T>XVGqhav<;La!|FkOlXLD->z?M?oD2L4+VX*!G01_bA8vp<R diff --git a/__pycache__/simplex_plot.cpython-310.pyc b/__pycache__/simplex_plot.cpython-310.pyc new file mode 100644 index 0000000000000000000000000000000000000000..2c4249fdd0ebd95ed28071c9f8d211aa84a2bb34 GIT binary patch literal 3059 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 literal 0 HcmV?d00001 diff --git a/__pycache__/simplex_plot.cpython-37.pyc b/__pycache__/simplex_plot.cpython-37.pyc index d40c9990e4c7cc9a2781a81174008f4cb3e8b339..a8537b6f9da6be3317317d69450bbe8640da3809 100644 GIT binary patch delta 960 zcmZWnJ!}(66rMM`Uhj|XIL7}z5`-_hGeyWz@FNjSq7xiKqCvXCP2|g4n@#MEnccgC zXsJTVAfhP{RCa+-5Tc>Hf`aY@x(?~4IKg%4=xKOk5LetA&71H2%s1aY?eof$YIZf7 zbs5>8Vio_`&(`3d{qJsEcaT=!KtSl(=%RNQIwj0t_Acv`{R-wbxllOMsrr0e!#u57 z>Ymkz&H^5po<%HSf#MRDv9$lLHsfFgt9wRg4*7M~s=ctG1&fMp&)~0OEeeLCfq!dp z6!tGE*j#tCEV2x3E%7St=wJCWzv#IMjI9Y9rxRCB_?0VO%r<5cPs`oqX!dxGCFu(L zn(?L?yTW=LGYK2#(3=2ei!6Y|dBE=hus9o=8+rK`ubxK}b9;O|iyo#Yd<X7$aUo$l zx~Z_kv`@Tg^#4aadDA!odAVy`z=S@0)3^`f8L2B%RF2JYiYNi?2E)o!O%-c<22rwc zWumFsMl~_9jt%?<kM5bkk`yt#rFu=*Lz_@tBLte@ocw4UfGHoFOJK;i=II}88j{e{ z>OXp@?cinq&1-ER+RE7K^#s?opWbg5pI`pF{iW$)`>;ys7AP|cwtcyrItdLqO#Qx+ zj@G+z><eWM{cfnz!jEorN4`ppL=eWxj{JD-)*u*uMz;wGkC>F*4a2Rt8~d_hEkH)D zSdEfO#X&sqJ8snd&0m{hu_!mJHk^@9t*d8G(M9Iikl{Hff(_aitvOgVmMF4lpEvT5 z=PtN#oZC>KoXf?z7Ypf^a3W2Y`<j8VckM6WLt9uBA8IG`?{uwYi@MA?wQ_?ZWvp*S zijM+iL_tWUCAsW0i)VEA)ScC+Np3~P&H^;$Bj>==JT0zZoy1>r%TSlTI}c^K>(0*~ zqgp3F?8c+PRy+uPSsVnRAF0&z5LNlg?O5liM>J*AYkj*+P#FV16qj}K2kriQ{j&r) X^1d&-P(NuOwYizf&=~Z}@eKb2(cJ2G delta 833 zcmah`%}*0S6yG=dHM`rE7PjB=5s_$7lmJm;5Df>TA@O43VGnMa&QJ<%X=WFNrp80T z8%8oFUevS~4bgZZ@#<gT!JAo)cMe|s1B^3}=+T+X@BQA)do%C%=56jnHog>(+lm<7 zCrMJ=kLTh0{@K;XnBb~PfWV4LEMo6~mnII0?I>P`W=VV<v9BcI<tXaq$$*$i5uKDw z*c2H&wnM}vDdD>$P28$l)%)NTXpx?xxh{0U8>VSmAedxGc2D(22)e73a_ukny;^XX zgmIW?<B$g7#a6R=GlKOBmSu|Jh$Ty27AxrSGP>bd9q1W-rDt|5{vO@FZHEILy9=O% z%388xOCh_6Xe%hM{Pi5^tsoNXD7^%6`at5YQiBeDfu73Dc&M$V_@X*GJ1C@^ebj|V z_W$matq8SVioa18=R>8J=_|)YWJM2zPLd<}Jq?tO_6*o_ah{XsO)OYmG6JFp1%69A z0G0pJrUCJB{jy;SrOe{KUP!eE$R_iHTBB8`Te3C$m3|2d{ImY>ir!+iW*C`4r5uKo zMOuTFn~}+Auv%`>2nRIux9YXV3ELKo$v*O3V*(uh&L}24J19S(epn0Zluhz)#&wwC zMRR$2Qp711h8RkK3m7E2#)x27)oEBzlaNF<!Y~L1*oe&?zBWGr82rAKnbJk-ks*M| zAG}k-EGulJw<+5QBK@Q|ot2wa%5uDKxp0Ahw8q^TnQ{!Xl8p(t#(!E9Fvf@MgVXY| z5{jV0WO1d@$n<@(QStpqZ*DeP+bqj}*rPDSe+wMuBhE0S`GVsab0VCL@t02N%)FqH kTBl96BsZrd{CoD~ZGPmO%U~#+$HN$DdQ51RGl6304{KAx@Bjb+ diff --git a/analysis_pmf.py b/analysis_pmf.py index 637f06cd..03e55c1d 100644 --- a/analysis_pmf.py +++ b/analysis_pmf.py @@ -7,8 +7,30 @@ import seaborn as sns type2color = {0: 'green', 1: 'blue', 2: 'red'} all_conts = np.array([-1, -0.5, -.25, -.125, -.062, 0, .062, .125, .25, 0.5, 1]) +performance_points = np.array([-1, -1, 0, 0]) + +def pmf_to_perf(pmf): + # determine performance of a pmf, but only on the omnipresent strongest contrasts + return np.mean(np.abs(performance_points + pmf[[0, 1, -2, -1]])) + +contrasts_L = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0]) +contrasts_R = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0])[::-1] + +def weights_to_pmf(weights, with_bias=1): + psi = weights[0] * contrasts_R + weights[1] * contrasts_L + with_bias * weights[-1] + return 1 / (1 + np.exp(psi)) def pmf_type(pmf): + rew = pmf_to_perf(pmf) + if rew < 0.6: + return 0 + elif rew < 0.7827: + return 1 + else: + return 2 + + +def pmf_type_old(pmf): if pmf[-1] - pmf[0] < 0.2: return 0 # elif pmf[-1] - pmf[0] < 0.4:# and np.abs(pmf[0] + pmf[-1] - 1) > 0.1: @@ -59,6 +81,30 @@ if __name__ == "__main__": all_pmfs = pickle.load(open("all_pmfs.p", 'rb')) all_bias_flips = pickle.load(open("all_bias_flips.p", 'rb')) + _, axs = plt.subplots(1, 3, figsize=(16, 9)) + for defined_points, pmf in all_first_pmfs_typeless['KS014']: + axs[pmf_type(pmf)].plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)]) + if np.round(pmf_to_perf(pmf), 2) in [0.86, 0.81]: + axs[pmf_type(pmf)].annotate(np.round(pmf_to_perf(pmf), 2), (8.7, pmf[-1] - 0.05), size=19) + else: + axs[pmf_type(pmf)].annotate(np.round(pmf_to_perf(pmf), 2), (8.7, pmf[-1] + 0.02), size=19) + for i, a in enumerate(axs): + a.spines[['right', 'top']].set_visible(False) + a.set_ylim(0, 1) + if i != 0: + a.set_xticks([]) + a.set_yticks([]) + else: + tick_size = 14 + a.set_xticks(np.arange(11), all_conts, size=tick_size, rotation=45) + a.set_yticks([0, 0.25, 0.5, 0.75, 1], [0, 0.25, 0.5, 0.75, 1], size=tick_size) + a.set_ylabel("P(rightwards)", size=26) + a.set_xlabel("Contrasts", size=26) + plt.tight_layout() + plt.savefig("ks014_pmfs") + plt.close() + + # bias flips # plt.hist(all_bias_flips, bins=np.arange(0, max(all_bias_flips) + 1), color='grey', align='left') # plt.ylabel("# of mice") @@ -159,7 +205,92 @@ if __name__ == "__main__": # plt.xlabel("Higher lapse rate") # plt.show() - lw = 4 + lw = 7 + + # indiv examples + + state_num = 6 + defined_points, pmf = all_first_pmfs_typeless['CSHL061'][state_num][0], all_first_pmfs_typeless['CSHL061'][state_num][1] + plt.plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)], lw=lw) + + plt.ylim(0, 1) + plt.xlim(0, 10) + plt.yticks([]) + plt.gca().set_xticks([]) + sns.despine() + plt.gca().spines['left'].set_linewidth(4) + plt.gca().spines['bottom'].set_linewidth(4) + plt.tight_layout() + plt.savefig("single exam 1") + plt.close() + + + state_num = 7 + defined_points, pmf = all_first_pmfs_typeless['NYU-06'][state_num][0], all_first_pmfs_typeless['NYU-06'][state_num][1] + plt.plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)], lw=lw) + + plt.ylim(0, 1) + plt.xlim(0, 10) + plt.yticks([]) + plt.gca().set_xticks([]) + sns.despine() + plt.gca().spines['left'].set_linewidth(4) + plt.gca().spines['bottom'].set_linewidth(4) + plt.tight_layout() + plt.savefig("single exam 2") + plt.close() + + + + state_num = 3 + defined_points, pmf = all_first_pmfs_typeless['ibl_witten_14'][state_num][0], all_first_pmfs_typeless['ibl_witten_14'][state_num][1] + plt.plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)], lw=lw) + + plt.ylim(0, 1) + plt.xlim(0, 10) + plt.yticks([]) + plt.gca().set_xticks([]) + sns.despine() + plt.gca().spines['left'].set_linewidth(4) + plt.gca().spines['bottom'].set_linewidth(4) + plt.tight_layout() + plt.savefig("single exam 3") + plt.close() + + + state_num = 1 + defined_points, pmf = all_first_pmfs_typeless['CSHL_018'][state_num][0], all_first_pmfs_typeless['CSHL_018'][state_num][1] + plt.plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)], lw=lw) + + plt.ylim(0, 1) + plt.xlim(0, 10) + plt.yticks([]) + plt.gca().set_xticks([]) + sns.despine() + plt.gca().spines['left'].set_linewidth(4) + plt.gca().spines['bottom'].set_linewidth(4) + plt.tight_layout() + plt.savefig("single exam 4") + plt.close() + + + state_num = 4 + defined_points, pmf = all_first_pmfs_typeless['ibl_witten_17'][state_num][0], all_first_pmfs_typeless['ibl_witten_17'][state_num][1] + plt.plot(np.where(defined_points)[0], pmf[defined_points], c=type2color[pmf_type(pmf)], lw=lw) + + plt.ylim(0, 1) + plt.xlim(0, 10) + plt.yticks([]) + plt.gca().set_xticks([]) + sns.despine() + plt.gca().spines['left'].set_linewidth(4) + plt.gca().spines['bottom'].set_linewidth(4) + plt.tight_layout() + plt.savefig("single exam 5") + plt.show() + + + # Simplex example pmfs state_num = 7 defined_points, pmf = all_first_pmfs_typeless['NYU-06'][state_num][0], all_first_pmfs_typeless['NYU-06'][state_num][1] @@ -211,7 +342,7 @@ if __name__ == "__main__": plt.tight_layout() plt.savefig("example type 3") plt.show() - quit() + n_rows, n_cols = 5, 6 _, axs = plt.subplots(n_rows, n_cols, figsize=(16, 9)) @@ -356,7 +487,7 @@ if __name__ == "__main__": # All first PMFs tick_size = 14 label_size = 26 - all_first_pmfs = pickle.load(open("pmfs_temp.p", 'rb')) + all_first_pmfs = pickle.load(open("all_first_pmfs.p", 'rb')) n_rows, n_cols = 1, 3 _, axs = plt.subplots(n_rows, n_cols, figsize=(16, 9)) save_title = "all types" if True else "KS014 types" @@ -407,6 +538,9 @@ if __name__ == "__main__": else: use_ax = int(pmf[0] > 1 - pmf[-1]) + pmf_min = min(pmf[0], pmf[1]) + pmf_max = max(pmf[-2], pmf[-1]) + defined_points = np.logical_and(np.logical_and(defined_points, ~ (pmf > pmf_max)), ~ (pmf < pmf_min)) ax[use_ax].plot(np.where(defined_points)[0], pmf[defined_points], c='b') ax[0].set_ylim(0, 1) ax[0].set_xlim(0, 10) diff --git a/behavioral_state_data.py b/behavioral_state_data.py index 2f1f3f02..be9aef83 100644 --- a/behavioral_state_data.py +++ b/behavioral_state_data.py @@ -41,7 +41,7 @@ def get_df(trials): df['feedback'] = df['feedback'].replace(-1, 0) df['signed_contrast'] = df['contrastR'] - df['contrastL'] df['signed_contrast'] = df['signed_contrast'].map(contrast_to_num) - df['response'] += 1 + df['response'] += 1 # this is coded most unintuitely, 0 is rightwards, and 1 is leftwards (which is why I not this variable in other programs) df['block'] = trials['probabilityLeft'] # df['rt'] = data_dict['response_times'] - data_dict['goCue_times'] # RTODO @@ -49,11 +49,7 @@ def get_df(trials): misses = [] to_introduce = [2, 3, 4, 5] -subjects = ['ibl_witten_13', 'ibl_witten_17', 'ibl_witten_18', - 'ibl_witten_19', 'ibl_witten_20', 'ibl_witten_25', 'ibl_witten_26', - 'ibl_witten_27', 'ibl_witten_29', 'CSH_ZAD_001', 'CSH_ZAD_011', - 'CSH_ZAD_019', 'CSH_ZAD_022', 'CSH_ZAD_024', 'CSH_ZAD_025', - 'CSH_ZAD_026', 'CSH_ZAD_029'] +# subjects = ['ZFM-05236', 'ZFM-05245'] # subjects = ['CSHL045', 'CSHL046', 'CSHL049', 'CSHL051', 'CSHL052', 'CSHL053', 'CSHL054', 'CSHL055', # 'CSHL059', 'CSHL061', 'CSHL062', 'CSHL065', 'CSHL066'] # CSHL063 no good # subjects = ['CSHL_007', 'CSHL_014', 'CSHL_015', 'CSHL_018', 'CSHL_019', 'CSHL_020', 'CSH_ZAD_001', 'CSH_ZAD_011', @@ -77,7 +73,7 @@ subjects = ['ibl_witten_13', 'ibl_witten_17', 'ibl_witten_18', # "ibl_witten_06", "ibl_witten_07", "ibl_witten_12", "ibl_witten_13", "ibl_witten_14", "ibl_witten_15", # "ibl_witten_16", "KS003", "KS005", "KS019", "NYU-01", "NYU-02", "NYU-04", "NYU-06", "ZM_1367", "ZM_1369", # "ZM_1371", "ZM_1372", "ZM_1743", "ZM_1745", "ZM_1746"] # zoe's subjects -# subjects = ['CSHL_018'] +subjects = ['ibl_witten_14'] data_folder = 'session_data' # why does CSHL058 not work? @@ -101,7 +97,7 @@ for subject in subjects: print('_____________________') print(subject) - eids, sess_info = one.search(subject=subject, date_range=['2015-01-01', '2023-01-01'], details=True) + eids, sess_info = one.search(subject=subject, date_range=['2015-01-01', '2025-01-01'], details=True) start_times = [sess['date'] for sess in sess_info] protocols = [sess['task_protocol'] for sess in sess_info] diff --git a/behavioral_state_data_easier.py b/behavioral_state_data_easier.py new file mode 100644 index 00000000..e526d7cc --- /dev/null +++ b/behavioral_state_data_easier.py @@ -0,0 +1,200 @@ +from one.api import ONE +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import seaborn as sns +import pickle +import json + +one = ONE() + + +contrast_to_num = {-1.: 0, -0.5: 1, -0.25: 2, -0.125: 3, -0.0625: 4, 0: 5, 0.0625: 6, 0.125: 7, 0.25: 8, 0.5: 9, 1.: 10} + +dataset_types = ['choice', 'contrastLeft', 'contrastRight', + 'feedbackType', 'probabilityLeft', 'response_times', + 'goCue_times'] + +def get_df(trials): + if np.all(None == trials['choice']) or np.all(None == trials['contrastLeft']) or np.all(None == trials['contrastRight']) or np.all(None == trials['feedbackType']) or np.all(None == trials['probabilityLeft']): # or np.all(None == data_dict['response_times']): + return None, None + d = {'response': trials['choice'], 'contrastL': trials['contrastLeft'], 'contrastR': trials['contrastRight'], 'feedback': trials['feedbackType']} + + df = pd.DataFrame(data=d, index=range(len(trials['choice']))).fillna(0) + df['feedback'] = df['feedback'].replace(-1, 0) + df['signed_contrast'] = df['contrastR'] - df['contrastL'] + df['signed_contrast'] = df['signed_contrast'].map(contrast_to_num) + df['response'] += 1 # this is coded most unintuitely, 0 is rightwards, and 1 is leftwards (which is why I not this variable in other programs) + df['block'] = trials['probabilityLeft'] + # df['rt'] = data_dict['response_times'] - data_dict['goCue_times'] # RTODO + + return df + +misses = [] +to_introduce = [2, 3, 4, 5] + +amiss = ['UCLA034', 'UCLA036', 'UCLA037', 'PL015', 'PL016', 'PL017', 'PL024', 'NR_0017', 'NR_0019', 'NR_0020', 'NR_0021', 'NR_0027'] +subjects = ['NYU-21'] +fit_type = ['prebias', 'bias', 'all', 'prebias_plus', 'zoe_style'][0] +if fit_type == 'bias': + loading_info = json.load(open("canonical_infos_bias.json", 'r')) + r_hats = json.load(open("canonical_info_r_hats_bias.json", 'r')) +elif fit_type == 'prebias': + loading_info = json.load(open("canonical_infos.json", 'r')) + r_hats = json.load(open("canonical_info_r_hats.json", 'r')) +already_fit = list(loading_info.keys()) + +remaining_subs = [s for s in subjects if s not in amiss and s not in already_fit] +print(remaining_subs) + + + +data_folder = 'session_data_test' + +old_style = False +if old_style: + print("Warning, data can have splits") + data_folder = 'session_data_old' +bias_eids = [] + +print("#########################################") +print("Waring, rt's removed, find with # RTODO") +print("#########################################") + +short_subjs = [] +names = [] + +pre_bias = [] +entire_training = [] +for subject in subjects: + print('_____________________') + print(subject) + + if subject in already_fit or subject in amiss: + continue + + trials = one.load_aggregate('subjects', subject, '_ibl_subjectTrials.table') + + # Load training status and join to trials table + training = one.load_aggregate('subjects', subject, '_ibl_subjectTraining.table') + trials = (trials + .set_index('session') + .join(training.set_index('session')) + .sort_values(by='session_start_time', kind='stable')) + + start_times, indices = np.unique(trials.session_start_time, return_index=True) + start_times = [trials.session_start_time[index] for index in sorted(indices)] + task_protocol, indices = np.unique(trials.task_protocol, return_index=True) + task_protocol = [trials.task_protocol[index] for index in sorted(indices)] + nums, indices = np.unique(trials.session_number, return_index=True) + nums = [trials.session_number[index] for index in sorted(indices)] + eids, indices = np.unique(trials.index, return_index=True) + eids = [trials.index[index] for index in sorted(indices)] + + print("original # of eids {}".format(len(eids))) + + test = [(y, x) for y, x in sorted(zip(start_times, eids))] + pickle.dump(test, open("./{}/{}_session_names.p".format(data_folder, subject), "wb")) + + performance = np.zeros(len(eids)) + easy_per = np.zeros(len(eids)) + hard_per = np.zeros(len(eids)) + bias_start = 0 + + info_dict = {'subject': subject, 'dates': [st.to_pydatetime() for st in start_times], 'eids': eids} + contrast_set = {0, 1, 9, 10} + + rel_count = -1 + quit() + for i, start_time in enumerate(start_times): + + rel_count += 1 + + df = trials[trials.session_start_time == start_time] + df.loc[:, 'contrastRight'] = df.loc[:, 'contrastRight'].fillna(0) + df.loc[:, 'contrastLeft'] = df.loc[:, 'contrastLeft'].fillna(0) + df.loc[:, 'feedbackType'] = df.loc[:, 'feedbackType'].replace(-1, 0) + df.loc[:, 'signed_contrast'] = df.loc[:, 'contrastRight'] - df.loc[:, 'contrastLeft'] + df.loc[:, 'signed_contrast'] = df.loc[:, 'signed_contrast'].map(contrast_to_num) + df.loc[:, 'choice'] = df.loc[:, 'choice'] + 1 + + if any([df[x].isnull().any() for x in ['signed_contrast', 'choice', 'feedbackType', 'probabilityLeft']]): + quit() + + assert len(np.unique(df['session_start_time'])) == 1 + + current_contrasts = set(df['signed_contrast']) + diff = current_contrasts.difference(contrast_set) + for c in to_introduce: + if c in diff: + info_dict[c] = rel_count + contrast_set.update(diff) + + performance[i] = np.mean(df['feedbackType']) + easy_per[i] = np.mean(df['feedbackType'][np.logical_or(df['signed_contrast'] == 0, df['signed_contrast'] == 10)]) + hard_per[i] = np.mean(df['feedbackType'][df['signed_contrast'] == 5]) + + if bias_start == 0 and df.task_protocol[0].startswith('_iblrig_tasks_biasedChoiceWorld'): + bias_start = i + print("bias start {}".format(rel_count)) + info_dict['bias_start'] = rel_count + if bias_start < 33: + short_subjs.append(subject) + + pickle.dump(df, open("./{}/{}_df_{}.p".format(data_folder, subject, rel_count), "wb")) + + side_info = np.zeros((len(df), 2)) + side_info[:, 0] = df['probabilityLeft'] + side_info[:, 1] = df['feedbackType'] + pickle.dump(side_info, open("./{}/{}_side_info_{}.p".format(data_folder, subject, rel_count), "wb")) + + fit_info = np.zeros((len(df), 3)) + fit_info[:, 0] = df['signed_contrast'] + fit_info[:, 1] = df['choice'] + print(len(df)) + # fit_info[:, 2] = df['rt'] # RTODO + pickle.dump(fit_info, open("./{}/{}_fit_info_{}.p".format(data_folder, subject, rel_count), "wb")) + + if rel_count == -1: + continue + plt.figure(figsize=(11, 8)) + print(performance) + plt.plot(performance, label='Overall') + plt.plot(easy_per, label='100% contrasts') + plt.plot(hard_per, label='0% contrasts') + plt.axvline(bias_start - 0.5) + skip_count = 0 + for p in performance: + if p == 0.: + skip_count += 1 + else: + break + for c in to_introduce: + plt.axvline(info_dict[c] + skip_count, ymax=0.85, c='grey') + plt.annotate('Pre-bias', (bias_start / 2, 1.), size=20, ha='center') + plt.annotate('Bias', (bias_start + (i - bias_start) / 2, 1.), size=20, ha='center') + plt.title(subject, size=22) + plt.ylabel('Performance', size=22) + plt.xlabel('Session', size=22) + plt.xticks(size=16) + plt.xticks(size=16) + plt.ylim(bottom=0) + plt.xlim(left=0) + + sns.despine() + plt.tight_layout() + if not old_style: + plt.savefig('./figures/behavior/all_of_trainig_{}'.format(subject)) + plt.close() + + # print(bias_eids) + pre_bias.append(info_dict['bias_start']) + entire_training.append(rel_count + 1) + + info_dict['n_sessions'] = rel_count + pickle.dump(info_dict, open("./{}/{}_info_dict.p".format(data_folder, subject), "wb")) +print(misses) +print(short_subjs) + +print(pre_bias) +print(entire_training) diff --git a/behaviour_overview.py b/behaviour_overview.py index 1a4899e6..f38eca39 100644 --- a/behaviour_overview.py +++ b/behaviour_overview.py @@ -5,7 +5,7 @@ from one.api import ONE import pickle -show = 0 +show = 1 def progression(data, contrasts, progression_variable='feedback', windowsize=6, upper_bound=None, title=None): # looks somewhat irregular, red dots are not in middle of bump they cause, this is because distribution of specific contrasts is not uniform @@ -47,12 +47,37 @@ def progression(data, contrasts, progression_variable='feedback', windowsize=6, # plt.title(title, size=22) # plt.savefig("temp {}".format(title).replace('/', '_')) # plt.close() + if progression_variable == 'feedback': + data_local = data[:113] + means = data_local.groupby('signed_contrast').mean()['response'] + stds = data_local.groupby('signed_contrast').sem()['response'] + plt.errorbar(means.index, means.values, stds.values, label='1') + + data_local = data[113:226] + means = data_local.groupby('signed_contrast').mean()['response'] + stds = data_local.groupby('signed_contrast').sem()['response'] + plt.errorbar(means.index, means.values, stds.values, label='2') + + data_local = data[226:339] + means = data_local.groupby('signed_contrast').mean()['response'] + stds = data_local.groupby('signed_contrast').sem()['response'] + plt.errorbar(means.index, means.values, stds.values, label='3') + + data_local = data[339:] + means = data_local.groupby('signed_contrast').mean()['response'] + stds = data_local.groupby('signed_contrast').sem()['response'] + plt.errorbar(means.index, means.values, stds.values, label='last') + plt.title(title, size=22) + plt.ylim(0, 1) + plt.legend() + # plt.savefig("temp {}".format(title).replace('/', '_')) + plt.show() if progression_variable == 'rt': means = data.groupby('signed_contrast').mean()['rt'] stds = data.groupby('signed_contrast').sem()['rt'] plt.errorbar(means.index, means.values, stds.values) plt.title(title, size=22) - plt.savefig("temp {}".format(title).replace('/', '_')) + # plt.savefig("temp {}".format(title).replace('/', '_')) plt.close() @@ -95,8 +120,8 @@ exclude_eids = ['a66f1593-dafd-4982-9b66-f9554b6c86b5', 'ee40aece-cffd-4edb-a4b6 # project='ibl_neuropixel_brainwide_01') # traj.reverse() -subject = 'KS014' -eids, sess_info = one.search(subject=subject, date_range=['2015-01-01', '2022-01-01'], details=True) +subject = 'KS022' +eids, sess_info = one.search(subject=subject, date_range=['2015-01-01', '2024-01-01'], details=True) start_times = [sess['date'] for sess in sess_info] protocols = [sess['task_protocol'] for sess in sess_info] @@ -107,8 +132,11 @@ protocols = [x for _, x in sorted(zip(start_times, protocols))] # for t in traj: counti = 0 for i, (prot, eid) in enumerate(zip(protocols, eids)): + print("Nice demonstration that the PMF jump is actually quite sudden!") print(i) - if not prot.startswith('_iblrig_tasks_trainingChoiceWorld'): + # if not prot.startswith('_iblrig_tasks_trainingChoiceWorld'): + # continue + if 'habituation' in prot: continue # eid = t['session']['id'] df, _ = get_df(eid) @@ -116,13 +144,18 @@ for i, (prot, eid) in enumerate(zip(protocols, eids)): if df is None: continue + print(prot) + counti += 1 - rt_data = np.zeros((len(df), 3)) - rt_data[:, 0] = df['signed_contrast'] - rt_data[:, 1] = df['rt'] - rt_data[:, 2] = df['response'] - pickle.dump(rt_data, open("./session_data/{} rt info {}".format(subject, counti), 'wb')) + if counti != 7: + continue + + # rt_data = np.zeros((len(df), 3)) + # rt_data[:, 0] = df['signed_contrast'] + # rt_data[:, 1] = df['rt'] + # rt_data[:, 2] = df['response'] + # pickle.dump(rt_data, open("./session_data/{} rt info {}".format(subject, counti), 'wb')) - progression(df, df['signed_contrast'].unique(), progression_variable='feedback', upper_bound=2, title="{} PMF {} / 15".format(subject, counti)) - progression(df, df['signed_contrast'].unique(), progression_variable='rt', upper_bound=4, title="{} CMF {} / 15".format(subject, counti)) + progression(df, df['signed_contrast'].unique(), progression_variable='feedback', upper_bound=2, title="{} PMF {}".format(subject, counti)) + # progression(df, df['signed_contrast'].unique(), progression_variable='rt', upper_bound=4, title="{} CMF {}".format(subject, counti)) diff --git a/brain_wide_download.py b/brain_wide_download.py new file mode 100644 index 00000000..3e44f83a --- /dev/null +++ b/brain_wide_download.py @@ -0,0 +1,77 @@ +from pathlib import Path + +import seaborn + +from one.api import ONE +from one.remote import aws +from one.alf.files import add_uuid_string +# root_path = Path("/datadisk/FlatIron/aggregates") +# +# files_parquet = list(root_path.rglob('_ibl_subjectTrials.table.pqt')) + +one.load(subject_id, content_type='subject', name='_ibl_subjectTrials.table.pqt') + + +if len(files_parquet) == 0: + one = ONE() + s3, bucket_name = aws.get_s3_from_alyx(alyx=one.alyx) + datasets = one.alyx.rest('datasets', 'list', name='_ibl_subjectTrials.table.pqt') + for dset in datasets: + rel_path = dset['file_records'][0]['relative_path'] + aws_path = add_uuid_string('aggregates/' + rel_path, dset['url'][-36:]) + aws.s3_download_file(aws_path, root_path.joinpath(rel_path), s3=s3, bucket_name=bucket_name) + + +## %% +import dask.dataframe as dd +import pandas as pd +import numpy as np + +time_bins = np.arange(0, 4000, 20) + + +trials = dd.read_parquet(files_parquet) +# the ITI is the start time of the next trial minus the end time of the current plus .5 secs +trials['iti'] = trials['intervals_0'].shift(-1) - trials['intervals_1'] + .5 +trials = trials[trials['iti'] > 0] # we need to remove the session jumps +# here we select only the ephys protocol trials +trials = trials[trials['task_protocol'].apply(lambda x: 'ephys' in x, meta=('task_protocol', 'bool'))] +# aggregate the iti per time bins +evolution = trials['iti'].groupby(trials['intervals_0'].map_partitions(pd.cut, time_bins)).agg(['mean', 'std']) + + + +import time +# crunch crunch +now = time.time() +itis = trials['iti'].compute() +tev = evolution.compute() +print(time.time() - now) + + + +## %% +import seaborn as sns +import matplotlib.pyplot as plt +sns.set_theme('paper') +sns.set_palette('deep') +fig, axs = plt.subplots(1, 3, figsize=(16, 5)) +axs[0].hist(itis, bins=1000, range=[0.5, 3], linewidth=0, alpha=0.8) +axs[0].set(title='ITI distribution for all trials', xlabel='ITI (s)', ylabel='Count') + +x = time_bins[:-1] + 10 +axs[1].fill_between(x, y1=tev['mean'].values - tev['std'].values, y2=tev['mean'].values + tev['std'].values, alpha=0.4) +axs[1].plot(x, tev['mean'].values, color='orange', linewidth=2) +axs[1].set(title='ITI duration', ylabel='ITI (s)', xlabel='Time elapsed in session (s)', ylim=[0.75, 2], xlim=[0, 3600]) + +trials_ = pd.read_parquet(files_parquet[0]) +trials_['iti'] = trials_['intervals_0'].shift(-1) - trials_['intervals_1'] + .5 +session0 = trials_[trials_['session'] == 'dc1b7422-cc16-4a37-b552-c31dccdddbce'] +axs[2].plot(session0['intervals_0'], session0['iti'], label='dc1b7422', linewidth=0.5) +trials_ = pd.read_parquet(files_parquet[50]) +trials_['iti'] = trials_['intervals_0'].shift(-1) - trials_['intervals_1'] + .5 +session1 = trials_[trials_['session'] == 'd9d83a6a-8fb5-41eb-b4ce-7c6dd1716d72'] +axs[2].plot(session1['intervals_0'], session1['iti'], label='d9d83a6a', linewidth=0.5) +axs[2].set(title='ITI duration', ylabel='ITI (s)', xlabel='Time elapsed in session (s)', ylim=[0.75, 2], xlim=[0, 3600]) +axs[2].legend() +## diff --git a/bwm_mice_stats.py b/bwm_mice_stats.py index 14696ff1..0ea04bba 100644 --- a/bwm_mice_stats.py +++ b/bwm_mice_stats.py @@ -69,6 +69,7 @@ subjects = ['NYU-11', 'NYU-12', 'NYU-21', 'NYU-27', 'NYU-30', 'NYU-37', 'ibl_witten_27', 'ibl_witten_29', 'CSH_ZAD_001', 'CSH_ZAD_011', 'CSH_ZAD_019', 'CSH_ZAD_022', 'CSH_ZAD_024', 'CSH_ZAD_025', 'CSH_ZAD_026', 'CSH_ZAD_029'] +quit() # why does CSHL058 not work? old_style = False diff --git a/canonical_infos.json b/canonical_infos.json index c0868bc5..12a3fa3a 100644 --- a/canonical_infos.json +++ b/canonical_infos.json @@ -1 +1 @@ -{"SWC_022": {"seeds": ["412", "401", "403", "413", "406", "407", "415", "409", "405", "400", "408", "404", "410", "411", "414", "402"], "fit_nums": ["347", "54", "122", "132", "520", "386", "312", "59", "999", "849", "372", "300", "485", "593", "358", "550"], "chain_num": 19, "ignore": [5, 6, 12, 3, 1, 11, 10]}, "SWC_023": {"seeds": ["302", "312", "304", "300", "315", "311", "308", "305", "303", "309", "306", "313", "307", "314", "301", "310"], "fit_nums": ["994", "913", "681", "816", "972", "790", "142", "230", "696", "537", "975", "773", "918", "677", "742", "745"], "chain_num": 4, "ignore": [12, 1, 15, 14, 8, 6, 4, 10]}, "ibl_witten_15": {"seeds": ["408", "412", "400", "411", "410", "407", "403", "406", "413", "405", "404", "402", "401", "415", "409", "414"], "fit_nums": ["40", "241", "435", "863", "941", "530", "382", "750", "532", "731", "146", "500", "967", "334", "375", "670"], "chain_num": 19, "ignore": [6, 7, 9, 8, 5, 13, 12, 11]}, "ibl_witten_13": {"seeds": ["401", "414", "409", "413", "415", "411", "410", "408", "402", "405", "406", "407", "412", "403", "400", "404"], "fit_nums": ["702", "831", "47", "740", "251", "929", "579", "351", "515", "261", "222", "852", "754", "892", "473", "29"], "chain_num": 19, "ignore": [11, 4, 15, 6, 8, 0]}, "KS016": {"seeds": ["315", "301", "309", "313", "302", "307", "303", "308", "311", "312", "314", "306", "310", "300", "305", "304"], "fit_nums": ["99", "57", "585", "32", "501", "558", "243", "413", "59", "757", "463", "172", "524", "957", "909", "292"], "chain_num": 4, "ignore": [0, 2, 14, 12, 1, 7, 11, 6]}, "ibl_witten_19": {"seeds": ["412", "415", "413", "408", "409", "404", "403", "401", "405", "411", "410", "406", "402", "414", "407", "400"], "fit_nums": ["234", "41", "503", "972", "935", "808", "912", "32", "331", "755", "117", "833", "822", "704", "901", "207"], "chain_num": 19, "ignore": [6, 1, 15, 10, 12]}, "CSH_ZAD_017": {"seeds": ["408", "404", "413", "406", "414", "411", "400", "401", "415", "407", "402", "412", "403", "409", "405", "410"], "fit_nums": ["928", "568", "623", "841", "92", "251", "829", "922", "964", "257", "150", "970", "375", "113", "423", "564"], "chain_num": 19, "ignore": [8, 10, 12, 5, 9, 7, 4]}, "KS022": {"seeds": ["315", "300", "314", "301", "303", "302", "306", "308", "305", "310", "313", "312", "304", "307", "311", "309"], "fit_nums": ["899", "681", "37", "957", "629", "637", "375", "980", "810", "51", "759", "664", "420", "127", "259", "555"], "chain_num": 4, "ignore": [10, 1, 0, 13, 5, 9, 12, 3]}, "CSH_ZAD_025": {"seeds": ["303", "311", "307", "312", "313", "314", "308", "315", "305", "306", "304", "302", "309", "310", "301", "300"], "fit_nums": ["581", "148", "252", "236", "581", "838", "206", "756", "449", "288", "756", "593", "733", "633", "418", "563"], "chain_num": 4, "ignore": [8, 10, 13, 5, 12, 9, 7, 1]}, "ibl_witten_17": {"seeds": ["406", "415", "408", "413", "402", "405", "409", "400", "414", "401", "412", "407", "404", "410", "403", "411"], "fit_nums": ["827", "797", "496", "6", "444", "823", "384", "873", "634", "27", "811", "142", "207", "322", "756", "275"], "chain_num": 9, "ignore": [9, 0, 1, 7, 11, 3, 10, 8]}, "SWC_021": {"seeds": ["404", "413", "406", "412", "403", "401", "410", "409", "400", "414", "415", "402", "405", "408", "411", "407"], "fit_nums": ["840", "978", "224", "38", "335", "500", "83", "509", "441", "9", "135", "890", "358", "460", "844", "30"], "chain_num": 19, "ignore": [2, 13, 1, 9, 0, 4, 6, 5]}, "ibl_witten_18": {"seeds": ["311", "310", "303", "314", "302", "309", "305", "307", "312", "300", "308", "306", "315", "313", "304", "301"], "fit_nums": ["236", "26", "838", "762", "826", "409", "496", "944", "280", "704", "930", "419", "637", "896", "876", "297"], "chain_num": 4, "ignore": [11, 0, 4, 2, 12, 13, 8, 3]}, "CSHL_018": {"seeds": ["302", "310", "306", "300", "314", "307", "309", "313", "311", "308", "304", "301", "312", "303", "305", "315"], "fit_nums": ["843", "817", "920", "900", "226", "36", "472", "676", "933", "453", "116", "263", "269", "897", "568", "438"], "chain_num": 4, "ignore": [15, 4, 8, 0, 5, 10, 12, 11]}, "GLM_Sim_06": {"seeds": ["313", "309", "302", "303", "305", "314", "300", "315", "311", "306", "304", "310", "301", "312", "308", "307"], "fit_nums": ["9", "786", "286", "280", "72", "587", "619", "708", "360", "619", "311", "189", "60", "708", "939", "733"], "chain_num": 2, "ignore": [15, 9, 8, 14, 1, 12, 10, 3]}, "ZM_1897": {"seeds": ["304", "308", "305", "311", "315", "314", "307", "306", "300", "303", "313", "310", "301", "312", "302", "309"], "fit_nums": ["549", "96", "368", "509", "424", "897", "287", "426", "968", "93", "725", "513", "837", "581", "989", "374"], "chain_num": 4, "ignore": [0, 14, 5, 8, 7, 11, 13, 10]}, "CSHL_020": {"seeds": ["305", "309", "313", "302", "314", "310", "300", "307", "315", "306", "312", "304", "311", "301", "303", "308"], "fit_nums": ["222", "306", "243", "229", "584", "471", "894", "238", "986", "660", "494", "657", "896", "459", "100", "283"], "chain_num": 4, "ignore": [6, 5, 9, 15, 0, 8, 4, 13]}, "CSHL054": {"seeds": ["401", "415", "409", "410", "414", "413", "407", "405", "406", "408", "411", "400", "412", "402", "403", "404"], "fit_nums": ["901", "734", "609", "459", "574", "793", "978", "66", "954", "906", "954", "111", "292", "850", "266", "967"], "chain_num": 9, "ignore": [5, 12, 7, 10, 11, 2, 6, 4]}, "CSHL_014": {"seeds": ["305", "311", "309", "300", "313", "310", "307", "306", "304", "312", "308", "302", "314", "303", "301", "315"], "fit_nums": ["371", "550", "166", "24", "705", "385", "870", "884", "831", "546", "404", "722", "287", "564", "613", "783"], "chain_num": 4, "ignore": [15, 0, 3, 4, 7, 6, 1, 11]}, "CSHL062": {"seeds": ["307", "313", "310", "303", "306", "312", "308", "305", "311", "314", "304", "302", "300", "301", "315", "309"], "fit_nums": ["846", "371", "94", "888", "499", "229", "546", "432", "71", "989", "986", "91", "935", "314", "975", "481"], "chain_num": 4, "ignore": [14, 6, 3, 11, 15, 13, 4, 12]}, "CSH_ZAD_001": {"seeds": ["313", "309", "311", "312", "305", "310", "315", "300", "314", "304", "301", "302", "308", "303", "306", "307"], "fit_nums": ["468", "343", "314", "544", "38", "120", "916", "170", "305", "569", "502", "496", "452", "336", "559", "572"], "chain_num": 4, "ignore": [12, 8, 5, 1, 9, 3, 13, 15]}, "KS003": {"seeds": ["405", "401", "414", "415", "410", "404", "409", "413", "412", "408", "411", "407", "402", "406", "403", "400"], "fit_nums": ["858", "464", "710", "285", "665", "857", "990", "438", "233", "177", "43", "509", "780", "254", "523", "695"], "chain_num": 19, "ignore": [1, 8, 9, 2, 4, 15, 0, 7]}, "NYU-06": {"seeds": ["314", "309", "306", "305", "312", "303", "307", "304", "300", "302", "310", "301", "315", "308", "313", "311"], "fit_nums": ["950", "862", "782", "718", "427", "645", "827", "612", "821", "834", "595", "929", "679", "668", "648", "869"], "chain_num": 4, "ignore": [8, 2, 7, 12, 3, 4, 13, 11]}, "KS019": {"seeds": ["404", "401", "411", "408", "400", "403", "410", "413", "402", "407", "415", "409", "406", "414", "412", "405"], "fit_nums": ["682", "4", "264", "200", "250", "267", "737", "703", "132", "855", "922", "686", "85", "176", "54", "366"], "chain_num": 9, "ignore": [12, 14, 1, 2, 4, 7, 10, 15]}, "CSHL049": {"seeds": ["411", "402", "414", "408", "409", "410", "413", "407", "406", "401", "404", "405", "403", "415", "400", "412"], "fit_nums": ["104", "553", "360", "824", "749", "519", "347", "228", "863", "671", "140", "883", "701", "445", "627", "898"], "chain_num": 9, "ignore": [10, 11, 6, 7, 12, 13, 1, 8]}, "ibl_witten_14": {"seeds": ["310", "311", "304", "306", "300", "302", "314", "313", "303", "308", "301", "309", "305", "315", "312", "307"], "fit_nums": ["563", "120", "85", "712", "277", "871", "183", "661", "505", "598", "210", "89", "310", "638", "564", "998"], "chain_num": 4, "ignore": [11, 14, 6, 13, 5, 12, 15, 8]}, "KS014": {"seeds": ["301", "310", "302", "312", "313", "308", "307", "303", "305", "300", "314", "306", "311", "309", "304", "315"], "fit_nums": ["668", "32", "801", "193", "269", "296", "74", "24", "270", "916", "21", "250", "342", "451", "517", "293"], "chain_num": 4, "ignore": [9, 11, 0, 1, 14, 2, 12, 13]}, "CSHL059": {"seeds": ["306", "309", "300", "304", "314", "303", "315", "311", "313", "305", "301", "307", "302", "312", "310", "308"], "fit_nums": ["821", "963", "481", "999", "986", "45", "551", "605", "701", "201", "629", "261", "972", "407", "165", "9"], "chain_num": 4, "ignore": [9, 3, 5, 15, 6, 10, 2, 1]}, "GLM_Sim_13": {"seeds": ["310", "303", "308", "306", "300", "312", "301", "313", "305", "311", "315", "304", "314", "309", "307", "302"], "fit_nums": ["982", "103", "742", "524", "614", "370", "926", "456", "133", "143", "302", "80", "395", "549", "579", "944"], "chain_num": 2, "ignore": [12, 4, 11, 6, 7, 14, 0, 1]}, "CSHL_007": {"seeds": ["314", "303", "308", "313", "301", "300", "302", "305", "315", "306", "310", "309", "311", "304", "307", "312"], "fit_nums": ["462", "703", "345", "286", "480", "313", "986", "165", "201", "102", "322", "894", "960", "438", "330", "169"], "chain_num": 4, "ignore": [3, 12, 4, 5, 2, 0, 13, 1]}, "CSH_ZAD_011": {"seeds": ["314", "311", "303", "300", "305", "310", "306", "301", "302", "315", "304", "309", "308", "312", "313", "307"], "fit_nums": ["320", "385", "984", "897", "315", "120", "320", "945", "475", "403", "210", "412", "695", "564", "664", "411"], "chain_num": 4, "ignore": [0, 2, 14, 11, 7, 10, 13, 9]}, "KS021": {"seeds": ["309", "312", "304", "310", "303", "311", "314", "302", "305", "301", "306", "300", "308", "315", "313", "307"], "fit_nums": ["874", "943", "925", "587", "55", "136", "549", "528", "349", "211", "401", "84", "225", "545", "153", "382"], "chain_num": 4, "ignore": [11, 12, 0, 8, 2, 14, 5, 1]}, "GLM_Sim_15": {"seeds": ["303", "312", "305", "308", "309", "302", "301", "310", "313", "315", "311", "314", "307", "306", "304", "300"], "fit_nums": ["769", "930", "328", "847", "899", "714", "144", "518", "521", "873", "914", "359", "242", "343", "45", "364"], "chain_num": 2, "ignore": [8, 1, 0, 3, 2, 5, 10, 4]}, "CSHL_015": {"seeds": ["301", "302", "307", "310", "309", "311", "304", "312", "300", "308", "313", "305", "314", "315", "306", "303"], "fit_nums": ["717", "705", "357", "539", "604", "971", "669", "76", "45", "413", "510", "122", "190", "821", "368", "472"], "chain_num": 4, "ignore": [7, 6, 10, 2, 15, 13, 1, 3]}, "ibl_witten_16": {"seeds": ["304", "313", "309", "314", "312", "307", "305", "301", "306", "310", "300", "315", "308", "311", "303", "302"], "fit_nums": ["392", "515", "696", "270", "7", "583", "880", "674", "23", "576", "579", "695", "149", "854", "184", "875"], "chain_num": 4, "ignore": [3, 12, 2, 6, 10, 14, 4, 1]}, "KS015": {"seeds": ["315", "305", "309", "303", "314", "310", "311", "312", "313", "300", "307", "308", "304", "301", "302", "306"], "fit_nums": ["257", "396", "387", "435", "133", "164", "403", "8", "891", "650", "111", "557", "473", "229", "842", "196"], "chain_num": 4, "ignore": [7, 8, 0, 10, 2, 3, 12, 9]}, "GLM_Sim_12": {"seeds": ["304", "312", "306", "303", "310", "302", "300", "305", "308", "313", "307", "311", "315", "301", "314", "309"], "fit_nums": ["971", "550", "255", "195", "952", "486", "841", "535", "559", "37", "654", "213", "864", "506", "732", "550"], "chain_num": 2, "ignore": [0, 7, 15, 14, 3, 10, 11, 13]}, "GLM_Sim_11": {"seeds": ["300", "312", "310", "315", "302", "313", "314", "311", "308", "303", "309", "307", "306", "304", "301", "305"], "fit_nums": ["477", "411", "34", "893", "195", "293", "603", "5", "887", "281", "956", "73", "346", "640", "532", "688"], "chain_num": 2}, "GLM_Sim_10": {"seeds": ["301", "300", "306", "305", "307", "309", "312", "314", "311", "315", "304", "313", "303", "308", "302", "310"], "fit_nums": ["391", "97", "897", "631", "239", "652", "19", "448", "807", "35", "972", "469", "280", "562", "42", "706"], "chain_num": 2, "ignore": [1, 9, 15, 3, 13, 12, 7, 11]}, "CSH_ZAD_026": {"seeds": ["312", "313", "308", "310", "303", "307", "302", "305", "300", "315", "306", "301", "311", "304", "314", "309"], "fit_nums": ["699", "87", "537", "628", "797", "511", "459", "770", "969", "240", "504", "948", "295", "506", "25", "378"], "chain_num": 4, "ignore": [12, 13, 4, 11, 8, 3, 15, 0]}, "KS023": {"seeds": ["304", "313", "306", "309", "300", "314", "302", "310", "303", "315", "307", "308", "301", "311", "305", "312"], "fit_nums": ["698", "845", "319", "734", "908", "507", "45", "499", "175", "108", "419", "443", "116", "779", "159", "231"], "chain_num": 4, "ignore": [8, 10, 1, 13, 4, 15, 14, 7]}, "GLM_Sim_05": {"seeds": ["301", "315", "300", "302", "305", "304", "313", "314", "311", "309", "306", "307", "308", "310", "303", "312"], "fit_nums": ["425", "231", "701", "375", "343", "902", "623", "125", "921", "637", "393", "964", "678", "930", "796", "42"], "chain_num": 2, "ignore": [11, 2, 5, 1, 4, 9, 15, 12]}, "CSHL061": {"seeds": ["305", "315", "304", "303", "309", "310", "302", "300", "314", "306", "311", "313", "301", "308", "307", "312"], "fit_nums": ["396", "397", "594", "911", "308", "453", "686", "552", "103", "209", "128", "892", "345", "925", "777", "396"], "chain_num": 4, "ignore": [11, 13, 7, 15, 14, 3, 0, 4]}, "CSHL051": {"seeds": ["303", "310", "306", "302", "309", "305", "313", "308", "300", "314", "311", "307", "312", "304", "315", "301"], "fit_nums": ["69", "186", "49", "435", "103", "910", "705", "367", "303", "474", "596", "334", "929", "796", "616", "790"], "chain_num": 4, "ignore": [15, 12, 8, 13, 0, 2, 4, 5]}, "GLM_Sim_14": {"seeds": ["310", "311", "309", "313", "314", "300", "302", "304", "305", "306", "307", "312", "303", "301", "315", "308"], "fit_nums": ["616", "872", "419", "106", "940", "986", "599", "704", "218", "808", "244", "825", "448", "397", "552", "316"], "chain_num": 2, "ignore": [7, 11, 2, 15, 0, 13, 5, 10]}, "GLM_Sim_11_trick": {"seeds": ["411", "400", "408", "409", "415", "413", "410", "412", "406", "414", "403", "404", "401", "405", "407", "402"], "fit_nums": ["95", "508", "886", "384", "822", "969", "525", "382", "489", "436", "344", "537", "251", "223", "458", "401"], "chain_num": 2}, "GLM_Sim_16": {"seeds": ["302", "311", "303", "307", "313", "308", "309", "300", "305", "315", "304", "310", "312", "301", "314", "306"], "fit_nums": ["914", "377", "173", "583", "870", "456", "611", "697", "13", "713", "159", "248", "617", "37", "770", "780"], "chain_num": 2, "ignore": [4, 10, 5, 0, 13, 8, 6, 7]}, "ZM_3003": {"seeds": ["300", "304", "307", "312", "305", "310", "311", "314", "303", "308", "313", "301", "315", "309", "306", "302"], "fit_nums": ["603", "620", "657", "735", "357", "390", "119", "33", "62", "617", "209", "810", "688", "21", "744", "426"], "chain_num": 4, "ignore": [14, 7, 12, 1, 3, 4, 11, 8]}, "CSH_ZAD_022": {"seeds": ["305", "310", "311", "315", "303", "312", "314", "313", "307", "302", "300", "304", "301", "308", "306", "309"], "fit_nums": ["143", "946", "596", "203", "576", "403", "900", "65", "478", "325", "282", "513", "460", "42", "161", "970"], "chain_num": 4, "ignore": [9, 12, 4, 8, 3, 7, 0, 1]}, "GLM_Sim_07": {"seeds": ["300", "309", "302", "304", "305", "312", "301", "311", "315", "314", "308", "307", "303", "310", "306", "313"], "fit_nums": ["724", "701", "118", "230", "648", "426", "689", "114", "832", "731", "592", "519", "559", "938", "672", "144"], "chain_num": 1}, "KS017": {"seeds": ["311", "310", "306", "309", "303", "302", "308", "300", "313", "301", "314", "307", "315", "304", "312", "305"], "fit_nums": ["97", "281", "808", "443", "352", "890", "703", "468", "780", "708", "674", "27", "345", "23", "939", "457"], "chain_num": 4, "ignore": [0, 13, 8, 1, 12, 5, 10, 9]}, "GLM_Sim_11_sub": {"seeds": ["410", "414", "413", "404", "409", "415", "406", "408", "402", "411", "400", "405", "403", "407", "412", "401"], "fit_nums": ["830", "577", "701", "468", "929", "374", "954", "749", "937", "488", "873", "416", "612", "792", "461", "488"], "chain_num": 2}} \ No newline at end of file +{"SWC_022": {"seeds": ["412", "401", "403", "413", "406", "407", "415", "409", "405", "400", "408", "404", "410", "411", "414", "402"], "fit_nums": ["347", "54", "122", "132", "520", "386", "312", "59", "999", "849", "372", "300", "485", "593", "358", "550"], "chain_num": 19}, "SWC_023": {"seeds": ["302", "312", "304", "300", "315", "311", "308", "305", "303", "309", "306", "313", "307", "314", "301", "310"], "fit_nums": ["994", "913", "681", "816", "972", "790", "142", "230", "696", "537", "975", "773", "918", "677", "742", "745"], "chain_num": 4}, "ZFM-05236": {"seeds": ["404", "409", "401", "412", "406", "411", "410", "402", "408", "405", "415", "403", "414", "400", "413", "407"], "fit_nums": ["106", "111", "333", "253", "395", "76", "186", "192", "221", "957", "989", "612", "632", "304", "50", "493"], "chain_num": 14, "ignore": [3, 0, 8, 2, 6, 15, 14, 10]}, "ibl_witten_15": {"seeds": ["408", "412", "400", "411", "410", "407", "403", "406", "413", "405", "404", "402", "401", "415", "409", "414"], "fit_nums": ["40", "241", "435", "863", "941", "530", "382", "750", "532", "731", "146", "500", "967", "334", "375", "670"], "chain_num": 19}, "ibl_witten_13": {"seeds": ["401", "414", "409", "413", "415", "411", "410", "408", "402", "405", "406", "407", "412", "403", "400", "404"], "fit_nums": ["702", "831", "47", "740", "251", "929", "579", "351", "515", "261", "222", "852", "754", "892", "473", "29"], "chain_num": 19}, "KS016": {"seeds": ["315", "301", "309", "313", "302", "307", "303", "308", "311", "312", "314", "306", "310", "300", "305", "304"], "fit_nums": ["99", "57", "585", "32", "501", "558", "243", "413", "59", "757", "463", "172", "524", "957", "909", "292"], "chain_num": 4}, "ibl_witten_19": {"seeds": ["412", "415", "413", "408", "409", "404", "403", "401", "405", "411", "410", "406", "402", "414", "407", "400"], "fit_nums": ["234", "41", "503", "972", "935", "808", "912", "32", "331", "755", "117", "833", "822", "704", "901", "207"], "chain_num": 19}, "CSH_ZAD_017": {"seeds": ["408", "404", "413", "406", "414", "411", "400", "401", "415", "407", "402", "412", "403", "409", "405", "410"], "fit_nums": ["928", "568", "623", "841", "92", "251", "829", "922", "964", "257", "150", "970", "375", "113", "423", "564"], "chain_num": 19}, "KS022": {"seeds": ["315", "300", "314", "301", "303", "302", "306", "308", "305", "310", "313", "312", "304", "307", "311", "309"], "fit_nums": ["899", "681", "37", "957", "629", "637", "375", "980", "810", "51", "759", "664", "420", "127", "259", "555"], "chain_num": 4}, "CSH_ZAD_025": {"seeds": ["303", "311", "307", "312", "313", "314", "308", "315", "305", "306", "304", "302", "309", "310", "301", "300"], "fit_nums": ["581", "148", "252", "236", "581", "838", "206", "756", "449", "288", "756", "593", "733", "633", "418", "563"], "chain_num": 4}, "ibl_witten_17": {"seeds": ["406", "415", "408", "413", "402", "405", "409", "400", "414", "401", "412", "407", "404", "410", "403", "411"], "fit_nums": ["827", "797", "496", "6", "444", "823", "384", "873", "634", "27", "811", "142", "207", "322", "756", "275"], "chain_num": 9}, "SWC_021": {"seeds": ["404", "413", "406", "412", "403", "401", "410", "409", "400", "414", "415", "402", "405", "408", "411", "407"], "fit_nums": ["840", "978", "224", "38", "335", "500", "83", "509", "441", "9", "135", "890", "358", "460", "844", "30"], "chain_num": 19}, "ibl_witten_18": {"seeds": ["311", "310", "303", "314", "302", "309", "305", "307", "312", "300", "308", "306", "315", "313", "304", "301"], "fit_nums": ["236", "26", "838", "762", "826", "409", "496", "944", "280", "704", "930", "419", "637", "896", "876", "297"], "chain_num": 4}, "CSHL_018": {"seeds": ["302", "310", "306", "300", "314", "307", "309", "313", "311", "308", "304", "301", "312", "303", "305", "315"], "fit_nums": ["843", "817", "920", "900", "226", "36", "472", "676", "933", "453", "116", "263", "269", "897", "568", "438"], "chain_num": 4}, "ZFM-05245": {"seeds": ["400", "413", "414", "409", "411", "403", "405", "412", "406", "410", "407", "415", "401", "404", "402", "408"], "fit_nums": ["512", "765", "704", "17", "539", "449", "584", "987", "138", "932", "869", "313", "253", "540", "37", "634"], "chain_num": 11}, "GLM_Sim_06": {"seeds": ["313", "309", "302", "303", "305", "314", "300", "315", "311", "306", "304", "310", "301", "312", "308", "307"], "fit_nums": ["9", "786", "286", "280", "72", "587", "619", "708", "360", "619", "311", "189", "60", "708", "939", "733"], "chain_num": 2}, "ZM_1897": {"seeds": ["304", "308", "305", "311", "315", "314", "307", "306", "300", "303", "313", "310", "301", "312", "302", "309"], "fit_nums": ["549", "96", "368", "509", "424", "897", "287", "426", "968", "93", "725", "513", "837", "581", "989", "374"], "chain_num": 4}, "CSHL_020": {"seeds": ["305", "309", "313", "302", "314", "310", "300", "307", "315", "306", "312", "304", "311", "301", "303", "308"], "fit_nums": ["222", "306", "243", "229", "584", "471", "894", "238", "986", "660", "494", "657", "896", "459", "100", "283"], "chain_num": 4}, "CSHL054": {"seeds": ["401", "415", "409", "410", "414", "413", "407", "405", "406", "408", "411", "400", "412", "402", "403", "404"], "fit_nums": ["901", "734", "609", "459", "574", "793", "978", "66", "954", "906", "954", "111", "292", "850", "266", "967"], "chain_num": 9}, "CSHL_014": {"seeds": ["305", "311", "309", "300", "313", "310", "307", "306", "304", "312", "308", "302", "314", "303", "301", "315"], "fit_nums": ["371", "550", "166", "24", "705", "385", "870", "884", "831", "546", "404", "722", "287", "564", "613", "783"], "chain_num": 4}, "ZFM-04019": {"seeds": ["413", "404", "408", "403", "415", "406", "414", "410", "402", "405", "411", "400", "401", "412", "409", "407"], "fit_nums": ["493", "302", "590", "232", "121", "938", "270", "999", "95", "175", "576", "795", "728", "244", "32", "177"], "chain_num": 14, "ignore": [11, 12, 6, 3, 5, 2, 15, 1]}, "CSHL062": {"seeds": ["307", "313", "310", "303", "306", "312", "308", "305", "311", "314", "304", "302", "300", "301", "315", "309"], "fit_nums": ["846", "371", "94", "888", "499", "229", "546", "432", "71", "989", "986", "91", "935", "314", "975", "481"], "chain_num": 4}, "CSH_ZAD_001": {"seeds": ["313", "309", "311", "312", "305", "310", "315", "300", "314", "304", "301", "302", "308", "303", "306", "307"], "fit_nums": ["468", "343", "314", "544", "38", "120", "916", "170", "305", "569", "502", "496", "452", "336", "559", "572"], "chain_num": 4}, "KS003": {"seeds": ["405", "401", "414", "415", "410", "404", "409", "413", "412", "408", "411", "407", "402", "406", "403", "400"], "fit_nums": ["858", "464", "710", "285", "665", "857", "990", "438", "233", "177", "43", "509", "780", "254", "523", "695"], "chain_num": 19}, "NYU-06": {"seeds": ["314", "309", "306", "305", "312", "303", "307", "304", "300", "302", "310", "301", "315", "308", "313", "311"], "fit_nums": ["950", "862", "782", "718", "427", "645", "827", "612", "821", "834", "595", "929", "679", "668", "648", "869"], "chain_num": 4}, "KS019": {"seeds": ["404", "401", "411", "408", "400", "403", "410", "413", "402", "407", "415", "409", "406", "414", "412", "405"], "fit_nums": ["682", "4", "264", "200", "250", "267", "737", "703", "132", "855", "922", "686", "85", "176", "54", "366"], "chain_num": 9}, "CSHL049": {"seeds": ["411", "402", "414", "408", "409", "410", "413", "407", "406", "401", "404", "405", "403", "415", "400", "412"], "fit_nums": ["104", "553", "360", "824", "749", "519", "347", "228", "863", "671", "140", "883", "701", "445", "627", "898"], "chain_num": 9}, "ibl_witten_14": {"seeds": ["310", "311", "304", "306", "300", "302", "314", "313", "303", "308", "301", "309", "305", "315", "312", "307"], "fit_nums": ["563", "120", "85", "712", "277", "871", "183", "661", "505", "598", "210", "89", "310", "638", "564", "998"], "chain_num": 4}, "KS014": {"seeds": ["301", "310", "302", "312", "313", "308", "307", "303", "305", "300", "314", "306", "311", "309", "304", "315"], "fit_nums": ["668", "32", "801", "193", "269", "296", "74", "24", "270", "916", "21", "250", "342", "451", "517", "293"], "chain_num": 4}, "CSHL059": {"seeds": ["306", "309", "300", "304", "314", "303", "315", "311", "313", "305", "301", "307", "302", "312", "310", "308"], "fit_nums": ["821", "963", "481", "999", "986", "45", "551", "605", "701", "201", "629", "261", "972", "407", "165", "9"], "chain_num": 4}, "GLM_Sim_13": {"seeds": ["310", "303", "308", "306", "300", "312", "301", "313", "305", "311", "315", "304", "314", "309", "307", "302"], "fit_nums": ["982", "103", "742", "524", "614", "370", "926", "456", "133", "143", "302", "80", "395", "549", "579", "944"], "chain_num": 2}, "CSHL_007": {"seeds": ["314", "303", "308", "313", "301", "300", "302", "305", "315", "306", "310", "309", "311", "304", "307", "312"], "fit_nums": ["462", "703", "345", "286", "480", "313", "986", "165", "201", "102", "322", "894", "960", "438", "330", "169"], "chain_num": 4}, "CSH_ZAD_011": {"seeds": ["314", "311", "303", "300", "305", "310", "306", "301", "302", "315", "304", "309", "308", "312", "313", "307"], "fit_nums": ["320", "385", "984", "897", "315", "120", "320", "945", "475", "403", "210", "412", "695", "564", "664", "411"], "chain_num": 4}, "KS021": {"seeds": ["309", "312", "304", "310", "303", "311", "314", "302", "305", "301", "306", "300", "308", "315", "313", "307"], "fit_nums": ["874", "943", "925", "587", "55", "136", "549", "528", "349", "211", "401", "84", "225", "545", "153", "382"], "chain_num": 4}, "GLM_Sim_15": {"seeds": ["303", "312", "305", "308", "309", "302", "301", "310", "313", "315", "311", "314", "307", "306", "304", "300"], "fit_nums": ["769", "930", "328", "847", "899", "714", "144", "518", "521", "873", "914", "359", "242", "343", "45", "364"], "chain_num": 2}, "CSHL_015": {"seeds": ["301", "302", "307", "310", "309", "311", "304", "312", "300", "308", "313", "305", "314", "315", "306", "303"], "fit_nums": ["717", "705", "357", "539", "604", "971", "669", "76", "45", "413", "510", "122", "190", "821", "368", "472"], "chain_num": 4}, "ibl_witten_16": {"seeds": ["304", "313", "309", "314", "312", "307", "305", "301", "306", "310", "300", "315", "308", "311", "303", "302"], "fit_nums": ["392", "515", "696", "270", "7", "583", "880", "674", "23", "576", "579", "695", "149", "854", "184", "875"], "chain_num": 4}, "KS015": {"seeds": ["315", "305", "309", "303", "314", "310", "311", "312", "313", "300", "307", "308", "304", "301", "302", "306"], "fit_nums": ["257", "396", "387", "435", "133", "164", "403", "8", "891", "650", "111", "557", "473", "229", "842", "196"], "chain_num": 4}, "GLM_Sim_12": {"seeds": ["304", "312", "306", "303", "310", "302", "300", "305", "308", "313", "307", "311", "315", "301", "314", "309"], "fit_nums": ["971", "550", "255", "195", "952", "486", "841", "535", "559", "37", "654", "213", "864", "506", "732", "550"], "chain_num": 2}, "GLM_Sim_11": {"seeds": ["300", "312", "310", "315", "302", "313", "314", "311", "308", "303", "309", "307", "306", "304", "301", "305"], "fit_nums": ["477", "411", "34", "893", "195", "293", "603", "5", "887", "281", "956", "73", "346", "640", "532", "688"], "chain_num": 2}, "GLM_Sim_10": {"seeds": ["301", "300", "306", "305", "307", "309", "312", "314", "311", "315", "304", "313", "303", "308", "302", "310"], "fit_nums": ["391", "97", "897", "631", "239", "652", "19", "448", "807", "35", "972", "469", "280", "562", "42", "706"], "chain_num": 2}, "CSH_ZAD_026": {"seeds": ["312", "313", "308", "310", "303", "307", "302", "305", "300", "315", "306", "301", "311", "304", "314", "309"], "fit_nums": ["699", "87", "537", "628", "797", "511", "459", "770", "969", "240", "504", "948", "295", "506", "25", "378"], "chain_num": 4}, "KS023": {"seeds": ["304", "313", "306", "309", "300", "314", "302", "310", "303", "315", "307", "308", "301", "311", "305", "312"], "fit_nums": ["698", "845", "319", "734", "908", "507", "45", "499", "175", "108", "419", "443", "116", "779", "159", "231"], "chain_num": 4}, "GLM_Sim_05": {"seeds": ["301", "315", "300", "302", "305", "304", "313", "314", "311", "309", "306", "307", "308", "310", "303", "312"], "fit_nums": ["425", "231", "701", "375", "343", "902", "623", "125", "921", "637", "393", "964", "678", "930", "796", "42"], "chain_num": 2}, "CSHL061": {"seeds": ["305", "315", "304", "303", "309", "310", "302", "300", "314", "306", "311", "313", "301", "308", "307", "312"], "fit_nums": ["396", "397", "594", "911", "308", "453", "686", "552", "103", "209", "128", "892", "345", "925", "777", "396"], "chain_num": 4}, "CSHL051": {"seeds": ["303", "310", "306", "302", "309", "305", "313", "308", "300", "314", "311", "307", "312", "304", "315", "301"], "fit_nums": ["69", "186", "49", "435", "103", "910", "705", "367", "303", "474", "596", "334", "929", "796", "616", "790"], "chain_num": 4}, "GLM_Sim_14": {"seeds": ["310", "311", "309", "313", "314", "300", "302", "304", "305", "306", "307", "312", "303", "301", "315", "308"], "fit_nums": ["616", "872", "419", "106", "940", "986", "599", "704", "218", "808", "244", "825", "448", "397", "552", "316"], "chain_num": 2}, "GLM_Sim_11_trick": {"seeds": ["411", "400", "408", "409", "415", "413", "410", "412", "406", "414", "403", "404", "401", "405", "407", "402"], "fit_nums": ["95", "508", "886", "384", "822", "969", "525", "382", "489", "436", "344", "537", "251", "223", "458", "401"], "chain_num": 2}, "GLM_Sim_16": {"seeds": ["302", "311", "303", "307", "313", "308", "309", "300", "305", "315", "304", "310", "312", "301", "314", "306"], "fit_nums": ["914", "377", "173", "583", "870", "456", "611", "697", "13", "713", "159", "248", "617", "37", "770", "780"], "chain_num": 2}, "ZM_3003": {"seeds": ["300", "304", "307", "312", "305", "310", "311", "314", "303", "308", "313", "301", "315", "309", "306", "302"], "fit_nums": ["603", "620", "657", "735", "357", "390", "119", "33", "62", "617", "209", "810", "688", "21", "744", "426"], "chain_num": 4}, "CSH_ZAD_022": {"seeds": ["305", "310", "311", "315", "303", "312", "314", "313", "307", "302", "300", "304", "301", "308", "306", "309"], "fit_nums": ["143", "946", "596", "203", "576", "403", "900", "65", "478", "325", "282", "513", "460", "42", "161", "970"], "chain_num": 4}, "GLM_Sim_07": {"seeds": ["300", "309", "302", "304", "305", "312", "301", "311", "315", "314", "308", "307", "303", "310", "306", "313"], "fit_nums": ["724", "701", "118", "230", "648", "426", "689", "114", "832", "731", "592", "519", "559", "938", "672", "144"], "chain_num": 1}, "KS017": {"seeds": ["311", "310", "306", "309", "303", "302", "308", "300", "313", "301", "314", "307", "315", "304", "312", "305"], "fit_nums": ["97", "281", "808", "443", "352", "890", "703", "468", "780", "708", "674", "27", "345", "23", "939", "457"], "chain_num": 4}, "GLM_Sim_11_sub": {"seeds": ["410", "414", "413", "404", "409", "415", "406", "408", "402", "411", "400", "405", "403", "407", "412", "401"], "fit_nums": ["830", "577", "701", "468", "929", "374", "954", "749", "937", "488", "873", "416", "612", "792", "461", "488"], "chain_num": 2}} \ No newline at end of file diff --git a/dyn_glm_chain_analysis.py b/dyn_glm_chain_analysis.py index c61d4c7c..3e8a74ce 100644 --- a/dyn_glm_chain_analysis.py +++ b/dyn_glm_chain_analysis.py @@ -545,10 +545,10 @@ def contrasts_plot(test, state_sets, subject, save=False, show=False, dpi='figur cnas.append(c_n_a) mask = c_n_a[:, -1] == 0 - plt.plot(np.where(mask)[0], 0.5 + 0.25 * (noise[mask] - c_n_a[mask, 0] + c_n_a[mask, 1]), 'o', c='b', ms=ms, label='Leftward', alpha=0.6) + plt.plot(np.where(mask)[0], 0.5 + 0.25 * (noise[mask] - all_conts[cont_mapping(- c_n_a[mask, 0] + c_n_a[mask, 1])]), 'o', c='b', ms=ms, label='Rightward', alpha=0.6) mask = c_n_a[:, -1] == 1 - plt.plot(np.where(mask)[0], 0.5 + 0.25 * (noise[mask] - c_n_a[mask, 0] + c_n_a[mask, 1]), 'o', c='r', ms=ms, label='Rightward', alpha=0.6) + plt.plot(np.where(mask)[0], 0.5 + 0.25 * (noise[mask] - all_conts[cont_mapping(- c_n_a[mask, 0] + c_n_a[mask, 1])]), 'o', c='r', ms=ms, label='Leftward', alpha=0.6) plt.title("session #{} / {}".format(1+seq_num, test.results[0].n_sessions), size=26) # plt.yticks(*self.cont_ticks, size=22-2) @@ -566,13 +566,15 @@ def contrasts_plot(test, state_sets, subject, save=False, show=False, dpi='figur 1.03, functions=(cont_to_belief, belief_to_cont)) secax_y2.set_ylabel("Contrast", size=26) secax_y2.set_yticks([-1, -0.5, 0., 0.5, 1]) + # secax_y2.set_yticks(np.arange(11) / 5 - 1) + # secax_y2.set_yticklabels([-1, '', '', '', '', 0., '', '', '', '', 1]) secax_y2.spines['right'].set_bounds(-1, 1) secax_y2.tick_params(axis='y', which='major', labelsize=fs) plt.xlabel('Trial', size=28) sns.despine() - plt.xlim(left=250, right=450) - plt.legend(frameon=False, fontsize=22, bbox_to_anchor=(0.8, 0.5)) + # plt.xlim(left=250, right=450) + plt.legend(frameon=False, fontsize=22, ncol=2, loc=(0.7, 0.05)) plt.tight_layout() if save: plt.savefig("dynamic_GLM_figures/all posterior and contrasts {}, sess {}{}.png".format(subject, seq_num, save_append), dpi=dpi)#, bbox_inches='tight') @@ -685,6 +687,7 @@ def create_mode_indices(test, subject, fit_type): try: xy, z = pickle.load(open("multi_chain_saves/xyz_{}_{}.p".format(subject, fit_type), 'rb')) except Exception: + print('Doing PCA') ev, eig, projection_matrix, dimreduc = test.state_pca(subject, pca_type='dists', dim=dim) xy = np.vstack([dimreduc[i] for i in range(dim)]) from scipy.stats import gaussian_kde @@ -1128,7 +1131,6 @@ def state_development(test, state_sets, indices, save=True, save_append='', show counter += 1 else: counter = 0 - if test.results[0].infos[c] + 1 < plot_until: ax0.axvline(test.results[0].infos[c] + 1, color='gray', zorder=0) ax1.axvline(test.results[0].infos[c] + 1, color='gray', zorder=0) ax0.plot(test.results[0].infos[c] + 1 - 0.25, 0.6 + counter * 0.2, 'ko', ms=18) @@ -1281,7 +1283,7 @@ def state_development(test, state_sets, indices, save=True, save_append='', show ax0.axhline(-0.5, c='k') ax0.axhline(0.5, c='k') # print(perf) - ax0.fill_between(range(1, min(1 + test.results[0].n_sessions, plot_until)), perf[:plot_until - 1] - 0.5, -0.5, color='k') + ax0.fill_between(range(1, 1 + test.results[0].n_sessions), perf - 0.5, -0.5, color='k') durs, state_types = state_type_durs(states_by_session, all_pmfs) @@ -1352,7 +1354,7 @@ def state_development(test, state_sets, indices, save=True, save_append='', show plt.tight_layout() if save: - print("saving with {} dpi".format(dpi)) + # print("saving with {} dpi".format(dpi)) plt.savefig("dynamic_GLM_figures/meta_state_development_{}_{}{}.png".format(test.results[0].name, separate_pmf, save_append), dpi=dpi) if show: plt.show() @@ -1361,7 +1363,7 @@ def state_development(test, state_sets, indices, save=True, save_append='', show return states_by_session, all_pmfs, all_pmf_weights, durs, state_types, contrast_intro_types, smart_divide(introductions_by_stage, np.array(durs)), introductions_by_stage, states_per_type -def compare_pmfs(test, state_sets, indices, states2compare, states_by_session, all_pmfs, title=""): +def compare_pmfs(test, states2compare, states_by_session, all_pmfs, title=""): """ Take a set of states, and plot out their PMFs on all sessions on which they occur. See how different they really are. @@ -1395,6 +1397,31 @@ def compare_pmfs(test, state_sets, indices, states2compare, states_by_session, a plt.show() +def compare_params(test, session, state_sets, indices, states2compare, title=""): + """ + Take a set of states, and plot a histogram of their regression parameters for a specific session. + See how different they really are. + + Unfinished + + Takes states_by_session and all_pmfs as input from state_development + """ + colors = ['blue', 'orange', 'green', 'black', 'red'] + assert len(states2compare) <= len(colors) + # subtract 1 to get internal numbering + states2compare = [s - 1 for s in states2compare] + # transform desired states into the actual numbering, before ordering by bias + states2compare = [key for key in test.state_mapping.keys() if test.state_mapping[key] in states2compare] + + for state, trials in enumerate(state_sets): + if state not in states2compare: + continue + session_js, pmfs, pmf_weights = state_weights(test, trials, indices) + return pmf_weights + plt.tight_layout() + plt.show() + + def compare_weights(test, state_sets, indices, states2compare, states_by_session, title=""): """ Take a set of states, and plot out their weights on all sessions on which they occur. @@ -1495,7 +1522,7 @@ if __name__ == "__main__": elif fit_type == 'prebias': loading_info = json.load(open("canonical_infos.json", 'r')) r_hats = json.load(open("canonical_info_r_hats.json", 'r')) - subjects = ['SWC_021', 'ibl_witten_15', 'ibl_witten_13', 'KS003', 'ibl_witten_19', 'SWC_022', 'CSH_ZAD_017'] # list(loading_info.keys()) + subjects = ['ZFM-04019', 'ZFM-05236'] # list(loading_info.keys()) r_hats = {} @@ -1544,6 +1571,24 @@ def dist_helper(dist_matrix, state_hists, inds): dist_matrix[i, j] = np.sum(np.abs(state_hists[i] - state_hists[j])) return dist_matrix +def type_2_appearance(states, pmfs): + # How does type 2 appear, is it a new state or continuation of a type 1? + state_counter = {} + found_states = 0 + for session_counter in range(states.shape[1]): + for state, pmf in zip(range(states.shape[0]), pmfs): + if states[state, session_counter]: + if state not in state_counter: + state_counter[state] = -1 + state_counter[state] += 1 + if pmf_type(pmf[1][state_counter[state]][pmf[0]]) == 1: + found_states += 1 + new = state_counter[state] == 0 + if found_states > 1: + print("Problem") + return 2 + if found_states == 1: + return new def state_type_durs(states, pmfs): # Takes states and pmfs, first creates an array of when which type is how active, then computes the number of sessions each type lasts. @@ -1557,7 +1602,6 @@ def state_type_durs(states, pmfs): pmf_counter += 1 state_types[pmf_type(pmf[1][pmf_counter][pmf[0]]), i] += s[i] # indexing horror - print(state_types) if np.any(state_types[1] > 0.5): durs = (np.where(state_types[1] > 0.5)[0][0], np.where(state_types[2] > 0.5)[0][0] - np.where(state_types[1] > 0.5)[0][0], @@ -1662,6 +1706,36 @@ def compare_performance(cnas, contrasts=(1, 1), title=""): plt.savefig(title) plt.show() +def write_results(test, state_sets, indices, consistencies=None): + n = test.results[0].n_sessions + trial_counter = 0 + state_dict = {state: {'sessions': [], 'trials': [], 'pmfs': []} for state in range(len(state_sets))} + + for state, trials in enumerate(state_sets): + + session_js, pmfs, pmf_weights = state_pmfs(test, trials, indices) + state_dict[state]['sessions'] = session_js + state_dict[state]['pmfs'] = pmfs + + + for seq_num in range(n): + for state, trials in enumerate(state_sets): + relevant_trials = trials[np.logical_and(trial_counter <= trials, trials < trial_counter + len(test.results[0].models[0].stateseqs[seq_num]))] + active_trials = np.zeros(len(test.results[0].models[0].stateseqs[seq_num])) + + if consistencies is None: + active_trials[relevant_trials - trial_counter] = 1 + else: + active_trials[relevant_trials - trial_counter] = np.sum(consistencies[tuple(np.meshgrid(relevant_trials, trials))], axis=0) + active_trials[relevant_trials - trial_counter] -= 1 + active_trials[relevant_trials - trial_counter] = active_trials[relevant_trials - trial_counter] / (trials.shape[0] - 1) + + if np.sum(active_trials) > 0: + state_dict[state]['trials'].append(active_trials) + + trial_counter += len(test.results[0].models[0].stateseqs[seq_num]) + return state_dict + if __name__ == "__main__": @@ -1675,7 +1749,7 @@ if __name__ == "__main__": no_good_pcas = ['NYU-06', 'SWC_023'] subjects = list(loading_info.keys()) # subjects = ['SWC_021', 'ibl_witten_15', 'ibl_witten_13', 'KS003', 'ibl_witten_19', 'SWC_022', 'CSH_ZAD_017'] - # subjects = ['KS014'] + subjects = ['KS021'] print(subjects) fit_variance = [0.03, 0.002, 0.0005, 'uniform', 0, 0.008][0] @@ -1717,11 +1791,13 @@ if __name__ == "__main__": all_bias_flips = [] all_pmf_weights = [] - temp_counter = 0 - + new_counter, transform_counter = 0, 0 state_types_interpolation = np.zeros((3, 150)) all_state_types = [] + state_nums_5 = [] + state_nums_10 = [] + for subject in subjects: if subject.startswith('GLM_Sim_') or subject == 'ibl_witten_18': @@ -1748,22 +1824,64 @@ if __name__ == "__main__": # lapse_sides(test, [s for s in state_sets if len(s) > 40], mode_indices) # training overview - # states, pmfs, durs, _, contrast_intro_type, intros_by_type, undiv_intros, states_per_type = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 1', show=1, separate_pmf=1, type_coloring=True, dont_plot=list(range(7)), plot_until=2) - # states, pmfs, durs, _, contrast_intro_type, intros_by_type, undiv_intros, states_per_type = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 2', show=1, separate_pmf=1, type_coloring=True, dont_plot=list(range(6)), plot_until=7) - # states, pmfs, durs, _, contrast_intro_type, intros_by_type, undiv_intros, states_per_type = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 3', show=1, separate_pmf=1, type_coloring=True, dont_plot=list(range(4)), plot_until=13) + # _ = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 0', show=1, separate_pmf=1, type_coloring=False, dont_plot=list(range(8)), plot_until=-1) + # _ = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 1', show=1, separate_pmf=1, type_coloring=False, dont_plot=list(range(7)), plot_until=2) + # _ = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 2', show=1, separate_pmf=1, type_coloring=False, dont_plot=list(range(6)), plot_until=7) + # _ = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, save_append='step 3', show=1, separate_pmf=1, type_coloring=False, dont_plot=list(range(4)), plot_until=13) states, pmfs, pmf_weights, durs, state_types, contrast_intro_type, intros_by_type, undiv_intros, states_per_type = state_development(test, [s for s in state_sets if len(s) > 40], mode_indices, show=0, separate_pmf=1, type_coloring=True) - all_pmf_weights += pmf_weights - continue + # state_nums_5.append((states > 0.05).sum(0)) + # state_nums_10.append((states > 0.1).sum(0)) + # continue + a = compare_params(test, 26, [s for s in state_sets if len(s) > 40], mode_indices, [3, 5]) + compare_pmfs(test, [3, 5], states, pmfs, title="{} convergence pmf".format(subject)) + quit() + new = type_2_appearance(states, pmfs) + + if new == 2: + print('____________________________') + print(subject) + print('____________________________') + if new == 1: + new_counter += 1 + if new == 0: + transform_counter += 1 + print(new_counter, transform_counter) consistencies = pickle.load(open("multi_chain_saves/consistencies_{}_{}.p".format(subject, fit_type), 'rb')) consistencies /= consistencies[0, 0] - contrasts_plot(test, [s for s in state_sets if len(s) > 40], dpi=300, subject=subject, save=True, show=False, consistencies=consistencies, CMF=False) + temp = contrasts_plot(test, [s for s in state_sets if len(s) > 40], dpi=300, subject=subject, save=True, show=True, consistencies=consistencies, CMF=False) + continue - all_state_types.append(state_types) + state_dict = write_results(test, [s for s in state_sets if len(s) > 40], mode_indices) + pickle.dump(state_dict, open("state_dict_{}".format(subject), 'wb')) + quit() + # abs_state_durs.append(durs) + # continue + # all_pmf_weights += pmf_weights + # all_state_types.append(state_types) + # # state_types_interpolation[0] += np.interp(np.linspace(1, state_types.shape[1], 150), np.arange(1, 1 + state_types.shape[1]), state_types[0]) # state_types_interpolation[1] += np.interp(np.linspace(1, state_types.shape[1], 150), np.arange(1, 1 + state_types.shape[1]), state_types[1]) # state_types_interpolation[2] += np.interp(np.linspace(1, state_types.shape[1], 150), np.arange(1, 1 + state_types.shape[1]), state_types[2]) - # temp_counter += 1 + # + # all_first_pmfs_typeless[subject] = [] + # for pmf in pmfs: + # all_first_pmfs_typeless[subject].append((pmf[0], pmf[1][0])) + # all_pmfs.append(pmf) + # + # first_pmfs, changing_pmfs = get_first_pmfs(states, pmfs) + # for pmf in changing_pmfs: + # if type(pmf[0]) == int: + # continue + # all_changing_pmf_names.append(subject) + # all_changing_pmfs.append(pmf) + # + # all_first_pmfs[subject] = first_pmfs + # continue + # + # consistencies = pickle.load(open("multi_chain_saves/consistencies_{}_{}.p".format(subject, fit_type), 'rb')) + # consistencies /= consistencies[0, 0] + # contrasts_plot(test, [s for s in state_sets if len(s) > 40], dpi=300, subject=subject, save=True, show=False, consistencies=consistencies, CMF=False) # b_flips = bias_flips(states, pmfs, durs) @@ -1776,22 +1894,12 @@ if __name__ == "__main__": # compare_pmfs(test, [s for s in state_sets if len(s) > 40], mode_indices, [4, 5], states, pmfs, title="{} convergence pmf".format(subject)) # compare_weights(test, [s for s in state_sets if len(s) > 40], mode_indices, [4, 5], states, title="{} convergence weights".format(subject)) # quit() - # all_first_pmfs_typeless[subject] = [] - # for pmf in pmfs: - # all_first_pmfs_typeless[subject].append((pmf[0], pmf[1][0])) # all_intros.append(undiv_intros) # all_intros_div.append(intros_by_type) # if states_per_type != []: # all_states_per_type.append(states_per_type) # # intros_by_type_sum += intros_by_type - # first_pmfs, changing_pmfs = get_first_pmfs(states, pmfs) - # for pmf in changing_pmfs: - # if type(pmf[0]) == int: - # continue - # all_changing_pmf_names.append(subject) - # all_changing_pmfs.append(pmf) - # all_first_pmfs[subject] = first_pmfs # for pmf in pmfs: # all_pmfs.append(pmf) # for p in pmf[1]: @@ -1817,7 +1925,6 @@ if __name__ == "__main__": # compare_performance(cnas, (0, 0.848)) # duration of different state types (and also percentage of type activities) - # abs_state_durs.append(durs) # continue # simplex_durs = np.array(durs).reshape(1, 3) # print(simplex_durs / np.sum(simplex_durs)) @@ -1860,6 +1967,7 @@ if __name__ == "__main__": # plt.savefig("temp") # plt.close() + print('Computing sub result') create_mode_indices(test, subject, fit_type) state_set_and_plot(test, 'first_', subject, fit_type) print("second mode?") @@ -1868,8 +1976,8 @@ if __name__ == "__main__": except FileNotFoundError as e: print(e) - continue print('no canoncial result') + continue print(r_hats[subject]) if r_hats[subject] >= 1.05: print("Skipping") @@ -1915,7 +2023,7 @@ if __name__ == "__main__": test.r_hat_and_ess(alpha_func, True) - # pickle.dump(all_first_pmfs, open("pmfs_temp.p", 'wb')) + # pickle.dump(all_first_pmfs, open("all_first_pmfs.p", 'wb')) # pickle.dump(all_changing_pmfs, open("changing_pmfs.p", 'wb')) # pickle.dump(all_changing_pmf_names, open("changing_pmf_names.p", 'wb')) # pickle.dump(all_first_pmfs_typeless, open("all_first_pmfs_typeless.p", 'wb')) @@ -1927,13 +2035,12 @@ if __name__ == "__main__": # pickle.dump(regression_diffs, open("regression_diffs.p", 'wb')) # pickle.dump(all_bias_flips, open("all_bias_flips.p", 'wb')) # pickle.dump(all_state_types, open("all_state_types.p", 'wb')) - pickle.dump(all_pmf_weights, open("all_pmf_weights.p", 'wb')) - quit() - + # pickle.dump(all_pmf_weights, open("all_pmf_weights.p", 'wb')) + # pickle.dump(state_types_interpolation, open("state_types_interpolation.p", 'wb')) + # abs_state_durs = np.array(abs_state_durs) + # pickle.dump(abs_state_durs, open("multi_chain_saves/abs_state_durs.p", 'wb')) if True: - abs_state_durs = np.array(abs_state_durs) - # pickle.dump(abs_state_durs, open("multi_chain_saves/abs_state_durs.p", 'wb')) abs_state_durs = pickle.load(open("multi_chain_saves/abs_state_durs.p", 'rb')) print("Correlations") diff --git a/dynamic_GLMiHMM_fit (copy).py b/dynamic_GLMiHMM_fit (copy).py new file mode 100644 index 00000000..6ccb8afc --- /dev/null +++ b/dynamic_GLMiHMM_fit (copy).py @@ -0,0 +1,407 @@ +"""Start a (series) of iHMM fit(s).""" +import os +os.environ["OMP_NUM_THREADS"] = "1" # export OMP_NUM_THREADS=4 +os.environ["OPENBLAS_NUM_THREADS"] = "1" # export OPENBLAS_NUM_THREADS=4 +os.environ["MKL_NUM_THREADS"] = "1" # export MKL_NUM_THREADS=6 +os.environ["VECLIB_MAXIMUM_THREADS"] = "1" # export VECLIB_MAXIMUM_THREADS=4 +os.environ["NUMEXPR_NUM_THREADS"] = "1" # export NUMEXPR_NUM_THREADS=6 +import pyhsmm +import pyhsmm.basic.distributions as distributions +import copy +import warnings +import pickle +import time +from scipy.special import digamma +import os.path +import numpy as np +from itertools import product +import json +import sys + + +def crp_expec(n, theta): + """ + Return expected number of tables after n customers, given concentration theta. + + From Wikipedia + """ + return theta * (digamma(theta + n) - digamma(theta)) + + +def eleven2nine(x): + """Map from 11 possible contrasts to 9, for the non-training phases. + + 1 and 9 can't appear there, make other elements consider this. + + E.g.: + [2, 0, 4, 8, 10] -> [1, 0, 3, 7, 8] + """ + assert 1 not in x and 9 not in x + x[x > 9] -= 1 + x[x > 1] -= 1 + return x + + +def eval_cross_val(models, data, unmasked_data, n_all_states): + """Eval cross_val.""" + lls = np.zeros(len(models)) + cross_val_n = 0 + for sess_time, (d, full_data) in enumerate(zip(data, unmasked_data)): + held_out = np.isnan(d[:, -1]) + cross_val_n += held_out.sum() + d[:, -1][held_out] = full_data[:, -1][held_out] + for i, m in enumerate(models): + for s in range(n_all_states): + mask = np.logical_and(held_out, m.stateseqs[sess_time] == s) + if mask.sum() > 0: + ll = m.obs_distns[s].log_likelihood(d[mask], sess_time) + lls[i] += np.sum(ll) + lls /= cross_val_n + ll_mean = np.mean(lls[-1000:]) + return lls, ll_mean + + +# following Nick Roys contrasts: following tanh transformation of the contrasts x has a +# free parameter p which we set as p= 5 throughout the paper: xp = tanh (px)/ tanh (p). +contrast_to_num = {-1.: 0, -0.987: 1, -0.848: 2, -0.555: 3, -0.302: 4, 0.: 5, 0.302: 6, 0.555: 7, 0.848: 8, 0.987: 9, 1.: 10} +num_to_contrast = {v: k for k, v in contrast_to_num.items()} +cont_mapping = np.vectorize(num_to_contrast.get) + +data_folder = 'session_data_test' +old_style = False +if old_style: + print("Warning, data can have splits") + print("Sure you want to use old data?") + temp = input() + if temp: + data_folder = 'session_data_old' + else: + quit() + +# available: +# not great: ibl_witten_18 + +# test subjects: +subjects = ['NYU-21', 'NYU-27', 'NYU-30', 'NYU-37', 'NYU-39', 'NYU-40', 'NYU-45', 'NYU-46', 'NYU-47', 'NYU-48', 'CSHL045', 'CSHL047', 'CSHL052', 'CSHL053', 'CSHL055', 'CSHL058', 'CSHL060', 'UCLA005', 'UCLA006', 'UCLA011', 'UCLA012', 'UCLA014', 'UCLA015', 'UCLA017', 'UCLA033', 'UCLA035', 'KS042', 'KS043', 'KS044', 'KS045', 'KS046', 'KS051', 'KS052', 'KS055', 'KS084', 'KS086', 'KS091', 'KS094', 'KS096', 'DY_008', 'DY_009', 'DY_010', 'DY_011', 'DY_013', 'DY_014', 'DY_016', 'DY_018', 'DY_020', 'SWC_042', 'SWC_043', 'SWC_060', 'SWC_061', 'SWC_066', 'ZFM-01576', 'ZFM-01577', 'ZFM-01592', 'ZFM-01935', 'ZFM-01936', 'ZFM-01937', 'ZFM-02368', 'ZFM-02369', 'ZFM-02370', 'ZFM-02372', 'ZFM-02373', 'ZM_1898', 'ZM_2240', 'ZM_2241', 'ZM_2245', 'SWC_038', 'SWC_039', 'SWC_052', 'SWC_053', 'SWC_054', 'SWC_058', 'SWC_065', 'ibl_witten_20', 'ibl_witten_25', 'ibl_witten_26', 'ibl_witten_27', 'ibl_witten_29', 'CSH_ZAD_019', 'CSH_ZAD_024', 'CSH_ZAD_029'] + + +# subjects = [['GLM_Sim_15', 'GLM_Sim_14', 'GLM_Sim_13', 'GLM_Sim_11', 'GLM_Sim_10', 'GLM_Sim_09', 'GLM_Sim_12'][2]] +# (0.03, 0.3, 5, 'contR', 'contL', 'prevA', 'bias', 1, 0.1): + +print(subjects) + +cv_nums = [400 + int(sys.argv[1]) % 16, 400 + (2 * int(sys.argv[1])) % 16] +subjects = [subjects[int(sys.argv[1]) // 16], subjects[(2 * int(sys.argv[1])) // 16]] + +print(cv_nums) +print(subjects) + +for loop_count_i, (s, cv_num) in enumerate(zip(subjects, cv_nums)): + # if loop_count_i > 8: + # if loop_count_i <= 8 or loop_count_i > 16: + # if loop_count_i <= 16: + # continue + params = {} + params['subject'] = s + params['cross_val_num'] = cv_num + params['fit_variance'] = 0.03 + params['jumplimit'] = 1 + all_regressors = ['contR', 'contL', 'cont', 'prevA', 'weighted_prevA', 'WSLS', 'bias'] + params['regressors'] = [all_regressors[i] for i in [0, 1, 3, 6]] + + # default (non-iteration) settings: + params['fit_type'] = ['prebias', 'bias', 'all', 'prebias_plus', 'zoe_style'][0] + # params['fit_variance'] = [0.0005, 0.002, 0.008, 0.02, 0.06, 0.1, 0.3, 0.6, 1., 2.4, 10, 16, 30, 'uniform'][6] + if 'prevA' in params['regressors'] or 'weighted_prevA' in params['regressors']: + params['exp_decay'], params['exp_length'] = 0.3, 5 + params['exp_filter'] = np.exp(- params['exp_decay'] * np.arange(params['exp_length'])) + params['exp_filter'] /= params['exp_filter'].sum() + print(params['exp_filter']) + params['dur'] = 'yes' + params['obs_dur'] = ['glm', 'cat'][0] + # more obscure params: + params['gamma'] = None # 0.005 + params['alpha'] = None # 1 + if params['gamma'] is not None: + print("_______________________") + print("Warning, gamma is fixed") + print("_______________________") + params['gamma_a_0'] = 0.001 + params['gamma_b_0'] = 1000 + params['init_var'] = 8 + params['init_mean'] = np.zeros(len(params['regressors'])) + # normal: + r_support = np.cumsum(np.arange(5, 100, 5)) + r_support = np.arange(5, 705, 4) + params['dur_params'] = dict(r_support=r_support, + r_probs=np.ones(len(r_support))/len(r_support), alpha_0=1, beta_0=1) + # params['dur_params'] = dict(r_support=np.array([1, 2, 3, 5, 7, 10, 15, 21, 28, 36, 45, 55, 150]), + # r_probs=np.ones(13)/13., alpha_0=1, beta_0=1) + # params['dur_params'] = dict(r_support=np.arange(1, 251), + # r_probs=np.ones(250)/250., alpha_0=1, beta_0=1) + params['alpha_a_0'] = 0.1 + params['alpha_b_0'] = 10 + # trying a smaller value here, should lower the appearance of ephemeral new states on session bounds + # hope this doesn't make real new states at session bound less likely, or hurt mixing... + params['init_state_concentration'] = 3 + # cat params + params['conditioned_on'] = 'nothing' + + params['cross_val'] = False + params['cross_val_fold'] = 10 + params['CROSS_VAL_SEED'] = 4 # Do not change this, it's 4 + + params['seed'] = 100 + params['cross_val_num'] + + params['n_states'] = 15 + params['n_samples'] = 6 if params['obs_dur'] == 'glm' else 4000 + if params['cross_val']: + params['n_samples'] = 4000 + if s.startswith("GLM_Sim"): + print("reduced sample size") + params['n_samples'] = 12000 + + print(params['n_samples']) + # now actual fit: + # new start names: uniform_start_, bias_fraction_, small_gamma_, high_init_, non_semi_, non_semi_normal_init_, correct_sol_, correct_sol_semi_ + while True: + folder = "./dynamic_GLMiHMM_crossvals/" + rand_id = np.random.randint(1000) + if params['cross_val']: + id = "{}_crossval_{}_{}_var_{}_{}_{}".format(params['subject'], params['cross_val_num'], params['fit_type'], + params['fit_variance'], params['seed'], rand_id) + else: + id = "{}_fittype_{}_var_{}_{}_{}".format(params['subject'], params['fit_type'], + params['fit_variance'], params['seed'], rand_id) + if not os.path.isfile(folder + id + '_0.p'): + break + # create placeholder dataset for rand_id purposes + pickle.dump(params, open(folder + id + '_0.p', 'wb')) + if params['obs_dur'] == 'glm': + print(params['regressors']) + else: + print('using categoricals') + print(id) + params['file_name'] = folder + id + np.random.seed(params['seed']) + + info_dict = pickle.load(open("./{}/{}_info_dict.p".format(data_folder, params['subject']), "rb")) + # Determine session numbers + if params['fit_type'] == 'prebias': + till_session = info_dict['bias_start'] + elif params['fit_type'] == 'bias' or params['fit_type'] == 'zoe_style' or params['fit_type'] == 'all': + till_session = info_dict['n_sessions'] + elif params['fit_type'] == 'prebias_plus': + till_session = min(info_dict['bias_start'] + 6, info_dict['n_sessions']) # 6 here will actually turn into 7 later + + from_session = info_dict['bias_start'] if params['fit_type'] in ['bias', 'zoe_style'] else 0 + + models = [] + + if params['obs_dur'] == 'glm': + n_inputs = len(params['regressors']) + T = till_session - from_session + (params['fit_type'] != 'prebias') + obs_hypparams = {'n_regressors': n_inputs, 'T': T, 'jumplimit': params['jumplimit'], 'prior_mean': params['init_mean'], + 'P_0': params['init_var'] * np.eye(n_inputs), 'Q': params['fit_variance'] * np.tile(np.eye(n_inputs), (T, 1, 1))} + obs_distns = [distributions.Dynamic_GLM(**obs_hypparams) for state in range(params['n_states'])] + else: + n_inputs = 9 if params['fit_type'] == 'bias' else 11 + obs_hypparams = {'n_regressors': n_inputs * (1 + (params['conditioned_on'] != 'nothing')), 'n_outputs': 2, 'T': till_session - from_session + (params['fit_type'] != 'prebias'), + 'jumplimit': params['jumplimit'], 'sigmasq_states': params['fit_variance']} + obs_distns = [Dynamic_Input_Categorical(**obs_hypparams) for state in range(params['n_states'])] + + dur_distns = [distributions.NegativeBinomialIntegerR2Duration(**params['dur_params']) for state in range(params['n_states'])] + + if params['dur'] == 'yes': + if params['gamma'] is None: + posteriormodel = pyhsmm.models.WeakLimitHDPHSMM( + # https://math.stackexchange.com/questions/449234/vague-gamma-prior + alpha_a_0=params['alpha_a_0'], alpha_b_0=params['alpha_b_0'], # TODO: gamma vs alpha? gamma steers state number + gamma_a_0=params['gamma_a_0'], gamma_b_0=params['gamma_b_0'], + init_state_concentration=params['init_state_concentration'], + obs_distns=obs_distns, + dur_distns=dur_distns, + var_prior=params['fit_variance']) # TODO: I don't think this does anything + else: + posteriormodel = pyhsmm.models.WeakLimitHDPHSMM( + # https://math.stackexchange.com/questions/449234/vague-gamma-prior + alpha=params['alpha'], # TODO: gamma vs alpha? gamma steers state number + gamma=params['gamma'], + init_state_concentration=params['init_state_concentration'], + obs_distns=obs_distns, + dur_distns=dur_distns, + var_prior=params['fit_variance']) # TODO: I don't think this does anything + else: + if params['gamma'] is None: + posteriormodel = pyhsmm.models.WeakLimitHDPHMM( + alpha_a_0=params['alpha_a_0'], alpha_b_0=params['alpha_b_0'], # TODO: gamma vs alpha? gamma steers state number + gamma_a_0=params['gamma_a_0'], gamma_b_0=params['gamma_b_0'], + init_state_concentration=params['init_state_concentration'], + obs_distns=obs_distns, + var_prior=params['fit_variance']) # TODO: I don't think this does anything + else: + posteriormodel = pyhsmm.models.WeakLimitHDPHMM( + alpha=params['alpha'], # TODO: gamma vs alpha? gamma steers state number + gamma=params['gamma'], + init_state_concentration=params['init_state_concentration'], + obs_distns=obs_distns, + var_prior=params['fit_variance']) # TODO: I don't think this does anything + + print(from_session, till_session + (params['fit_type'] != 'prebias')) + + if params['cross_val']: + rng = np.random.RandomState(params['CROSS_VAL_SEED']) + + data_save = [] + for j in range(from_session, till_session + (params['fit_type'] != 'prebias')): + try: + data = pickle.load(open("./{}/{}_fit_info_{}.p".format(data_folder, params['subject'], j), "rb")) + except FileNotFoundError: + continue + if data.shape[0] == 0: + print("meh, skipped session") + continue + + # if j == 15: + # import matplotlib.pyplot as plt + # for i in [0, 2, 3,4,5,6,7,8,10]: + # plt.plot(i, data[data[:, 0] == i, 1].mean(), 'ko') + # plt.show() + + if params['obs_dur'] == 'glm': + for i in range(data.shape[0]): + data[i, 0] = num_to_contrast[data[i, 0]] + mask = data[:, 1] != 1 + mask[0] = False + if params['fit_type'] == 'zoe_style': + mask[90:] = False + mega_data = np.empty((np.sum(mask), n_inputs + 1)) + + for i, reg in enumerate(params['regressors']): + # positive numbers are contrast on the right + if reg == 'contR': + mega_data[:, i] = np.maximum(data[mask, 0], 0) + elif reg == 'contL': + mega_data[:, i] = np.abs(np.minimum(data[mask, 0], 0)) + elif reg == 'cont': + mega_data[:, i] = data[mask, 0] + elif reg == 'prevA': + # prev_ans = data[:, 1].copy() + new_prev_ans = data[:, 1].copy() + # prev_ans[1:] = prev_ans[:-1] + # prev_ans -= 1 + new_prev_ans -= 1 + new_prev_ans = np.convolve(np.append(0, new_prev_ans), params['exp_filter'])[:-(params['exp_filter'].shape[0])] + mega_data[:, i] = new_prev_ans[mask] + elif reg == 'weighted_prevA': + prev_ans = data[:, 1].copy() + prev_ans -= 1 + # weigh the tendency by how clear the previous contrast was + weighted_prev_ans = data[:, 0] + prev_ans + weighted_prev_ans = np.convolve(np.append(0, weighted_prev_ans), params['exp_filter'])[:-(params['exp_filter'].shape[0])] + mega_data[:, i] = weighted_prev_ans[mask] + elif reg == 'WSLS': + side_info = pickle.load(open("./{}/{}_side_info_{}.p".format(data_folder, params['subject'], j), "rb")) + prev_reward = side_info[:, 1] + prev_reward[1:] = prev_reward[:-1] + prev_ans = data[:, 1].copy() + prev_ans[1:] = prev_ans[:-1] - 1 + mega_data[:, i] = prev_ans[mask] + mega_data[prev_reward[mask] == 0, i] *= -1 + elif reg == 'bias': + # have bias active only if contrasts further from 1 are in the session + # if len(np.unique(data[mask, 0])) > 5: + # print("original 1") + # mega_data[:, i] = 1 + # else: + # print("original 0") + # mega_data[:, i] = 0 + + # have bias active only if contrasts further from 1 are in the session, new version + # if bias_active: + # mega_data[:, i] = 1 + # elif len(np.unique(data[mask, 0])) > 5: + # if np.where(np.abs(data[mask, 0]) == 0.848)[0][0] / data.shape[0] < 0.5: + # mega_data[:, i] = 1 + # else: + # mega_data[:, i] = 0 + # bias_active = True + # else: + # mega_data[:, i] = 0 + + # bias is now always active + mega_data[:, i] = 1 + + mega_data[:, -1] = data[mask, 1] / 2 + elif params['obs_dur'] == 'cat': + mask = data[:, 1] != 1 + mask[0] = False + data = data[:, [0, 1]] + data[:, 1] = data[:, 1] / 2 + mega_data = data[mask] + + data_save.append(mega_data.copy()) + + if params['cross_val']: + test_sets = np.tile(np.arange(params['cross_val_fold']), mega_data.shape[0] // params['cross_val_fold'] + 1)[:mega_data.shape[0]] + rng.shuffle(test_sets) + mega_data[:, -1][test_sets == params['cross_val_num']] = None + + posteriormodel.add_data(mega_data) + + # for d in posteriormodel.datas: + # print(d.shape) + + if not os.path.isfile('./{}/data_save_{}.p'.format(data_folder, params['subject'])): + pickle.dump(data_save, open('./{}/data_save_{}.p'.format(data_folder, params['subject']), 'wb')) + + # states_solution = pickle.load(open("states_{}_{}_condition_{}_{}.p".format('DY_013', 'all', 'nothing', '0_01'), 'rb')) # todo: remove! + time_save = time.time() + likes = np.zeros(params['n_samples']) + with warnings.catch_warnings(): # ignore the scipy warning + warnings.simplefilter("ignore") + for j in range(params['n_samples']): + + if j % 400 == 0 or j == 3: + print(j) + + posteriormodel.resample_model() + + likes[j] = posteriormodel.log_likelihood() + model_save = copy.deepcopy(posteriormodel) + if j != params['n_samples'] - 1 and j != 0 and j % 2000 != 1: + # To save on memory: + model_save.delete_data() + model_save.delete_obs_data() + model_save.delete_dur_data() + models.append(model_save) + + # save something in case of crash + if j % 400 == 0 and j > 0: + if params['n_samples'] <= 4000: + pickle.dump(models, open(folder + id + '.p', 'wb')) + else: + pickle.dump(models, open(folder + id + '_{}.p'.format(j // 4001), 'wb')) + if j % 4000 == 0: + models = [] + print(time.time() - time_save) + + if params['cross_val']: + lls, lls_mean = eval_cross_val(models, posteriormodel.datas, data_save, n_all_states=params['n_states']) + params['cross_val_preds'] = lls + params['cross_val_preds'] = params['cross_val_preds'].tolist() + + print(id) + if 'exp_filter' in params: + params['exp_filter'] = params['exp_filter'].tolist() + params['dur_params']['r_support'] = params['dur_params']['r_support'].tolist() + params['dur_params']['r_probs'] = params['dur_params']['r_probs'].tolist() + params['ll'] = likes.tolist() + params['init_mean'] = params['init_mean'].tolist() + if params['cross_val']: + json.dump(params, open(folder + "infos_new/" + '{}_{}_cvll_{}_{}_{}_{}_{}.json'.format(params['subject'], params['cross_val_num'], str(np.round(lls_mean, 3)).replace('.', '_'), + params['fit_type'], params['fit_variance'], params['seed'], rand_id), 'w')) + else: + json.dump(params, open(folder + "infos_new/" + '{}_{}_{}_{}_{}.json'.format(params['subject'], params['fit_type'], + params['fit_variance'], params['seed'], rand_id), 'w')) + pickle.dump(models, open(folder + id + '_{}.p'.format(j // 4001), 'wb')) diff --git a/dynamic_GLMiHMM_fit.py b/dynamic_GLMiHMM_fit.py index dbbe447a..bf1d046d 100644 --- a/dynamic_GLMiHMM_fit.py +++ b/dynamic_GLMiHMM_fit.py @@ -67,7 +67,7 @@ contrast_to_num = {-1.: 0, -0.987: 1, -0.848: 2, -0.555: 3, -0.302: 4, 0.: 5, 0. num_to_contrast = {v: k for k, v in contrast_to_num.items()} cont_mapping = np.vectorize(num_to_contrast.get) -data_folder = 'session_data' +data_folder = 'session_data_test' old_style = False if old_style: print("Warning, data can have splits") @@ -86,7 +86,7 @@ subjects = ['ibl_witten_15', 'ibl_witten_17', 'ibl_witten_18', 'ibl_witten_19', 'CSH_ZAD_017', 'CSH_ZAD_025', 'CSH_ZAD_026', 'CSHL049', 'CSHL051', 'CSHL061'] # test subjects: -sim_subjects = ['GLM_Sim_13', 'GLM_Sim_11', 'GLM_Sim_15'] +subjects = ['KS014'] # subjects = ['KS021', 'KS016', 'ibl_witten_16', 'SWC_022', 'KS003', 'CSHL054', 'ZM_3003', 'KS015', 'ibl_witten_13', 'CSHL059', 'CSH_ZAD_022', 'CSHL_007', 'CSHL062', 'NYU-06', 'KS014', 'ibl_witten_14', 'SWC_023'] # subjects = [['GLM_Sim_15', 'GLM_Sim_14', 'GLM_Sim_13', 'GLM_Sim_11', 'GLM_Sim_10', 'GLM_Sim_09', 'GLM_Sim_12'][2]] @@ -314,30 +314,10 @@ for loop_count_i, (s, cv_num) in enumerate(product(subjects, cv_nums)): mega_data[:, i] = prev_ans[mask] mega_data[prev_reward[mask] == 0, i] *= -1 elif reg == 'bias': - # have bias active only if contrasts further from 1 are in the session - # if len(np.unique(data[mask, 0])) > 5: - # print("original 1") - # mega_data[:, i] = 1 - # else: - # print("original 0") - # mega_data[:, i] = 0 - - # have bias active only if contrasts further from 1 are in the session, new version - # if bias_active: - # mega_data[:, i] = 1 - # elif len(np.unique(data[mask, 0])) > 5: - # if np.where(np.abs(data[mask, 0]) == 0.848)[0][0] / data.shape[0] < 0.5: - # mega_data[:, i] = 1 - # else: - # mega_data[:, i] = 0 - # bias_active = True - # else: - # mega_data[:, i] = 0 - # bias is now always active mega_data[:, i] = 1 - mega_data[:, -1] = data[mask, 1] / 2 + mega_data[:, -1] = data[mask, 1] / 2 # 0 is rightwards, and 1 is leftwards, because the original data is weird elif params['obs_dur'] == 'cat': mask = data[:, 1] != 1 mask[0] = False @@ -357,9 +337,9 @@ for loop_count_i, (s, cv_num) in enumerate(product(subjects, cv_nums)): # for d in posteriormodel.datas: # print(d.shape) - if not os.path.isfile('./{}/data_save_{}.p'.format(data_folder, params['subject'])): - pickle.dump(data_save, open('./{}/data_save_{}.p'.format(data_folder, params['subject']), 'wb')) - + # if not os.path.isfile('./{}/data_save_{}.p'.format(data_folder, params['subject'])): + pickle.dump(data_save, open('./{}/data_save_{}.p'.format(data_folder, params['subject']), 'wb')) + quit() # states_solution = pickle.load(open("states_{}_{}_condition_{}_{}.p".format('DY_013', 'all', 'nothing', '0_01'), 'rb')) # todo: remove! time_save = time.time() likes = np.zeros(params['n_samples']) diff --git a/index_mice.py b/index_mice.py index e821de0e..add07bda 100644 --- a/index_mice.py +++ b/index_mice.py @@ -20,14 +20,6 @@ for filename in os.listdir("./dynamic_GLMiHMM_crossvals/"): fit_num = result.group(5) chain_num = result.group(6) - # print() - # print(filename) - # print(subject) - # print(fit_type) - # print(seed) - # print(fit_num) - # print(chain_num) - # continue if fit_type == 'prebias': local_dict = prebias_subinfo elif fit_type == 'bias': diff --git a/pmf_weight_analysis.py b/pmf_weight_analysis.py index 00611bcc..05985150 100644 --- a/pmf_weight_analysis.py +++ b/pmf_weight_analysis.py @@ -3,10 +3,148 @@ import matplotlib.pyplot as plt import pickle from scipy.stats import gaussian_kde from analysis_pmf import pmf_type, type2color +from mpl_toolkits import mplot3d + +performance_points = np.array([-1, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0]) +reduced_points = np.array([1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1], dtype=bool) + +folder = "./temp_reward_analysis/" + +def pmf_to_perf(pmf): + # determine performance of a pmf, but only on the omnipresent strongest contrasts + return np.mean(np.abs(performance_points[reduced_points] + pmf[reduced_points])) + + +contrasts_L = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0]) +contrasts_R = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0])[::-1] + + +def weights_to_pmf(weights, with_bias=1): + psi = weights[0] * contrasts_R + weights[1] * contrasts_L + with_bias * weights[-1] + return 1 / (1 + np.exp(psi)) + +def pmf_type_rew(weights): + rew = pmf_to_perf(weights_to_pmf(weights)) + if rew < 0.6: + return 0 + elif rew < 0.7827: + return 1 + else: + return 2 # all pmf weights apw = np.array(pickle.load(open("all_pmf_weights.p", 'rb'))) +colors = [type2color[pmf_type(weights_to_pmf(x))] for x in apw] +colors_rew = [type2color[pmf_type_rew(x)] for x in apw] + + +if True: + for i, weights in enumerate(apw): + if pmf_type(weights_to_pmf(weights)) != pmf_type_rew(weights): + plt.plot(weights_to_pmf(weights)) + plt.ylim(0, 1) + plt.title("Classic says {}, reward says {}, ({})".format(1 + pmf_type(weights_to_pmf(weights)), 1 + pmf_type_rew(weights), pmf_to_perf(weights_to_pmf(weights)))) + print(weights_to_pmf(weights)) + plt.tight_layout() + plt.savefig(folder + "divergent classification {}".format(i)) + plt.close() + + +type1_rews = [] +type2_rews = [] +type3_rews = [] +all_rews = [] +for weights in apw: + type = pmf_type(weights_to_pmf(weights)) + all_rews.append(pmf_to_perf(weights_to_pmf(weights))) + if type == 0: + if pmf_to_perf(weights_to_pmf(weights)) > 0.8: + plt.plot(weights_to_pmf(weights)) + plt.show() + type1_rews.append(pmf_to_perf(weights_to_pmf(weights))) + elif type == 1: + type2_rews.append(pmf_to_perf(weights_to_pmf(weights))) + elif type == 2: + type3_rews.append(pmf_to_perf(weights_to_pmf(weights))) + +type1_rews, type2_rews, type3_rews = np.array(type1_rews), np.array(type2_rews), np.array(type3_rews) + +bound1 = np.linspace(0.55, 0.65, 100) +bound2 = np.linspace(0.75, 0.85, 100) + +opt_bound1, errors1 = 0, 100 +for b in bound1: + if errors1 > (np.sum(type1_rews > b) + np.sum(type2_rews < b)): + opt_bound1 = b + errors1 = np.sum(type1_rews > b) + np.sum(type2_rews < b) + +opt_bound2, errors2 = 0, 100 +for b in bound2: + if errors2 > (np.sum(type2_rews > b) + np.sum(type3_rews < b)): + opt_bound2 = b + errors2 = np.sum(type2_rews > b) + np.sum(type3_rews < b) + +print(opt_bound1, errors1, opt_bound2, errors2) + +opt_bound2 = 0.780303 +print("Optimal bound 2: {}, {}".format(np.sum(type2_rews > opt_bound2), np.sum(type3_rews < opt_bound2))) + +man_bound = 0.7827 +print("Manual bound 2: {}, {}".format(np.sum(type2_rews > man_bound), np.sum(type3_rews < man_bound))) + + +bins = np.linspace(0, 1, 30) +plt.hist([type1_rews, type2_rews, type3_rews], bins=bins, label=["Type 1", "Type 2", "Type 3"]) +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') +plt.legend() +plt.savefig(folder + "hist 1") +plt.show() + +plt.hist([type1_rews, type2_rews, type3_rews], bins=bins, label=["Type 1", "Type 2", "Type 3"], stacked=True) +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') +plt.legend() +plt.savefig(folder + "hist 2") +plt.show() + +plt.subplot(1, 3, 1) +plt.title("Bins = 25") +plt.hist(all_rews, bins=25) +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') + +plt.subplot(1, 3, 2) +plt.title("Bins = 40") +plt.hist(all_rews, bins=40) +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') + +plt.subplot(1, 3, 3) +plt.title("Bins = 55") +plt.hist(all_rews, bins=55) +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') + +plt.savefig(folder + "hists compare") +plt.show() + + +fig = plt.figure(figsize=(13 * 3 / 5, 9 * 3 / 5)) +plt.hist(all_rews, bins=40, color='grey') +plt.axvline(0.6, c='k') +plt.axvline(0.7827, c='k') + +plt.ylabel("# of occurences", size=28) +plt.xlabel("Reward rate", size=28) +plt.gca().spines[['right', 'top']].set_visible(False) + +plt.tight_layout() +plt.savefig(folder + "single hist") +plt.show() + + xy = np.vstack([apw[:, i] for i in range(4)]) z = gaussian_kde(xy)(xy) @@ -25,67 +163,107 @@ plt.scatter(apw[:, 3], apw[:, 0], c=z) plt.xlabel("Bias") plt.ylabel("Cont right") +plt.savefig(folder + "density scatter") plt.show() -contrasts_L = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0]) -contrasts_R = np.array([1., 0.987, 0.848, 0.555, 0.302, 0, 0, 0, 0, 0, 0])[::-1] - -def weights_to_pmf(weights, with_bias=1): - psi = weights[0] * contrasts_R + weights[1] * contrasts_L + with_bias * weights[-1] - return 1 / (1 + np.exp(psi)) - -colors = [type2color[pmf_type(weights_to_pmf(x))] for x in apw] - -plt.subplot(1, 3, 1) +plt.subplot(1, 4, 1) sc = plt.scatter(apw[:, 0], apw[:, 1], c=colors) -fig, ax = plt.gcf(), plt.gca() +fig, ax1 = plt.gcf(), plt.gca() plt.xlabel("Cont right") plt.ylabel("Cont left") -annot = ax.annotate("", xy=(0, 0), xytext=(20, 20), textcoords="offset points", - bbox=dict(boxstyle="round", fc="w"), - arrowprops=dict(arrowstyle="->")) -annot.set_visible(False) +annot1 = ax1.annotate("", xy=(0, 0), xytext=(20, 20), textcoords="offset points", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="->")) +annot1.set_visible(False) + +plt.subplot(1, 4, 2) +plt.scatter(apw[:, 3], apw[:, 1], c=colors) +ax2 = plt.gca() +plt.xlabel("Bias") +plt.ylabel("Cont left") + +annot2 = ax2.annotate("", xy=(0, 0), xytext=(20, 20), textcoords="offset points", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="->")) +annot2.set_visible(False) + +plt.subplot(1, 4, 3) +plt.scatter(apw[:, 3], apw[:, 0], c=colors) +ax3 = plt.gca() +plt.xlabel("Bias") +plt.ylabel("Cont right") + +annot3 = ax3.annotate("", xy=(0, 0), xytext=(20, 20), textcoords="offset points", + bbox=dict(boxstyle="round", fc="w"), + arrowprops=dict(arrowstyle="->")) +annot3.set_visible(False) + def update_annot(ind): - print(ind) pos = sc.get_offsets()[ind["ind"][0]] - annot.xy = pos + annot1.xy = pos text = "{}".format(np.round(apw[ind["ind"][0]], 2)) - annot.set_text(text) + annot1.set_text(text) + + annot2.xy = apw[ind["ind"][0]][[3, 1]] + text = "{}".format(np.round(apw[ind["ind"][0]], 2)) + annot2.set_text(text) + + annot3.xy = apw[ind["ind"][0]][[3, 0]] + text = "{}".format(np.round(apw[ind["ind"][0]], 2)) + annot3.set_text(text) + + plt.subplot(1, 4, 4) + plt.cla() + plt.plot(weights_to_pmf(apw[ind["ind"][0]])) + plt.ylim(0, 1) + plt.ylabel("P(rightwards)") + plt.xlabel("Contrasts") + def hover(event): - vis = annot.get_visible() - if event.inaxes == ax: + vis = annot1.get_visible() + if event.inaxes == ax1: cont, ind = sc.contains(event) if cont: update_annot(ind) - annot.set_visible(True) + annot1.set_visible(True) + annot2.set_visible(True) + annot3.set_visible(True) fig.canvas.draw_idle() else: if vis: - annot.set_visible(False) + annot1.set_visible(False) + annot2.set_visible(False) + annot3.set_visible(False) fig.canvas.draw_idle() + fig.canvas.mpl_connect("motion_notify_event", hover) -plt.subplot(1, 3, 2) -plt.scatter(apw[:, 3], apw[:, 1], c=colors) -plt.xlabel("Bias") -plt.ylabel("Cont left") +plt.savefig(folder + "type scatter") +plt.show() -plt.subplot(1, 3, 3) -plt.scatter(apw[:, 3], apw[:, 0], c=colors) -plt.xlabel("Bias") -plt.ylabel("Cont right") +fig = plt.figure(figsize=(16, 9)) +ax = plt.axes(projection='3d') +ax.scatter3D(apw[:, 0], apw[:, 1], apw[:, 3], c=colors) +ax.view_init(27.5, -137) +plt.savefig(folder + "3d types") plt.show() +fig = plt.figure(figsize=(16, 9)) +ax = plt.axes(projection='3d') +ax.scatter3D(apw[:, 0], apw[:, 1], apw[:, 3], c=colors_rew) +ax.view_init(27.5, -137) +plt.savefig(folder + "3d types new") +plt.show() -from mpl_toolkits import mplot3d fig = plt.figure() ax = plt.axes(projection='3d') -ax.scatter3D(apw[:, 0], apw[:, 1], apw[:, 3], c=colors) +ax.scatter3D(apw[:, 0], apw[:, 1], apw[:, 3], c=z) +plt.savefig(folder + "3d density") plt.show() diff --git a/process_many_chains.py b/process_many_chains.py index cf806135..a0664e42 100644 --- a/process_many_chains.py +++ b/process_many_chains.py @@ -17,7 +17,7 @@ if fit_type == 'bias': loading_info = json.load(open("canonical_infos_bias.json", 'r')) elif fit_type == 'prebias': loading_info = json.load(open("canonical_infos.json", 'r')) -subjects = ['SWC_021', 'ibl_witten_15', 'ibl_witten_13', 'KS003', 'ibl_witten_19', 'SWC_022', 'CSH_ZAD_017'] # list(loading_info.keys()) +subjects = ['ZFM-04019', 'ZFM-05236'] # list(loading_info.keys()) fit_variance = [0.03, 0.002, 0.0005, 'uniform', 0, 0.008][0] func1 = state_num_helper(0.2) diff --git a/simplex_animation.py b/simplex_animation.py index 89dfe945..ddf6df79 100644 --- a/simplex_animation.py +++ b/simplex_animation.py @@ -9,6 +9,7 @@ import copy all_state_types = pickle.load(open("all_state_types.p", 'rb')) + # create a list of fixed offsets, to apply to mice when they are in a corner offsets = [(0, 0)] hex_size = 0 @@ -37,7 +38,7 @@ assert (test_count == 1).all() # plt.show() # quit() -session_counter = 0 +session_counter = -1 alph = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'za', 'zb', 'zc', 'zd', 'ze', 'zf', 'zg', 'zh', 'zi', 'zj'] # do as many sessions as it takes while True: @@ -65,9 +66,8 @@ while True: type_proportions[:, i] = sts[:, temp_counter] - plotSimplex(type_proportions.T, x_offset=x_offset, y_offset=y_offset, c=np.arange(len(all_state_types)), show=False, title="Session {}".format(session_counter), + plotSimplex(type_proportions.T, x_offset=x_offset, y_offset=y_offset, c=np.arange(len(all_state_types)), show=False, title="Session {}".format(1 + session_counter), vertexcolors=[type2color[i] for i in range(3)], vertexlabels=['Type 1', 'Type 2', 'Type 3'], save_title="simplex_{}.png".format(alph[session_counter])) - plt.close() if not_ended == 0: break diff --git a/simplex_plot.py b/simplex_plot.py index 635885d0..420dd26c 100644 --- a/simplex_plot.py +++ b/simplex_plot.py @@ -14,8 +14,8 @@ import matplotlib.patches as PA def plotSimplex(points, fig=None, - vertexlabels=['1: initial flat PMFs', '2: intermediate unilateral PMFs', '3: final bilateral PMFs'], - save_title="test.png", show=False, vertexcolors=['k', 'k', 'k'], x_offset=0, y_offset=0, **kwargs): + vertexlabels=['1: initial flat PMFs', '2: intermediate unilateral PMFs', '3: final bilateral PMFs'], title='', + save_title="dur_simplex.png", show=False, vertexcolors=['k', 'k', 'k'], x_offset=0, y_offset=0, **kwargs): """ Plot Nx3 points array on the 3-simplex (with optionally labeled vertices) @@ -37,21 +37,25 @@ def plotSimplex(points, fig=None, # fig.gca().annotate(vertexlabels[2], (0.1, np.sqrt(3) / 2 + 0.025), size=24, color=vertexcolors[2], annotation_clip=False) # Project and draw the actual points projected = projectSimplex(points / points.sum(1)[:, None]) - print(projected) - P.scatter(projected[:, 0], projected[:, 1], s=points.sum(1) * 3.5, **kwargs) + P.scatter(projected[:, 0] + x_offset, projected[:, 1] + y_offset, s=points.sum(1) * 3.5, **kwargs)#s=35 # plot center with average size projected = projectSimplex(np.mean(points / points.sum(1)[:, None], axis=0).reshape(1, 3)) - P.scatter(projected[:, 0], projected[:, 1], marker='*', color='r', s=np.mean(points.sum(1)) * 3.5) + print(points) + print() + print(projected) + P.scatter(projected[:, 0], projected[:, 1], marker='*', color='r', s=np.mean(points.sum(1)) * 3.5)#s=50 # Leave some buffer around the triangle for vertex labels fig.gca().set_xlim(-0.05, 1.05) fig.gca().set_ylim(-0.05, 1.05) P.axis('off') + if title != '': + P.annotate(title, (0.395, np.sqrt(3) / 2 + 0.025), size=24) P.tight_layout() - P.savefig("dur_simplex.png", bbox_inches='tight', dpi=300, transparent=True) + P.savefig(save_title, bbox_inches='tight', dpi=300, transparent=True) if show: P.show() else: diff --git a/state_dict_KS014 b/state_dict_KS014 new file mode 100644 index 0000000000000000000000000000000000000000..c183d111be82d6be94e31c438d9ece422bbbea76 GIT binary patch literal 153288 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%0AAw5U=2x%2+WrGt$o zdF!vtqwQ<|*mmzi9t9j)XxJ_(kK`|T1VwJeM^WxD36NWh=%U=wMm*qObI?~As0=;D z#pG?(yR>s|$NwVc?7+8@++Op;1BX-zlD`src-bS+Od~U-^ZS?1c$>o86xKD?H9P<h zzyt8W+v)+i1OG6p$Q}8p`_5)3@%fa0a_!8wlH7%lqG4CUKe>J__V7=xL#k<B4>B8> z{kCQ{<|POqKamH>1FQph03Lt`-~o659)JhlMi0o2{N!4ZiI2K7@vh>0o1cky<6BAY z&PQ=3exF}D+e7T(XW}#Qo7QnhBDK<Bc9<Pze;dt?yhL6iFY*2a55NQP06YK>zyt6A zJOB^C1MmPm01v#I9*}$TBD^B^;-ju&-&@q>dBwgD-%4^{K8lKc7O&X%6MJ~Y{(-IL zcw^;b<zwZ)n=2p34aW`shQHwfcmN)N2jBsC03Lt`-~o659)Jhn0eAo&_|pS&e_s4n zWECIPzcE@KAPVEJ?(Q^DRK|JDd=TGC@?fz`{oAAEA!3KPyOWJwxJ$e66x!Wu_=vAo zrO=wmPd2W2luX$_4`~}RCYid%9o<}|aSBZsZ(Hld?<v$c#`@=?++=#vIeeSX$|Q<! zRd(2DRT6bRGwq!3f@In<`6=aYPbPUNkD$mBA9WS{VInA>%{P22$;0`moy`cbL(IlX z6&#iDO&U3QPuw`(F^wiFFTb;$ok~Cbc7MRR!W4Qjy0l@3dZ`rhdt0OI1F7_zUDD3T z`zh33?|#?dr74tGc~cowltO#Frq*1tIF(YjEZ^NPES2PuJc1%S@liJ$XAzXoW)$B_ z@@PJ4XX7Gvh}n#=>{YW(Xa>a(-WlN(kU>k9L|ErUrPHR^*s@d4(&*av?1xUq>9p>= z-LLbfq|?aw<564Zr<1;Or#~+1Wl)FxUw^eK;41wqVe+=8KW9?^p!U6YpU))Ol}Auy zH$LiSGe!jEvl+{`lI+e$?QA^64l$b{4hJjKJkqJwX2W4=s&u-%?&izXd1*BFp`kK8 zJ(a%L9=W{D{ZyKAa%so1NoizdS?fZ_$ElP*CUV*A>{RL&7MeVEeHuNg7M;CgayqrU Y<#BcFymXSs@d%1Mo{#*uIs3HyHz!v=!~g&Q literal 0 HcmV?d00001 diff --git a/state_dict_ZFM-04019 b/state_dict_ZFM-04019 new file mode 100644 index 0000000000000000000000000000000000000000..458cbe0f1f432c5e57ca3156688138077467873d GIT binary patch literal 166660 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 P2Qx_QE+QU;ds+P#1N_e5 literal 0 HcmV?d00001 diff --git a/state_dict_ZFM-05236 b/state_dict_ZFM-05236 new file mode 100644 index 0000000000000000000000000000000000000000..216c9aeaafe342f1fda365a4d8261f91f3c2d74c GIT binary patch literal 245334 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ᯰO>|n0p4rX^b!yU|R=wKQz93lvS00@8p2!H?x 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 literal 0 HcmV?d00001 -- GitLab