From 46618e1e1d122d6bf23011eca5dc8283377e8f1c Mon Sep 17 00:00:00 2001 From: jakobrunge Date: Sat, 9 Apr 2022 15:22:45 +0200 Subject: [PATCH 1/4] fixed bug in causal effects --- docs/_build/doctrees/environment.pickle | Bin 924501 -> 952097 bytes docs/_build/doctrees/index.doctree | Bin 1532023 -> 1591003 bytes .../_modules/tigramite/causal_effects.html | 365 +++++++++++++++-- .../_modules/tigramite/data_processing.html | 21 +- .../tigramite/independence_tests/gpdc.html | 4 +- .../independence_tests/gpdc_torch.html | 10 +- .../html/_modules/tigramite/models.html | 94 +++-- .../html/_modules/tigramite/plotting.html | 369 +++++++++++++++++- docs/_build/html/genindex.html | 16 +- docs/_build/html/index.html | 154 +++++++- docs/_build/html/objects.inv | Bin 1482 -> 1523 bytes docs/_build/html/searchindex.js | 2 +- docs/_modules/tigramite/causal_effects.html | 365 +++++++++++++++-- docs/_modules/tigramite/data_processing.html | 21 +- .../tigramite/independence_tests/gpdc.html | 4 +- .../independence_tests/gpdc_torch.html | 10 +- docs/_modules/tigramite/models.html | 94 +++-- docs/_modules/tigramite/plotting.html | 369 +++++++++++++++++- docs/genindex.html | 16 +- docs/index.html | 154 +++++++- docs/objects.inv | Bin 1482 -> 1523 bytes docs/searchindex.js | 2 +- release_on_pip.sh | 10 +- setup.py | 2 +- 24 files changed, 1873 insertions(+), 209 deletions(-) mode change 100644 => 100755 release_on_pip.sh diff --git a/docs/_build/doctrees/environment.pickle b/docs/_build/doctrees/environment.pickle index 689f5d6e529887bb22c6b1934758ee9a354ca5fe..24b4dab7f74d83f38de446026114d52822f5ef0d 100644 GIT binary patch delta 31382 zcmc(I34Bvk);P&aUXquWE_B~to37A?wunlhK-sapQkDTqThg>mX+oNmB;8mnxFK2u ze1+?R0_r$A<0y-_1Ms z+;h)8=iGC*b05c^xpvPT725Th?O!~wPa7+61G-MH$7yfz4@${`*)YKRye+K`@1RsE zWI<-P-RpCB+=EXp7uKou1B~6>J=o4jX}WCbgPbzcKJ|zZv#O2{+V(8|-YE&@3LS=Q z87!3M=T4Ho%&k#br51BZiO=D;mvq`%R@zqBePcR0T~@!x<67zP`^MOM9X^}a@9_D_ zPnW|jePK?MKFG^wU7al*Ee>gKUb*yiUbeB*=56tKy_U|tLCI#GttyfBX^V3!PBzOK4 z^$14Vo1dlDGSbofWHrM`pXS#!sF)EWx|)3hoXg{0;dl65cHiK-K__mZlYu z3ByJJY{1yu<#O5mRu?pAP#P@S07VL&TF7eeb+V8&!Yfp_yC6v)gh~es#`OnZ2nt{T zErZwIX7}3NE%u90avBKQqB*k`REcvI%^19SFkGKA3NoG1_%Rk9UClOU45XNyk&reH zI^$`Qh!bwmnM_|(rT((Ce%#6d&gO1u_juj54*OtxZv* zB#J{M3JD2k4kSZFWsqg%94!e&iPMG(=Mv2rR^I>%Mq_vTL2FW9(f#~#Tpex3T**Aj z)lb?nhcIzT@eHFY)5wN`R1~xw_De}viG*#0Ge1PbOxSQ1Kr%!YK~a=kETjA)8N|>$ zqZ9J6_y!UyIy|ivO@7A;udM_6qlNUYrokY2gY?tU8M(5giCi{7F(v&T9U1{|XDvzKbye@NvYkvg0P zG9U>R!ZftuQzk=7FEbd3=0l*XoGT&m-&3p*bk=3-Q-(QfY1>`tioW`mOEv93 zr05%|qE!Ydc6<@^-PrNja^IynSEk~hjlX)hiq~JN5tpapbyq^-zo+8Vpo*&|#u+2V zW9gq2*+V?@^OtJRe@L$Zs#h`uCqf7Q)r15tJRgt_Oh~64nc`iUmJ24%9j@i4F4d&V z)AGJ6A@SeSata-KS5+p4J@l4JVTgjixKvaALkj*hLc#H%;Q5o{A{AUcDU~Xi;$4}7 zpPV#ixPm{vRFf`G!GFFI68~2UrgN8(bKI?t7Q0WdxmyLlt=VOlPEY3Wi1*p#WGcrj z?IosD!v!EONEb{g94^Q7DC_-%f?Rfsp3NdB~`6I21Ie`JbAv*sbw8y>>QcMl(UDf!3E1J0|B2$23TV`~@Q#*4NOY*Nl z+ZvffDKOV8t?n^Ohh~nV@N1>2SxJ&^RvjSQX4zyQI{lI=SvoyyDL}{1?x4`|(m!V> zOYhGzOCQa?1~Rhd;6ifw28&X3?Z`Z^mtH(ysr3rs?*T4A+hsI~&sQH`;GRV`O> zH9E5d_?a?yF~yxIou8W~)vbw=cF#(|eT0g%Aat_bGk><=t=TlXg()v0=^k)m^ z1?y4`>QYF7nuXUvfx8!Ora6_;l$OFf7w}TkqUiwt@uCgzEcnqn{QE~Y!*lfFjqrSu zJSQw^f#189NVM!6+$L#vU95ED(peNV6U8R#5~V|J*#w?khlw`U?Skj`b=%?j`ic_i z(6ZU^%TV7)%gjcrRJwHOkTq9&tiBdw)?+668@9nSw()j&-q$F%d$|)Gq#zK`@QW! zcl~Gkx8Jb^p4CqLJn39VtEvf^1;KoLB3#;Qx}$hM+X+)u@0>MM)#&vYLsmbzqQ%p@%#KEnN3COJSU@d&_*#XbN&Ku#GylP`6Aw09wYlk7?62w1WReBNP zyH{aLDfde7{H=EmJY#%~@O1m+Emxop&LJc*Nt^Hu?Ii*_F(6g-`l|vmdio-R;jGFRC>L)6f*wVy9%D2eVD}Q zK3sV2>do*xv08Qw71B$7v-Ey%v?O$M(#AE{Lgt}0xKR08{CsHbe5%$_AZ6*Lo&>4? zdQQq%R}Oi#>oD0v84b)RKPe0H5o38A++D zI&8j`f@E8tD^0nk;F&x9diWl8JT0)ET}Y?m81_~H4F4R^tF`wiGGl5WI`yZ1(% zJMt#{+=QQZ-i*f$>&-X8^G`QpaQ!Xql$nVr<`2er>D^l}84j-b3@2pxq0Z z6lvYf$Gj)_6C$(1jlSddPN4F`?ag%DDU?G06l zhu5jL*4AJt(ztD#Gg4#*WqhH-?r-Mr?oE;zH$K+D=A zkxcD2pVhvqi%e2NhjzF6LNge=>y3%_Q>ul|wLqPm_6=xTTsEI?@RmVme+Xs(WqKXW zU4A=;-*6H5%@={+dJ*{T+7bP7r9&&Y<01vNh2Shz3g%`|35b+{_go01ss|4Jy1bk5m*#D9e^w&zjmqWm?g}fSq zMJVL;5HO5*Bm|2<{9{=E5zx1kP~TAko>Bt7uLS%+3HWCK_EVdWsQzOm)K8UwUnl|3 zD*^we1pFEU>CtmU_1`L?ey;=^!Cu&7nGh_3B&!58P+&j!zz9@c2{l>?I8q6i5CVoZ zpB#ck)RPtj_D9y98H7dxvz36kO27go;3y?vNeI{1iU^33^!>*2o@ow zo0NbX6@dND+Z3SA%}T(nNbbhhPzne?$rRGbP~T zEcl-bJn%jx)TctgaP5H*ETZ=3m4FA7fQJBhq5uDt66$Z2fUhV4f3E~QtOWc6243L* zk13%ZR|1|?0=}mNJfj5s69M+)$fpSDeH20si}`E_7J>M=67ZZ7@UKe1uVkQf^Ib(j z8IXA`?)v`-l?XHOLkKo>s;JflEodlQdl9()LU=!!)EY0$An>S*z+*%32&u#?0h2;N zeOs5ih3p$bD^r8u{(&Lzj39g{SWpI=mBIPS;36fke$ZJ=;L_N8rcEIce?I+)5x`=( z68fNXoHF=YO5~Y)@`*;BGLcEj*j38l>B`_)%HZpi!Tq8#yjB^!P#L^91P+^FT?iJT z^@ia;qTbOIEw(7d3ELgFLad)s?AL3AIw0J3WsBnu+6f@?#@ z3$dBu^&{P_&e)luS}aX~=W9~k&XVlk1A&2PtIM{!&k7q$ZlB8rOFan!qkNt14tMXM zw0mb#%n`tH9>tG8;Kv`OU+>KCe*=CNI)`Qr@FMBV0vtQQj<+8IHHTq1PeQSc(Ak?e z;!5lg?b<%*JOe-o;AOe< zFE@_8f8*HuRe`bhs}DY}nvVXul$ov88&G8(lZw;2I!3_hnmQ&2r@QKyESw&yW6U`H za~+e5Q{yt4mMvrQ@q67e#)8vL%a|gZJ|*X$kl(fSOdf_8*E6GVy0o6j#_5`RivMsu zt?$)(rWnJ&k>TbBW(fb1PDwB7xUl;58gCL6{61zmlbucIzQu}vXNS@yahW9mzw2f9O z-LY2M`Z_CZ^^NlTqgIOdh7AA4%9P^rqnar9)lHP!J~{nK6Q%Qd6K%~`a++nM^~|!- zR{3qTp8IVS?`0cPg6V!G=bM{ltu!-5GfC@vqQ%dmp;=lQRT$i;skX>qh$gqT$r|`J zTKpE{>fIi92#yXlGf5ik;CD1L*{Xf$`(`Ew5}}1Lvm^#OLz*xvQ=l`lII6r(ufy%P zdSNHZYDtIt=1nazu)Jg1atyCKM&EBarX?LBa7=qOhX3W5mY7V= zTiS61?=2bcEed~5hM#*&OFH(*x3#2WU;Vb0m`eNGTGEm3d|OL8_OowmNyj|-ww4&Y z=D3!0=rPA>`T57S**QezNqVtJ4{D5|k)#$Y-tvYxb!a;9HF%uX^XzdgaUAa+r|tTu zOh1ywG^lgbv|&L6(;x(Fo$$XfKM>Ne;Wt8V3ZD1Asy||o7x1` zzQE%5v;{jbH~oH=Snh5=OEp`)q zYwu!-1@G!&%V_?w>XVRvbTvyXRMX9t@VHggA69=3oTfsQVk(dKutd_wdT5Ry84anBV!d)12eIGlDy1hJ9)y1Zu{{3tebtDse z*+Tm3{T?=xBIQW`tTkgVRkNBMgNv_bGbv7I7h3{=H&(NwA^CPSYo_q?el`^V6W6e5 zltePBTEoVps2-N303u&Z^X@gQ0I1s@*5wCIuVFt=z%o3%jY{b6+d%8Ucj}#N5!KH0 z>Y326c(i*18xMC|h{cr?Sd6V19}Twn;iglk-Rtj@bLUjsp+t1m)M=vKZ?jmfZhMc_ zN@ZBRu6jLW#so9H_7xysyO(sNLw8bjeI%z*5>-#RL`|w*V)F`#$?U0q5UA*6DssJ@ z1jqmo0|JjoY#gz~1JASRxQ!>Dr*_2dXUU|cd_PrV(|(o=hgYW66_^$2G`d=wcN*N5g7E|iFR=MkxY^R4r8!u*oiDI?6qF|&uFKcbL9Ajwn=6YP z#U6l0o@zq1pXy#jUmakhOvQr7S1feGxr)otjLzri;!*O8>`N9IVyT6kLXVHUTi^~E zj`k?DTJapvYAq@f#s~!#%b3847g>!}t@!|*&d_DE15B&EZ4j}Ux;*s(4wYo;M&oo@ zrfwWgw`J-qIDIKocP&o819;W}4vc(_N?Z?(9Wc$Rojwhe=WxR@FlY~u=4I)!d4hDe zN_-S|w5)7hDlUFk7A5z)EL|af|KBWKDNb_*T@g;_3AzlNx&_L{y@IY7zrP~rMsZ}& z6>xPZ`ypK>2r4~WmjOvdwhqQv)Re8up;rEnEL}bTex9uhiSwImptx(@#l#r^ajI1R zhA0PBXk#8|;=Vkch(62H%}eonVBs*SvH+`!Ubw3-ATadeB0d{^pReNrH|Fcc_Th#- zyNfpP!(F;kJr-HDvw9G%-=j-G*X-7%5h+&hsD2UzJqexLrAt6jdvtUI- zpYPUf!fEdw-9(%|vqx8LAbOal5}VP1J-QNf&ozZ(~osm1#LgJDPKqDc4<;@GndptuR zb&ad800v{AfUmEkc_@c})9VQX$p$@fI@1mM;xVMubJZuHluj-s`!Ev*Qb!ZY*oSr* z^m()g%r)qPrXPso^uPWRH}0Ju^khi><_A*O_H+Xtxwlsu@IbqLg#k0L{dNPE)b?i# zSPt7iA_+=X8HkIlQW?l}afON$MYpO9qv()&KO?4UK#=n^1~O0_QxS6L?)G6o2hL(eh>-28VTq4IcNWk?1#;>E5bB zXCBsVMN74YRMh*vmJfKfhOAhWb+<~VSz5QSFt8!f@NO=WQuVQ_g{bOIZ5&#E&JbmS zJOQpc3O-M>-HXabs*_j@sua+wHw|fepWW4FSy;rOg}3Q*(c~)LSlrv^6F4E_&(S7y z+q}X=p;YjA$af`fPBC*zT(=D=i(Khl>BEOHMNjn1grgLNapFS-7ltcC ztG+kIp$|701$6p=CP`&RUy1C(B-|*oVCw({_#;?DN88yXw6ccfqe|pP6^+3SLF;PR z)RDLp$kT0YcCGY*t(TRe4M$*DOG`D3EOCR9^IC;wm#1ZAp|412gML6>N{GEV+$)N6 z1R;+WMjM>QY-#;7T6C~NtuOF(fQ{GzADbsBpCY^=?vza(F;55b*Uln)!JQ-I(duM4 zDOMUpj^N>f0ugycW65Yrwt*XE#?qlATWx+@8(b8&L)lily|cyB*;g0>7NHGWOmWf8 zxHH4v=n8uwk?_%ZY#eRd$Me|o1WJyObgi_4P5FTsvedGPv9e~0g+)RMsSwSpWpmJk znR=LPMQM#_eJxuuErI}+DmFr(;O?}nwtGFkLaK*R!zErUwEFux?UeE;en?$K^-F;Fi@_ED9QIV}!wArpTY{`D7swF=m#J0!NBNp$RKK$7*}!qLL7h zv^|$r5LBlHzY;G6Z3)$l-gr!#j_wn<$*6LsUXLFAg5lBiW4S1_=_|bnxm-qLVsOK& zz8Q-FcC+m+Um>xcEcEjNqscU+BDANQPe9T8^f9RElwO0*j^z^2rqj?hx2Bu4sCEq( zgEnPzSri84btw8(&P-qTW-(gSc~+}OwO4U*=&^2|qohu+;W%`tR~L=Of494?W(-g#1wwp7Y5D8|g?Q>-EG|KSub1kic$KCai_ zZueSoWFxHyZ9Qxd(3UxzKEUU4U#q|=(7%h8@Jrj?E1f*YEwtEtb^*uy89NuZnmS-iA=my@`8X4 zNn8@jsOCz>&1q8_XFz|8yj}KUOx-Qm1c(!K!NBa3nLtNRaVddy`P>o)#ct9i^j|0e zzpwJ*Z3WL6HeiY-*xTBm4Po%Gp%pgqE*w>Z9jFNW{KdyWdqogWFrzo-a_NSkHq7V~ ziMwik=#~5+RvLDs;H2r86zUg2QwmRT!fugt94o5c!KFt<5-Ju@v(v$^n-FsyMhe@r))sEe(8M$vwpcAmf(|I{lcIn=9H@+69Qs2KN9Y zLAZ_<2XG75n!0Tc7rxdc*x)4?s~YMmvOJ)G51L6z`p~)=+(}LzQ3{|pHLW%#1Xj-E z1U``zgsmD}S2)@pbqpUH9h%^R%wPh8EQgIL{e&3K!TWq}zpF1)wXfaLhQ-_C@V8@^i=8o^ zC;QvMW0D5Jy#u*D7;bm_x~LELhbqQ)4S!xcoFc<=!iVd{jyxofgdhRDh=bna0}BL? zKjsll+BDE6#)T+n7;<4-N8wrmj4Om79tVUjA8xDs2MmF81zS`l>hOFPD51SATr&D{ zqN)sSn8r-uNJGddgnm1X5vc}Ce*?Js3d;OQTY!Xj zRMDvTIyPHN*g$1xv}Sbt@7j^53IAGfgDL^F&tOKzU}N%o{BWI%x&?G*29rLr0E6Ld zV@10^0-k|Bp2^$*YqFURIKPJmgImLhq_E>5{U}%|`fPwJ=wB4{=0stZMPXz- z=>3}uF2%)GP{+ZUC1GYEUT4vD*YNyHufT?56Kc4~LJqxtuRh5ndj`P_{j3o6Z!l)6 ziqZQAG|BO12y1X)2}T$mS#U~+kEI}E4eL@^j3q}6TZo;BHRKgt{`yPxgH9l8uat|f zz0ltKnRwLnl`e-Yv|{CjmM}HwP0+U4%uG5(4mzZZEv}%tgrdt{T%oc#Ol}Dc$%ip; zg)i(h!8}4MstAN4)Z{WIp(*p2q&Twhyl`=~^b(7w=JB}y{d;SqxcRIYLyAW%45jm* z#!U**{I`}v=$ZL!CGq(|zQXhrS3B4Q&B6kEr_0u2kLbeSEvclyOT$)Db6?nTc7kUP z_4QES#e`(p_79bQeL)Djpiy}>6z;H;pJ~|D1nY;}!aiGfXv`&jd`Pv!-3B^Y&BVoo z)lVlL$mTL84q3Kr*vBQuhA3evV26bE&ft<0gB~U5Xso1Kyh)XmN{Zl-`GRqQjLzuD zL0EpBp2=z%*a$-#=5Pu9K021k(*~>)GO_hp!YyCq363O!4MsmNnPb2nMW|%BL2%{H zBFw{kCou5Pp(@mj;L-)Q6J1@9>1hL>T@qUT2*K#TV!`e43!NT3^g6(Md%&}M1y7g1 zvkUF}gezAZsL;0Q%t92qR6RORVfN;OZw|S;Iy(EnW?%{mRimn2LlPNy;)AlfVDL#S z2xeVm079?Mg?U8zov@t!PJ%tch#p*zcO3Az4Q=qat=P`M#C+|xPJ2ioqyvOq&E+gV zLi!;qP`Hp7oK=HWxY6<*oI!Cda&ILpd4*U`lX~$5iBxki5j`>9s6~IdmeXDnG_!Dx z@(L5?@1YjpK0#VRhioW=UaMwuS!z3IPn9uoWJEqJGV$sXdz0cYU0KM%mME+b(7s%K z?!?P45jNe+>N?NYGJS~(R)d@K;d~}5>!LN&2|n8Mp(>tC?2GFwiYtm?Jrk0UyyR7& z&IL9t;1|#;7Bt!iC{N|TMTz-Lye*KT}kF-k-eoLyzd^-1uEA>xYvr1r-k+L zb#~6o7s#959&bSf${x$b$MQ3WT#*nR*OC@6#UF<8#BIqJ6OCA^c zgo+D5>*%0B0?P`43r!nn6YXl@nl7i=v8~)oSdR-)7HA!fYk^&_4m+2N?rP!wN80N( zp^dHF9A*{tzdtS#;KmX%gG z!olb2aOiGVi5`rXAsuqZqtX?ek)H2*RpMP}`U)GGLnVHU?uOSW zLgcJUj8g-V612eu?4DWyTQ(#kK`mZ|RPDiHSF6RDsJNXIN=fc)wP?k~l7{iv20^S= zI8l&Uw5i1%Xl*-}Non4t79Yek^P z=ErLBYn(ZTO5qC!mq|(fT`i8pF*<}~9D)pEj9eyx5sPtFJ}q-(C1-*iAOjoBw=iNY z&L@(MM;|RTqy)1TFrpV{jiyE4aB``%k$y&e1f6$s7Fzqy81Z9_H;Up-S;?i8Q>`(g z4US6(Qih42nh1^ok(q4Oh@;W%E4f^bl(T5Xr?hAtNCyGGX|$GrR#fAt)l9IXERITx zWyL8d$HnDRzNWI`JTx!#3NzHrXswGIO9^ac#kVnmELjpRE{aBcoM6Rx9h~Y;@o+g5 zlB5$K#*lw{xO__bQJwe>n$^KgrmuJD#e2|}4sH@9eXm~JiGu*gpt&8~7?58H#CM8F zhGt=CR#2*60d0(H-q8uW$x}MHXjyaZRY%jj;K4L0aLgbcg97A?et01oI1uW?G`xZ60!KVl zdbp(Mp-dB?956&Bz~Cr^+dP~c6Si{&CkLF~v691qu-|#Ov}6W_j0*Rl-X>C?UxQuw>>*Mn?ns> z>hsdbu9L6D(b;G5!CD`7WjZ=Na7wkZ)gJJ5amkump$4X;FlDvTop^^Ee-PVFF9g6M ztpjhG!&KEB8m(}|r~{THu+xAyCqnZavPQ9RsIa|4rai!~v3}SQfhqaYVxbOZEKtcpvT=rQF?jJro$Ns2dkwf5cw+Bxqcg>t zc;nIty2rP0CD1ik)&NeHd@ZRGjo!?qqD5R(Y+eMW1=bRUbgQ=)_A?1?u~5-yS%mgH z$|s@sDvY|xLz#w|)|!H)1rE|?SAb8q>a1wxFQA!+X2TI}!VWlUdZ56Ni1%WR3x_lG z{%+WU|JA)*3QPDXCwySkya?0?UVOuN*)XV2l1h(giHx#`^Rtlf6F~`Wc#4UStMT** zqX!k%`I%Z_YDIDM@xVl^gMuMX$(FRyE~==2m;!$R{QKhQnEu`1PAG-We4HE?h< zXHe(U^&nZdgo~5<$ySh@jn1v(l1x}XcspyF4F&)dJHQDl^NuHBZrQ(^Wl`sBE4n7(wxtMn*(y0K8&dNvO2O;mA#M8s*-Tv(dO zJ=d6sO7G@Ox}Xdz@8*O^jK;gU%G7X)h`wD9eWVdJ)^dgD^}9Lu#gM>G0yFR7^eXg^ zd%!7M78MET=q8AB@!ZGF4*c?7?n?$u+RZf~L1gqvA-80ObvYc@VJ`-&G_)Z_lZGbj z;kXnGx8mLf<}w5uo%za?fXy3i-KI|^KmJ95qi<;vQS>uREJ411H#Zi2F%zZ(ds9_f z6tkUY(HFb9B^q2Kirxd`=*m6ZbTn@lmynLn@e7AkKa|-d%xnhwVGkFjha)9Rhu!8z z^UrCLQ2z|0R*)6dSPve_-itf-P+F*Jqk43RL>4-?jB ziSY`3#)q$g>(L0c9Z&2#V^q54naVmzCV63NMe1$M3=S{DMs$poTKB|eLDV#p3-?wEq)4x5~QrPMtSP_xmx@S+6#o}?Crc-{1S7fYJ_gv zx!kCw1iw~`nRsekNC-|@ZcLS?_Y!}tW0AoWU9R%=YOmHQa+Wf`2z+vTRe!iZ;gEHlb;+|L-1 z#j%XQaT={fuMvwhNVUwEX$mTAv__nv!I~fyYvVfL-<6;>%+iQ!@Z3HfSj~`SvQ8uJ zL`Rny(=;Eb;Mcij##Gv_7d7HJvJjB&Uza+X68K;F_FGgfJ)45lF4nz z+8|c9!I+dpCbt)u^gcAH!I)2jF}E!?;wkEF4aW3jf*n2A;fAY}B7E+Pe!~#vwl6jq z@%4lE8{m|KBxxEDLK?+|bwR^|2QJVK!Arq< z#Pj|lt5LqY)?ZH=?XntEv>2xgt?GoK?mj?JuXG0vT8-aiqjVgQcW#YIhh}UrW(Qu} zVEm0*2M3HeHY;$$O~yZ{(V>k-1KPULSd4#Fp!J&=4VrtaQIEJ=jmgLz#UzGc$$>eW zj6Z0kBVV$~j#h|gYH5Y|6qr#J3-~Ei!XY)veozDJ^B%1>Al_jtQZo=+hqANSguv#l z#@b0~__EN*>7hg9A$I~)hmF~!XTbHKZZNg%qs9#C5_`p5H2-kW@bXpSG}Hsg)KF)u z#Fc2zVPn$xmDsb5ba{H(;asv4J_m&_Ho#n3wsDV2yp#AoUk7Zb2iL;eRj|@Lf7nO^ z>BUnj@o(5=o;hkvEFy;dwMxvzPRc~CvB9DSD7u3kHeW5yz<%g@K%Yaur|XDM>6l0`M6Il?#CELyln^I-L2?Jw;>(!aA!vFvA@_<}{3AvlvT!`1 z7EfSc#FZ?9d{Ql*1UTt)hLDtTN60)%y2|9E!~$(cjVWM{Yal5i2Byd?$zg-S+J_EM z8t*}=c#=1?0sD~g55_cVjQHc(fmwerifd?Cdu(+Xup1+9R>4B9+2L~FTRsr({glXO zr;{*tTeT0cc$o0O#;V=lI@@e!2?IcE=g0XehxgLm-0CUEn?&7sFIA|H9 z+L??v6XQl$2GGo&&tpf46_~1|IqW|M#z<8YOVMNVL1sVy8+v&@|H!cGL>pFdx1cW< z@MEuFWshKGzc294LjDL-PL}eK|FD!L{0~c!pCAo5f07sYRlRm!;L#=ggjRtgM`y#o z&le7LMR(l93r6{ybohIC=;@pIa$W`q1oGFL_%WtPh!2(A%xC7vpx{^Y@G5-RxAD-v z-x!O~eZS(qMSr=OM?=Zpc?+Lo9!i5oTMQ@i+AVx>Tx9(a<$%BIhxY6K0l{B|=*$=TB!ZMdk^G*{VJPH=1vvSne*6;OG4P=c5AYS} zod@^_1HGfUC{@rnY36w|o6tWO-xvYu%NtdZvh`Vn84!sDyIA-(2fnI;wTYKjLLr!A zO_4=dgu_|^CA2GtcPqeudi#P}B30EpiUlWL6+&POoNK!vXvp3PYkR@p5Bmd=b>b?9 z5QBRvfMLg9sul`?48G7(By_`zvsfqv7Ur}O_KFGZO1M&kLpmH-tWL5UM_=J>C|O{n z5)QNADl=voopSNH$ns;}8ekvhdsXO%r zLb0zvEHJFnb&!imlBKTvQi^O*j5(3!L{Ra8K%D5zN2YibeHARruW#UDvwNX5?6eJy z|F_WNd^q_O9N@y#aXEee0?pZoR*lr>=3Sax3GfsoIpvZh0TC*9Hd4=kg@yk>Dk0mm zpsd@BnP`0!qsi&54}Cni{eCp?Pkk^62BteZ%pB)dbOCd*SHs`GgE?ImI}- z59X-!guhsTO=N6^a9)}9Gv18;_Y|MPz(f}Au&U$G?#KBIbm%y*Ls3uj$>{WPUXRW^ z!q-T`)0z~B)3m!Py*arJU`A^y*X6b5!rcy_j z_&7mFeOY4>TKp5fFl4*J$RQ^0vV(n+2I}A^E{1GBSH+=UKFwD^%fEY?zXp=BXZXpv zCFNm%LiH_x3P5zE+DgjI(NEQJBa19JG|@_ivO?!IaBnsFhYGHosV_HX1g#Ed`_rnk&rJGhF@`J5Y^UO z)EFo>n)IfNRdrLcX%emUaI$Fvib^q+Au-i7675Vj=}}{fDHa{s!H-1mr@Ul4ShM2!1v}y{3y-YNMgDCyLpb6|vF@61Aqdceb^-;Tk;T;d5a7WzYZ7D41 z#TA0>5k-+3Dp$kx0Ia@Yh<%EP=)(r?Vf0obHv^(o)0cBTRVmuGocka2tHn%4f8^|g zUdq7%HAH$vMbtH5ULrqd>Pq-g zU?=o7=L^^wA}N_GSe9X~Xn!t%y`-Tm4$+4NhvC6zq3JB}Vj9eo%XIc(LjVu$=_#ab z1$(vFd*Rp$B4+}75~5V<$!YLWS^S4T4hG-;g42AsiR$&@!;m%)U0_$2R9_2ApqPkE zkF}+P>`0B`xRdqFBMZ?U0rQPa=lQS!x!pS6Rs&9l$BmHtsGX$^p;tW)h z9F>Oer(c&Gl}%f6YRzIOlzEXt!EbrfeM5sr zY`}YoaPJe&AA;RfUN6Zf?-02_aA14>GgB6PGlMX*nkuhwNlt@KJciHY zO>mKip4Q@R6}i}Pz4);njya+d$YzlEjb5Ay%i@%%bh^1Y#~|+Ips*lC-7ZAQg`VWZ zvqsoBv8F~P+ejUs8^t*C*&0$ie3D(pOfiY&QBXX%Y$nK6QDPMU$;QbLcFAgaxNi5M zhSVte<0yoSbb0qqNvZqL?$jv!35pj};p~&p(}!6i?>rSPbs2cK=I^Od@;2YQ$x+Gl gOOqFoKOu0L>L~TgcF|xGAS}VMY|EB~H*6VWzz7J79Tc_} zF7|!TVt8SqOp*aIlVq|7W+n*)FgP=l$;%^7^3O|VhD?(GR#i)0XgF}r{C_w}mFl~< zZq;4tR&}Z6Lz}ZddU2R$b-<1T`_F26n$-5elF5{)wri#7rZ}~I#0#~i1~qH1vNLu` zicB16Xi@j*F?rmT&2RrHF6nt`equIQcF#t-BxaOmKJ7J6%|Vh zQ?jMTq!6hhxxaKSDMFPkRVJIHR}-V9kty-2@ubzBoTN%8pZ=AYsmdUqqLTH}{^Ter zI3+_y+LQFs-lP=iNJ?+^V;IzNReCKYnST64x}6fOYLRrQW7T)mk~uX_{j*vsOYN=x zQ7vsqov;2uEw!bFM&ZdieuSdN9pJ1itnoB>90Y?-J<}rk{|qGiGDi=lM~_9GG{+ri zx^-oxHBL*Z(^l@0Jn3toOPa&SCoM=D9OP?|PS8g>kQQFh6=ZpdNE99kecbhyZbqPD>5;GxFD=%HTZaTsY8M5|z0g-C1qMY-_g-MqD;&|XVGTKtwpAq3U9R0@+lKWT3b?FsZZJX1m)?Km|P> zNG-zZW~;2#whAYBM+(WZ7u6+PIp*#d8L%rH`GO=)Ink^&{Y?SZLNUWpNJ=uyQutU~K4eYe234a%0aOMN&Hcchja9`K@+<> zI{1FdJeZ>cA4bG4=V+SZqw_mbI;4DCSxvsjcfMex>>;sT7Wwr1srDao^;9wjP3!|; zk$*B|7(R3N96FRbn$jQ6(al3=cX#xp`>FC^j?Q@)5x<{+nF)XGddmDzQc5&?L z`>FCDa%@8<$3}r;Ul^W%9sAsH(<3xjQ-+80?4;}=-95Yfe!4uEXX_qD#4qRBNb1?; zBf`7n>RwV?Q!nLQeeQmW{fGQ~mW+XO^}vxy*u(QiM$@HBDG%r1-;SK#-NDb_Pl*R} z@G}o1;+J!91aWYDryN~XR_Sz>R+Mzg(y%>ChxUiMI(9{J*Fbi~FYc%3f5_i|C1W@Y zjm@%eb_kj59ep)_QK-_#7 z5&ypef^LGrQ!9!}3vD$fYekXCX)P$TNh`+k(}{8Kruj@8p}Ehgth-I*gYQ>k)4H2B z>|w+}B>Ep$J05v^J&cI5&N8}Rg*;%ObQXbcWNHg)+<|a~WT~hvx4`93b*YVB&}|<- z9*+AtL1m|V6P+|X zXKf;}W`l=xwhtnG%y4Pdc_itpoJUpF(%1=kP#%~t7s~G^%!6{~#3!J9cH%Uy8qDNQ zoGs-}NRmFD7#=tquH0rg;j)eph9S|a>MdC&;Z842TEY@^D7s~3!la3lF}iBi)6DSrx!N(-1^txu|SdrCRw94?)m+8Y=bK=(gPoeyQ-X$zrj zoHhr_)@fEK$C@#|+q?$K=;`?L(&_R*Ls0)GU=n|yj3{~$ zus~ToV=;LJT2K;&MdMI1xZiKS(zye zXzwYg?Iaf^Wj}%4d*+EX6rJRgSwq`7V348P^RN=RdAle!QTo<4e0!czdf5@XJug7& zpQn))S)wU%2NTyA8@G zN}q=E%hD&ItZ-ntKaq0tV(dJ9*&!&OFOwZKT)H_YUAnM1SlT^RkVZJ7rKih-fMI_* z_P42`1j@z=?Bk%yCMc7taQS@ICMdI)G(&lL2_9%pHRh?T!Jbt)C4od=f{351qyZIS zQgoe8I`1?A^`>(Xl%s0rQ%j9N0~YWR(ywY|pAScuw+mrX)>51uHZ8^D|9vT5lQZio zp}bIsS5lv4xJ1jap@e!|y6Uk3zN;_i$;bmC?k(Gw_m}oA?+^I<%a=eoW(AhevI6&w zT8WKxYUN@&i)?A@(nRT2U4%5ZVHgm$G~f=ZRk*BKHH$8$jN($Kw6#7|nz5RfZm${$ zv^W$JKHapNk{(B@%|fIkZVZ?5o?1?^sZzhjL};c->6<11 zbH%0!bmo2VDNI`BPM7|=DFq06Hy(1ay9~-J?sc^HP}H{H5GLJxdJdq2Hy1#;bMtH{ zzuJt`=j1KeVXtf{aoK8W-D(HkkUt`hix66m_Dg#Jkh{6q=-R0+JH1m02t|LjsiKUV_(TM4|a1b(dq{vRdqJB`b? zIy+hKpMKU3GymYnIx+sF1gcmCkpW5|2cV1QhE76xC02tU?3hxJAM4b+ml7DJ1V#|h zMNZZoYd%_uHBJdkPy&fRRY&{2TA^K?2h96 zzex$)tORaT0zH1PLnGwJ{2IADj@@^o9>+c<@SqZSLq_A7mB4qD!1tBFORQ4<|DzJ?$4cN;KiFaB>wc`0 znQtnAp8?qSuKfR3CDtzpDCO<#L*ETz=@AvjX}h1lV-DZ?FJ9pzQ za!~#8ZUVu3aK6p2>%fd3?_?BK3Do&Pt?#}PYpM6aE_W9^(1&-0gO%Y>Ww^I89Hj(n zJ&ss{OUC^a>95TFh%!7x86K_-k5qG*pgfq<}*y3r~;%JK=6U+#kThpb4&lZOc4Pc*D=piR^d*I&6dhE!YTeSJl|8 z)rEGCe%Y_GqRd(VUjY-vjsnqv3;Qw%t+Ue2Lt#N! ztSozj2P`3J4-cN$3I{lNQIlA5s{^-y|5g_ex1a;&!gNC2THxl2%8EcaeZ9}SrlrP;v+p{f9GR9X}m<(K>urTqsen+N%XQAUowU{2*K`$s>O3CPml@9xXl}_`Hl}Xi;ZnIc%CA-ms;_P&yvkI6# zc;Hn9RFOjkObl*cgmxzB@ggV2>bee8RcI|Mk>_F3iEm?aqV$b9iGjJH!G+Yu3ks=C z*A`NpPZm;L{~)*jDf7h?QG9X{(;p9AUqpSiyNKHGExG=_h{}n!F{zkuqFh(l=s3+b zs><(dRNhxIJ*=3?B>cscUR^BvqL@j~BP!Mfinjwn2Mv8I%#jH}XU>wbvQn_Ttn8gY z@eXFx;@Izm{}3qt0C+84%swGF)1sNhOuVWE%`9OO0tj%$%9!YUFVE3} z?$~`3d9Ij=qe4~|Gs&u!jn+~I{txh4OEry^s?q4nE1FnrQU0oi1WWo=4Ov~&u4+gy z)m_yL#Pnz6_LZv|68*YQHA65y?o-VGTsuG23?_V^(tcNDT)3tgoJ2emsS)47Q65ZR z*vqn5tE$TCE!B|VuuD+UH4Rzcjn_0Jc3!@wA?xWc*ED2(^VcpACAcMH?LETKEF=o@i#OiPxQM%HOsxBG4W(ZF0Hsvi&U+eP{TkuDh_BxFNHLZ zkXgM5y>x{8W39+Ew`#&P!wBJDAOsa|+OS-Bw z6x8@v56b&Y6Bb2!j4+5Jpa)q+{$4F;%V(P2suu6b&orscc<9T^*f=tTIoCV~1_;Ti ztSExrZnmw)nPst*R+Ks|7U~-F4ahAeS#726LOFRfx@q566i+n;vp1J!gFn+R1ESR1O%E*9R7 zM5kS>oJ^ixPVoN$#R1QKhD-4dT+MzJitQ8MOw~6xvvKN7H7aYS_C(EKC20S;nT;Mr z((+WZ4U`NVH$F$SIj!LD3R|7u-3{i|Kn(H`t8FFln+aPrSxLc&T6(x#=Ob#_b%-UY z;W@z5uqDlh%tt^9CrgoSSVcevKn!^AAhs9j7I=Y;#u{W^pfjF#fh8w{br;yaBx9Jj zn_mTg@4ZNeZ@WMpXuQY{97-IgQHg^fBHUcAwK}J=8fHrr4J0UWS_g$>@;K@IJQH@t zu8V9M^;G@^HUW(K#YMI+1>6_dB-zTS@HH6va6X!~ll7v~R4x>K^bHq+P95XdqpUPe zhcv%qA5o=xUrysZD({`w*{VhA%WbGEfs5Bbl7($dO5jM?zns94DEwOjM;1(MB1eu( zGZMLB*a(e@6u*$jk>kwuM2@82pA$Kfj+2up|C}U_EI?NhN7DA$B#tbf>q#70s6Qmp zanh1Ga*Udr%;6|qlgy<;bt;*Q;fW<;C+AMcL8{Xn{OAUKmCRuq1f_84P-UlZegmve z;rgh`(b*L4eX9C_RPHOP@JSWQ?ZeGP2m5f*XhsIdp-UNDR!mjBvl33mqerFoHC0&) z7h6kgH49T^6lG>`@#xh)9Pb_9hkK+RYhHJh>q}F|Y_lDlnS|Pog2ZbH9IquovMLC42CZ03t5hFW-R;JV_XxihaTrf;=1-YXQsPF zj!G;*E01%TXv+ys->rM#32qu@UwDEeQ~dY@Hww2yPjX{$J@+I>Hlt-HIg+amo}^BA z_ayfS(3?+jB<1xxMSWU)iuw+4l0;uVMSXYs6h|^v+-YtQ*nReC4rh`zr?~{*xue~h zgroJt)5LrKIL&1NL&`JQOCEeX~EMs2T1vV;xhPvz~5lO@3q ziBO(VE6+tRYJD;4{ew~a`ghn6I|FoN4R`}|MC`Qy9XVY6J3vR)Op1o$(=rXT~oS2$f9a(ZIEbTs-)nz0SyX|Mh$N4BC4}bu4K&vCGdkLo_0kn(Lk?im$r%RqrhI&&YzK@S@ zTHjE9ClR>g6aWuAf7HN#vbj3(<8_W^u{!zGe2LTHU8PQ|!d;SLs7+{J5kCc8FtK_Ry;N^N2j1r+z00!sOa^^9ijVV-%HiMbZ*4zJa{vy+fvi0v;0ew>^XwV1ec-CuL$Zuy*{ve$W1zY&bNb1e@@~ZQBlivHA zHTD<7!h2B-79$z(!*+Qy$o!*=qa(yl5!TCkI!j9Rzz3FwWT{GU<( zqr4uqAl}SiR@F{^C|b3h?}fyjP#oFLk3ffZ@=47S7%JMsFF<{F@x9T2!ID)B0zNdu~*d9ve)a7+t8 zS$p_FR2r)mlhNWmd;)Ezs>PwGc@J-*&EaY>7hTxH$I|AbYH=g_+}~_ciymay%O}v8 zAhozp4Ks;E+xCJay$_=A-+Orj1>aJOpU7awKHflkUsa1=pt1Y-A+-6WT4a!GAD>K{ zEF;FC=l1cLR6-mhj$=^2Js|dneS9?K$zjAoWZKUUq*J#s;x2slOr<(4ZPA7V$rInp zh*vQwgOX0~=Od_yYmE3PdT&1jDN%4vfEW$SAH99V=dw7Bcnl|xzO-ld0X~Y(=%hyc zy9QYf_+0%DjW__gp-Ct62rG_-D-L%I=@)4&a@4{PXKQREy@9*Ov*IdDm*xHha%smk ztoRlt#K{95%{u5akd_nYBG*Aaol@s>;*;p?L4FKvrf9`9^sj^bXxdEI ziWz9^A$~+aGXCT`#HUcg22LD=oqJhI*`4ud#4uk>R}$I%(lZkJksN;7aDtn52l-R9Qx@X zAIISBY55U8je=2lJ>Z@D%_F4i{~Y0?@cK4F|1n4T4Dy@nTKZcb)OeKdt^W02@geh7 zly{8J@EY$c<;sY{JSdD(jH(y|9(>lLQmc1H#EP&-$Eb$j%U&5Z$Nsx^#-Ki z#5Z}J8o5jPAauQ*&qRi=`BZfMzqC9W|26C&mUdq6ee*4TfC}Y*rW3q_-{Bc`*PS8U zJNA8krW#p``3Q94L;fi=dbQBsyZRCzuSUljg)sDwk9Y$fVk=tpN4^66cPT9YUVq|$ z&@Q)FtE;W`>1fs%n-`kj#fOQVLOjjtABg?Yx7&qKx=bEXiQ7@2B!ttZM(uDt4hWIy9zid!VYPS=Sv`WBIS;GF7jZLGx>X;5KHM$n zY2TOB;v2ND)ZQQn4l?!MtHrlvFn^UGZ#(a*#Sc->9YQS4NSD>(Kk=53hT588;MKc@ zFgoxZwKxM+?GWVTnahX;kYrKYE+LXK6fxpbbYX`eUn?zRU^fhE79x!0h2-W8^57;$ zJcKcMtRsy0I!@G4c&rG6pY2UXyoK4KdiwUF&lr)x2T00kgg;+EHPQr#aS&x5Aq4c- zbQ&o>K%9fFHw%e0)jb{{F2(1^Hi(11IGc&DstDrll?&T^DS79=%b6Qkb_R&=plL`j zr4sAC7a($Yb1-)50dE@0Gtp_p!Dt&2BIMkv5f9@_wyhR^@y#?I>X$3^u35|FP zOXEAF(L5{G2T)3vM0-vno&$FJkl~9wa_|hItt|W|WnrbQ7);ZGEIWlzUz+vDKIG87 zI|ZDPU)w3*$Jf@Kf_zgOA?>S+c2|}pdu*1W22K1sS|kYu1;;OkB)9O z3;4R_{4OC553)*pYiCxZv@Ue=DhHR+N*y}xU5F`li|d?{P#jC$#*w?Ck*y|(4nZ;g#o1X zQ>vatkG?L%qFYUBIAF&F#3F*ZUl+o{7S`Cxin9tTE1fmYYHQUZQy=&dMJ>vET}bN? z@8^$3b3RcA(G=*H5!79V_weh&&jHQtjK+KYZ6RH)PDn@N{>=75AN-c%yb13K=Fz$x zt!sObf2f?-N8kspMqW=Iub$!c$uu)A6I0O@ULQl3c)CiQgnk01coM^Al~{pKvAPLX zr*#ti5eA3|a#ZLkR-mzhK7!t;SF6Mw5{z&JYD)Bl-L*SLyP&pUfREhsU zd!b_rVY#CcQ*kabSa5Jx!PoS*YW&L_LQGeSQ_wZwrBj;*XI%87f6Rkw@jUJ-EVWi! z;JZ%vb&9X!MKvtzEt~YFAwVM(*!^3VRyEv}Z`JEV1QJjYL~+!% zK?q@KC?l1ikBue7U^ocaOH1rk@J6czzC|Rrf+XTv1wFm)Y}V_;LI^YKvkjFiZQB^B zA!`F20OkmScGZPI#CULC@;-0Sm#@GsjA_!7%fS&%)RlQn`rgr4QFE>N_n?s;|2>y# zk|}VifF9eM^yI1k#U?$uUcA|)CzlF_r)WLmDLr|tw?3s$UO-H?O(nKq*L9r`A)Qr; zKVVXzWio`ay?aX4s6`Ij)hLs#MMV>fO6V6Wx1RFF72Y^8mrqD(O^*NJ2_|u? z)`EU?>u0L3yn$vstv`uQrg9rl(`G$fjFQu<7j4mBV!XQ~{fHv;O@=YRd(LFYoq_&Z zX$VA28s8KBbX6aR`d1o$h4ShRM)c|`Ll~O*k(NdMN9tH_NtNM>-cVRzsmOvy5exiX zqQyv+1`k!xEfM8k)9aA4!7!R+DAIbR!7zffzHczl#Fe_r(1#!w|DX>>xbVUtJ^zi4 zE>(wnBUc;$qEbJ@G_N%hBgd^ZMi0iuG>92X0a}#kDI7!tuY*%t!b?>Y7`N%T^v9H3BSn>b1%2m*vQYK=;|LN=M)1Wmsv~j zi!d~v+twP%7bNVHMiS5co-~s9ehk`Z#yVpH{kA)k5i{_k7f&R>pOC5YWu{D4Jk9~d zV5zn(wN=;HNa~Rz;S?wSnnP#T8AEvzHg9ucIArv7#%Q|nM{312@Z~hRxZWr~9In%e zukau)M5=O!%#g*L=f%GW0BWgvHNNk*zZ68q_k~oKnUUq*U0e9Fb-fW^PW@)R5nogP zwB8sqhHwVnWi|qL8jiH}5E!*p;1GDhewm!Xf}S+S#1m>rXKGfBb*Zhm6efykwfF~} MtkY9lTafjC0aaj>v;Y7A diff --git a/docs/_build/doctrees/index.doctree b/docs/_build/doctrees/index.doctree index 51a44398606712af0ede2958b2c636c90fc8db37..85964ff9a18186acf9d8056447b3ce20ca06c637 100644 GIT binary patch delta 130459 zcmdqKcYIdGwl~h6kn$wY-up=-bP`AiBq1d9B9PEKq4yFXkOT+`Nl;X(U^$|Klu;1` z3)lq}qsInT>|jSlz=l}i*yS92ziZ7rdp|qm-h1x*d++CdK0p3ovS+V0Yi8D3Gqd(Q zza5zV@pXl()*5TY+OW0t*M_f+SR1)EYOQZ=^xBxs{vQlu|BwFgf&STx7gtqQEh#LY zxp1G3S+3&2(PL!miXEjho(jS3acv%7Y>*=uV_wHWwsaWVAt?Q znS?d7vT#xP!lKGvxj8vGS;<^Ad*R|a3l|K2O{!FMAPdJb4rR8_oqZdS4?XBIA*U#YqNSAxhBOXFI|LpS-; zWRIc#e)6yG;qB$!_$xj3f`$a;^1P81o#PT@r(ynn$#EC9Gl;^kddD)W}b zWy*oW{heiEW2>!fI>KKpVxna1C1!gOg>t{Yg$$&d^W}=(e)~c_Y#bcfScGf1Rof#Q z$OlIH7aFOu@hE>68Q2pU)2`Q;>axn@ImL@Bi^{ZKk{6e8S8#VHYt1CjT~c_l?9)5E z(U|`hN?G!}C5sm&_b;p}9Jr)#QBn5hb(>djUcR|aad>I>D5G9+VrkbXx$C!>9Jw{m zzqRp&ot!?*08pnWnKHzTpZU+e!GTzrJa6%m8FcDp913%TLf zK;-|n5*lkIxWi?z8ZHAdp05bxm;>lBeOQ<~IEJqtN8K^6x@-<9IvHcBk~O_(@!X$vV77JD+c}^jB2gZC+a&;vJ2fA;5QI#BhNHmD#Ay!-@&$cm>CR93I@;}R{ z0T{W>o}ijN&fDxL)$G_V4N66El-zh-Vq0GkL8g^H8YwHjj~!(6mCyAL@9N_rI%i>F zrQFxRXuvj1ToENt9`m;sD>17^n~kVEcztYtaT6%{{cXh-wiy}n%<{+_aZ8lUE%L_` z(2*wohQ>;HWW2vw^h$86o(=okL7p5Ko}T3J36);Ij17GW$%${VKSx|1B?~*4t;I4t zw}macZcuo&IHHAnLkov8e`jEz_(}`+ISZF*JRprCf42Bqiw7_k?+q3&?2RZxE*cU( zLJ%3^^{SUwj~=0hJGo6sSykKQcI}c!Rxg@ev?Lh=gWh{>AVvn6!A%=qN^H*lCFsC{ zQ`M=Iv8n!eqq$r?8Liq-Zp4blKABq6E#JlH$o zV@M|Jo)aSqU-WQRm{u;G0qKUCUwW3@m#2G%h`n(m=SYs8v%rKT;*wQtsrSpMu z%xrJmqyXnDMIH9lZ!1R^2NkvZLiGC_^ooW4_QpXE`k9mU+Zk`Gs<$r0eb>QV-OitF ze8YeOlCaKElFp;&2X&qz-`Wz9Bo7~r?nyvrwuZ_6U4 z%Rh_!$!ZM5N2}?EGPlI;Z)C|`3!xOWaFIVNIG(ekW&VzY1S4AMqd&t4pq#zL8flDI zC}TV*6CISz(#$p%IVhuNV6g2xUq4cQc1c7#XrK9A>Oo%VAhQy-ILNF7@MR^$N9%#t zQl2e~XeD2-jL0RSXlfY&d1SFaoyN)8QoFTSiWwPewG~BC(r6EBGMguEOPQA%87bh% z4}RhAC`YgGcM=a^ZniWVh~v?6R}cT3nll6a+YRvxn*O=nRh*5Mi!SotCZ8ST56Jr? z%mjJu5dTARdc7qeJ~uMXLK;G|WF!ba0=KUEv=s z^4#bAujAw8j@c2N#7MU?wz1XDJc||=8^vL;s9`ZOb{*&zqomNQ2&E_VQX)

2EA% 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 delta 114244 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 x=y)uRI7` zJJ!urHO0Dov|HjM6{!UJ*i#m7RM{ynq~AFbU0bY6$HZ_@ksDXhhjA5QlUcZuin`T6 p^kwaCn>o8-#kk^Ssq^RDId59Sis;h2QaH;oOc#mMTQ}An{{M{syuknf diff --git a/docs/_build/html/_modules/tigramite/causal_effects.html b/docs/_build/html/_modules/tigramite/causal_effects.html index b88b016c..9b668b6e 100644 --- a/docs/_build/html/_modules/tigramite/causal_effects.html +++ b/docs/_build/html/_modules/tigramite/causal_effects.html @@ -56,6 +56,7 @@

Source code for tigramite.causal_effects

 # License: GNU General Public License v3.0
 
 import numpy as np
+import math
 import itertools
 from copy import deepcopy
 from collections import defaultdict
@@ -185,6 +186,8 @@ 

Source code for tigramite.causal_effects

         # print(self.graph.shape)
         self._check_graph(self.graph)
 
+        self._check_XYS()
+
         self.ancX = self._get_ancestors(X)
         self.ancY = self._get_ancestors(Y)
         self.ancS = self._get_ancestors(S)
@@ -402,6 +405,18 @@ 

Source code for tigramite.causal_effects

         #     self.graph_type = "tsg_admg"
         # else:
 
+    def _check_XYS(self):
+        """Check whether XYS are sober.
+        """
+
+        XYS = self.X.union(self.Y).union(self.S)
+        for xys in XYS:
+            var, lag = xys 
+            if var < 0 or var >= self.N:
+                raise ValueError("XYS vars must be in [0...N]")
+            if lag < -self.tau_max or lag > 0:
+                raise ValueError("XYS lags must be in [-taumax...0]")
+
 
 
[docs] def check_XYS_paths(self): """Check whether one can remove nodes from X and Y with no proper causal paths. @@ -1855,6 +1870,10 @@

Source code for tigramite.causal_effects

         conditional_estimator=None,  
         data_transform=None,
         mask_type=None,
+        # estimate_confidence=False,
+        # boot_samples=100,
+        # boot_blocklength=1,
+        # conf_lev=0.95, seed=None
         ):
         """Returns a fitted model for the total causal effect of X on Y 
            conditional on S.
@@ -1923,9 +1942,70 @@ 

Source code for tigramite.causal_effects

                 Y=self.listY, X=self.listX, Z=list(self.adjustment_set),
                 conditions=self.listS,
                 tau_max=self.tau_max,
-                cut_off='max_lag_or_tau_max',
+                cut_off='tau_max',
                 return_data=False)
 
+        # # Optionally estimate confidence bounds via bootstrap
+        # self.estimate_confidence = estimate_confidence
+        # self.conf_lev = conf_lev
+        # if self.estimate_confidence:
+        #     self.bootstrap_results = {}
+        #     random_state = np.random.default_rng(seed)
+
+        #     # Extract max_lag to construct bootstrap draws
+        #     XYZ = self.listY + \
+        #           self.listX + \
+        #           list(self.adjustment_set) + \
+        #           self.listS
+        #     max_lag = max(abs(np.array(XYZ)[:, 1].min()), self.tau_max)
+
+        #     # Determine the number of blocks total, rounding up for non-integer
+        #     # amounts
+        #     n_blks = int(math.ceil(float(T-max_lag)/boot_blocklength))
+
+        #     if n_blks < 10:
+        #         raise ValueError("Only %d block(s) for block-sampling,"  %n_blks +
+        #                          "choose smaller boot_blocklength!")
+
+
+        #     if self.verbosity > 0:
+        #         print("\n##\n## Running bootstrap confidence estimate"  +
+        #               "\n##\n" +
+        #               "\nboot_samples = %s \n" % boot_samples +
+        #               "\nboot_blocklength = %s \n" % boot_blocklength
+        #               )
+        #     boot_dataframe = deepcopy(dataframe)
+        #     for b in range(boot_samples):
+        #         # Get the starting indices for the blocks
+        #         blk_strt = random_state.integers(max_lag, T - boot_blocklength + 1, n_blks)
+        #         # Get the empty array of block resampled values
+        #         boot_draw = np.zeros(n_blks*boot_blocklength, dtype='int')
+        #         # Fill the array of block resamples
+        #         for i in range(boot_blocklength):
+        #             boot_draw[i::boot_blocklength] = np.arange(0, T, dtype='int')[blk_strt + i]
+        #         # Cut to proper length
+        #         boot_draw = boot_draw[:T-max_lag]
+
+        #         # boot_draw = random_state.integers(2*tau_max, T, size=T-2*tau_max)
+        #         boot_dataframe.bootstrap = boot_draw
+                
+        #         # Fit model of Y on X and Z (and conditions)
+        #         # Build the model
+        #         self.bootstrap_results[b] = Models(
+        #                         dataframe=boot_dataframe,
+        #                         model=estimator,
+        #                         conditional_model=conditional_estimator,
+        #                         data_transform=data_transform,
+        #                         mask_type=mask_type,
+        #                         verbosity=self.verbosity)      
+
+        #         self.bootstrap_results[b].get_general_fitted_model(
+        #                 Y=self.listY, X=self.listX, Z=list(self.adjustment_set),
+        #                 conditions=self.listS,
+        #                 tau_max=self.tau_max,
+        #                 cut_off='max_lag_or_tau_max',
+        #                 return_data=False)
+
         return self
# @profile @@ -1933,6 +2013,7 @@

Source code for tigramite.causal_effects

         intervention_data, 
         conditions_data=None,
         pred_params=None,
+        return_further_pred_results=False,
         ):
         """Predict effect of intervention with fitted model.
 
@@ -1946,10 +2027,14 @@ 

Source code for tigramite.causal_effects

             Numpy array of shape (time, len(S)) that contains the S=s values.
         pred_params : dict, optional
             Optional parameters passed on to sklearn prediction function.
+        return_further_pred_results : bool, optional (default: False)
+            In case the predictor class returns more than just the expected value,
+            the entire results can be returned.
 
         Returns
         -------
         Results from prediction: an array of shape  (time, len(Y)).
+        If estimate_confidence = True, then a tuple is returned.
         """
 
         if intervention_data.shape[1] != len(self.listX):
@@ -1969,10 +2054,37 @@ 

Source code for tigramite.causal_effects

         effect = self.model.get_general_prediction(
             intervention_data=intervention_data,
             conditions_data=conditions_data,
-            pred_params=pred_params) 
+            pred_params=pred_params,
+            return_further_pred_results=return_further_pred_results) 
 
         return effect
+ # # Optionally get confidence bounds + # if self.estimate_confidence: + # lenY = len(self.listY) + # intervention_T, lenX = intervention_data.shape + # boot_samples = len(self.bootstrap_results) + # bootstrap_predicted_array = np.zeros((boot_samples, intervention_T, lenY)) + # for b in self.bootstrap_results.keys(): + # boot_effect = self.bootstrap_results[b].get_general_prediction( + # intervention_data=intervention_data, + # conditions_data=conditions_data, + # pred_params=pred_params, + # return_further_pred_results=return_further_pred_results) + # if return_further_pred_results: + # bootstrap_predicted_array[b] = boot_effect[0] + # else: + # bootstrap_predicted_array[b] = boot_effect + + # # Confidence intervals for val_matrix; interval is two-sided + # c_int = (1. - (1. - self.conf_lev)/2.) + # confidence_interval = np.percentile( + # bootstrap_predicted_array, axis=0, + # q = [100*(1. - c_int), 100*c_int]) + # return effect, confidence_interval + # else: + # return effect + # @profile
[docs] def fit_wright_effect(self, dataframe, @@ -2080,7 +2192,7 @@

Source code for tigramite.causal_effects

                     fit_res = self.model.get_general_fitted_model(
                         Y=[medy], X=[par], Z=oset,
                         tau_max=self.tau_max,
-                        cut_off='max_lag_or_tau_max',
+                        cut_off='tau_max',
                         return_data=False)
                     coeffs[medy][par] = fit_res[medy]['model'].coef_[0]
                     # print(mediators, par, medy, coeffs[medy][par])
@@ -2100,7 +2212,7 @@ 

Source code for tigramite.causal_effects

                     Y=[medy], X=list(all_parents), Z=[],
                     conditions=None,
                     tau_max=self.tau_max,
-                    cut_off='max_lag_or_tau_max',
+                    cut_off='tau_max',
                     return_data=False)
 
                 for ipar, par in enumerate(all_parents):
@@ -2125,13 +2237,15 @@ 

Source code for tigramite.causal_effects

 
                 effect[(x, y)] += effect_here
                
+        # Make fitted coefficients available as attribute
+        self.coeffs = coeffs
 
         # Modify and overwrite variables in self.model
         self.model.Y = self.listY
         self.model.X = self.listX  
         self.model.Z = []
         self.model.conditions = [] 
-        self.model.cut_off = 'max_lag_or_tau_max'
+        self.model.cut_off = 'tau_max' # 'max_lag_or_tau_max'
 
         class dummy_fit_class():
             def __init__(self, y_here, listX_here, effect_here):
@@ -2214,6 +2328,157 @@ 

Source code for tigramite.causal_effects

 
         return predicted_array
+ +
[docs] def fit_bootstrap_of(self, method, method_args, + boot_samples=1000, + boot_blocklength=1, + seed=None): + """Runs chosen method on bootstrap samples drawn from DataFrame. + + Bootstraps for tau=0 are drawn from [max_lag, ..., T] and all lagged + variables constructed in DataFrame.construct_array are consistently + shifted with respect to this bootsrap sample to ensure that lagged + relations in the bootstrap sample are preserved. + + This function fits the models, predict_bootstrap_of can then be used + to get confidence intervals for the effect of interventions. + + Parameters + ---------- + method : str + Chosen method among valid functions in this class. + method_args : dict + Arguments passed to method. + boot_samples : int + Number of bootstrap samples to draw. + boot_blocklength : int, optional (default: 1) + Block length for block-bootstrap. + seed : int, optional(default = None) + Seed for RandomState (default_rng) + """ + + valid_methods = ['fit_total_effect', + 'fit_wright_effect', + ] + + if method not in valid_methods: + raise ValueError("method must be one of %s" % str(valid_methods)) + + # First call the method on the original dataframe + # to make available adjustment set etc + getattr(self, method)(**method_args) + + self.original_model = deepcopy(self.model) + + T = self.model.T + + # # Extract max_lag to construct bootstrap draws + # XYZ = self.listY + \ + # self.listX + \ + # list(self.adjustment_set) + \ + # self.listS + max_lag = self.tau_max #max(abs(np.array(XYZ)[:, 1].min()), self.tau_max) + + # Init seed + random_state = np.random.default_rng(seed) + + # Determine the number of blocks total, rounding up for non-integer + # amounts + n_blks = int(math.ceil(float(T-max_lag)/boot_blocklength)) + + if n_blks < 10: + raise ValueError("Only %d block(s) for block-sampling," %n_blks + + "choose smaller boot_blocklength!") + + if self.verbosity > 0: + print("\n##\n## Running Bootstrap of %s " % method + + "\n##\n" + + "\nboot_samples = %s \n" % boot_samples + + "\nboot_blocklength = %s \n" % boot_blocklength + ) + + method_args_bootstrap = deepcopy(method_args) + self.bootstrap_results = {} + + for b in range(boot_samples): + # Get the starting indices for the blocks + blk_strt = random_state.integers(max_lag, T - boot_blocklength + 1, n_blks) + # Get the empty array of block resampled values + boot_draw = np.zeros(n_blks*boot_blocklength, dtype='int') + # Fill the array of block resamples + for i in range(boot_blocklength): + boot_draw[i::boot_blocklength] = np.arange(0, T, dtype='int')[blk_strt + i] + # Cut to proper length + boot_draw = boot_draw[:T-max_lag] + + # Replace dataframe in method args by bootstrapped dataframe + method_args_bootstrap['dataframe'].bootstrap = boot_draw + + # Call method and save fitted model + getattr(self, method)(**method_args_bootstrap) + self.bootstrap_results[b] = deepcopy(self.model) + + # Reset model + self.model = self.original_model + + return self
+ + +
[docs] def predict_bootstrap_of(self, method, method_args, + conf_lev=0.9): + """Predicts with fitted bootstraps. + + To be used after fitting with fit_bootstrap_of. Only uses the + expected values of the predict function, not potential other output. + + Parameters + ---------- + method : str + Chosen method among valid functions in this class. + method_args : dict + Arguments passed to method. + conf_lev : float, optional (default: 0.9) + Two-sided confidence interval. + + Returns + ------- + confidence_intervals : numpy array of + """ + + valid_methods = ['predict_total_effect', + 'predict_wright_effect', + ] + + if method not in valid_methods: + raise ValueError("method must be one of %s" % str(valid_methods)) + + + lenY = len(self.listY) + intervention_T, lenX = method_args['intervention_data'].shape + boot_samples = len(self.bootstrap_results) + bootstrap_predicted_array = np.zeros((boot_samples, intervention_T, lenY)) + + for b in self.bootstrap_results.keys(): + self.model = self.bootstrap_results[b] + boot_effect = getattr(self, method)(**method_args) + + if isinstance(boot_effect, tuple): + bootstrap_predicted_array[b] = boot_effect[0] + else: + bootstrap_predicted_array[b] = boot_effect + + # Reset model + self.model = self.original_model + + # Confidence intervals for val_matrix; interval is two-sided + c_int = (1. - (1. - conf_lev)/2.) + confidence_interval = np.percentile( + bootstrap_predicted_array, axis=0, + q = [100*(1. - c_int), 100*c_int])[:,:,0] + + return confidence_interval
+ +
[docs] @staticmethod def get_graph_from_dict(links, tau_max=None): """Helper function to convert dictionary of links to graph array format. @@ -2299,72 +2564,108 @@

Source code for tigramite.causal_effects

     import sklearn
     from sklearn.linear_model import LinearRegression
 
-    T = 1000
+    T = 100
     def lin_f(x): return x
     auto_coeff = 0.3
     coeff = 2.
     links = {
             0: [((0, -1), auto_coeff, lin_f)], 
             1: [((1, -1), auto_coeff, lin_f), ((0, -1), coeff, lin_f)], 
-            2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
+            # 2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
             }
     data, nonstat = toys.structural_causal_process(links, T=T, 
                                 noises=None, seed=7)
 
     # Create some missing values
     data[-10:,:] = 999.
-    dataframe = pp.DataFrame(data, missing_flag=999.) 
+    var_names = range(2)
+    dataframe = pp.DataFrame(data, var_names=var_names,
+     missing_flag=999.) 
 
 
     # Construct expert knowledge graph from links here 
-    links = {0: [(0, -1)],
-             1: [(1, -1), (0, -1)],
-             2: [(2, -1), (1, 0),],
-             }
+    # links = {0: [(0, -1)],
+    #          1: [(1, -1), (0, -1)],
+    #          2: [(2, -1), (1, 0),],
+    #          }
     # Use staticmethod to get graph
     graph = CausalEffects.get_graph_from_dict(links, tau_max=None)
     
     # We are interested in lagged total effect of X on Y
     X = [(0, -1)]
-    Y = [(2, 0)]
+    Y = [(1, 0)]
 
     # Initialize class as `stationary_dag`
     causal_effects = CausalEffects(graph, graph_type='stationary_dag', 
                                 X=X, Y=Y, S=None, 
                                 hidden_variables=None, 
-                                verbosity=5)
+                                verbosity=0)
 
-    print(data)
+    # print(data)
     # Optimal adjustment set (is used by default)
     # print(causal_effects.get_optimal_set())
 
     # # Fit causal effect model from observational data
-    # causal_effects.fit_total_effect(
-    #     dataframe=dataframe, 
-    #     # mask_type='y',
-    #     estimator=LinearRegression(),
-    #     )
+    causal_effects.fit_total_effect(
+        dataframe=dataframe, 
+        # mask_type='y',
+        estimator=LinearRegression(),
+        )
 
-    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
-    # dox_vals = np.linspace(0., 1., 5)
-    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
-    # pred_Y = causal_effects.predict_total_effect( 
-    #         intervention_data=intervention_data)
-    # print(pred_Y)
 
-    # Fit causal effect model from observational data
-    causal_effects.fit_wright_effect(
-        dataframe=dataframe, 
+    # # Fit causal effect model from observational data
+    causal_effects.fit_bootstrap_of(
+        method='fit_total_effect',
+        method_args={'dataframe':dataframe,  
         # mask_type='y',
-        # estimator=LinearRegression(),
+        'estimator':LinearRegression()
+        },
+        seed=4
         )
 
+
     # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
-    dox_vals = np.linspace(0., 1., 5)
+    dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
     intervention_data = dox_vals.reshape(len(dox_vals), len(X))
-    pred_Y = causal_effects.predict_wright_effect( 
+    pred_Y = causal_effects.predict_total_effect( 
             intervention_data=intervention_data)
     print(pred_Y)
+
+
+
+
+    # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
+    dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
+    intervention_data = dox_vals.reshape(len(dox_vals), len(X))
+    conf = causal_effects.predict_bootstrap_of(
+        method='predict_total_effect',
+        method_args={'intervention_data':intervention_data})
+    print(conf)
+
+
+
+    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
+    # dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
+    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
+    # pred_Y = causal_effects.predict_total_effect( 
+    #         intervention_data=intervention_data)
+    # print(pred_Y)
+
+
+
+    # # Fit causal effect model from observational data
+    # causal_effects.fit_wright_effect(
+    #     dataframe=dataframe, 
+    #     # mask_type='y',
+    #     # estimator=LinearRegression(),
+    #     )
+
+    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
+    # dox_vals = np.linspace(0., 1., 5)
+    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
+    # pred_Y = causal_effects.predict_wright_effect( 
+    #         intervention_data=intervention_data)
+    # print(pred_Y)
 
diff --git a/docs/_build/html/_modules/tigramite/data_processing.html b/docs/_build/html/_modules/tigramite/data_processing.html index 11366b61..db34d87b 100644 --- a/docs/_build/html/_modules/tigramite/data_processing.html +++ b/docs/_build/html/_modules/tigramite/data_processing.html @@ -252,6 +252,8 @@

Source code for tigramite.data_processing

             max_lag = 2*tau_max
         elif cut_off == 'max_lag':
             max_lag = abs(np.array(XYZ)[:, 1].min())
+        elif cut_off == 'tau_max':
+            max_lag = tau_max
         elif cut_off == 'max_lag_or_tau_max':
             max_lag = max(abs(np.array(XYZ)[:, 1].min()), tau_max)
         else:
@@ -269,7 +271,7 @@ 

Source code for tigramite.data_processing

         # Setup and fill array with lagged time series
         time_length = T - max_lag
         array = np.zeros((dim, time_length), dtype=self.values.dtype)
-        # Note, lags are negative here
+        # Note, lags are negative or zero here
         for i, (var, lag) in enumerate(XYZ):
             if self.bootstrap is None:
                 array[i, :] = self.values[max_lag + lag:T + lag, var]
@@ -285,17 +287,11 @@ 

Source code for tigramite.data_processing

             missing_anywhere = np.array(np.where(np.any(np.isnan(array), axis=0))[0])
             if self.remove_missing_upto_maxlag:
                 for tau in range(max_lag+1):
-                    if self.bootstrap is None:
-                        delete = missing_anywhere + tau 
-                        delete = delete[delete < time_length]
-                        use_indices[delete] = 0
-                    else:
-                        use_indices[missing_anywhere[self.bootstrap] + tau] = 0
+                    delete = missing_anywhere + tau 
+                    delete = delete[delete < time_length]
+                    use_indices[delete] = 0
             else:
-                if self.bootstrap is None:
-                    use_indices[missing_anywhere] = 0
-                else:
-                    use_indices[missing_anywhere[self.bootstrap]] = 0
+                use_indices[missing_anywhere] = 0
 
         # Use the mask override if needed
         _use_mask = mask
@@ -323,6 +319,7 @@ 

Source code for tigramite.data_processing

             for idx, cde in index_code.items():
                 # Check if the letter index is in the mask type
                 if (mask_type is not None) and (idx in mask_type):
+                    print(idx, cde, xyz,  xyz == cde)
                     # If so, check if any of the data that correspond to the
                     # letter index is masked by taking the product along the
                     # node-data to return a time slice selection, where 0 means
@@ -332,7 +329,7 @@ 

Source code for tigramite.data_processing

 
         if (self.missing_flag is not None) or (_use_mask is not None):
             if use_indices.sum() == 0:
-                raise ValueError("No unmasked samples")
+                raise ValueError("No unmasked samples!")
             array = array[:, use_indices == 1]
 
         # Print information about the constructed array
diff --git a/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html b/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
index 9235c461..63b49be5 100644
--- a/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
+++ b/docs/_build/html/_modules/tigramite/independence_tests/gpdc.html
@@ -56,7 +56,7 @@ 

Source code for tigramite.independence_tests.gpdc

# License: GNU General Public License v3.0 from __future__ import print_function -import json, warnings +import json, warnings, os, pathlib import numpy as np try: from importlib import metadata @@ -65,7 +65,7 @@

Source code for tigramite.independence_tests.gpdc

try: import dcor from sklearn import gaussian_process - with open('../versions.py', 'r') as vfile: + with open(pathlib.Path(os.path.dirname(__file__)) / '../../versions.py', 'r') as vfile: packages = json.loads(vfile.read())['all'] packages = dict(map(lambda s: s.split('>='), packages)) if metadata.version('dcor') < packages['dcor']: diff --git a/docs/_build/html/_modules/tigramite/independence_tests/gpdc_torch.html b/docs/_build/html/_modules/tigramite/independence_tests/gpdc_torch.html index f88154fa..185d8891 100644 --- a/docs/_build/html/_modules/tigramite/independence_tests/gpdc_torch.html +++ b/docs/_build/html/_modules/tigramite/independence_tests/gpdc_torch.html @@ -56,7 +56,7 @@

Source code for tigramite.independence_tests.gpdc_torch

# License: GNU General Public License v3.0 from __future__ import print_function -import json, warnings +import json, warnings, os, pathlib import numpy as np import gc try: @@ -68,15 +68,15 @@

Source code for tigramite.independence_tests.gpdc_torch

import torch import gpytorch from .LBFGS import FullBatchLBFGS - with open('../versions.py', 'r') as vfile: + with open(pathlib.Path(os.path.dirname(__file__)) / '../../versions.py', 'r') as vfile: packages = json.loads(vfile.read())['all'] packages = dict(map(lambda s: s.split('>='), packages)) if metadata.version('dcor') < packages['dcor']: raise Exception('Version mismatch. Installed version of dcor', metadata.version('dcor'), 'Please install dcor>=', packages['dcor']) - if metadata.version('torch') < packages['pytorch']: - raise Exception('Version mismatch. Installed version of pytorch', metadata.version('torch'), - 'Please install pytorch>=', packages['pytorch']) + if metadata.version('torch') < packages['torch']: + raise Exception('Version mismatch. Installed version of torch', metadata.version('torch'), + 'Please install torch>=', packages['torch']) if metadata.version('gpytorch') < packages['gpytorch']: raise Exception('Version mismatch. Installed version of gpytorch', metadata.version('gpytorch'), 'Please install gpytorch>=', packages['gpytorch']) diff --git a/docs/_build/html/_modules/tigramite/models.html b/docs/_build/html/_modules/tigramite/models.html index 32848d7b..85ea6c6c 100644 --- a/docs/_build/html/_modules/tigramite/models.html +++ b/docs/_build/html/_modules/tigramite/models.html @@ -57,7 +57,7 @@

Source code for tigramite.models

 
 from __future__ import print_function
 from copy import deepcopy
-import json, warnings
+import json, warnings, os, pathlib
 import numpy as np
 try:
     from importlib import metadata
@@ -67,7 +67,7 @@ 

Source code for tigramite.models

     import sklearn
     import sklearn.linear_model
     import networkx
-    with open('../versions.py', 'r') as vfile:
+    with open(pathlib.Path(os.path.dirname(__file__)) / '../versions.py', 'r') as vfile:
         packages = json.loads(vfile.read())['all']
         packages = dict(map(lambda s: s.split('>='), packages))
         if metadata.version('scikit-learn') < packages['scikit-learn']:
@@ -81,6 +81,10 @@ 

Source code for tigramite.models

 from tigramite.data_processing import DataFrame
 from tigramite.pcmci import PCMCI
 
+### remove!!!
+from matplotlib import pyplot as plt
+from scipy.stats import kde
+
 
[docs]class Models(): """Base class for time series models. @@ -102,7 +106,8 @@

Source code for tigramite.models

     data_transform : sklearn preprocessing object, optional (default: None)
         Used to transform data prior to fitting. For example,
         sklearn.preprocessing.StandardScaler for simple standardization. The
-        fitted parameters are stored.
+        fitted parameters are stored. Note that the inverse_transform is then
+        applied to the predicted data.
     mask_type : {None, 'y','x','z','xy','xz','yz','xyz'}
         Masking mode: Indicators for which variables in the dependence
         measure I(X; Y | Z) the samples should be masked. If None, the mask
@@ -121,8 +126,9 @@ 

Source code for tigramite.models

         # Set the mask type and dataframe object
         self.mask_type = mask_type
         self.dataframe = dataframe
-        # Get the number of nodes for this dataset
-        self.N = self.dataframe.values.shape[1]
+        # Get the number of nodes and length for this dataset
+        self.N = self.dataframe.N
+        self.T = self.dataframe.T
         # Set the model to be used
         self.model = model
         if conditional_model is None:
@@ -209,8 +215,7 @@ 

Source code for tigramite.models

         fit_results = {}
         for y in self.Y:
 
-            # Construct array of shape (var, time) with first entry being
-            # a dummy, second is y followed by joint X and Z (ignore the notation in construct_array)
+            # Construct array of shape (var, time)
             array, xyz = \
                 self.dataframe.construct_array(X=self.X, Y=[y], # + self.Z, 
                                                Z=self.conditions,
@@ -220,18 +225,35 @@ 

Source code for tigramite.models

                                                cut_off=self.cut_off,
                                                verbosity=self.verbosity)
 
-
             # Transform the data if needed
+            self.fitted_data_transform = None
             if self.data_transform is not None:
-                array = self.data_transform.fit_transform(X=array.T).T
+                # Fit only X, Y, and S for later use in transforming input
+                X_transform = deepcopy(self.data_transform)
+                x_indices = list(np.where(xyz==0)[0])
+                X_transform.fit(array[x_indices, :].T)
+                self.fitted_data_transform = {'X': X_transform}
+                Y_transform = deepcopy(self.data_transform)
+                y_indices = list(np.where(xyz==1)[0])
+                Y_transform.fit(array[y_indices, :].T)
+                self.fitted_data_transform['Y'] = Y_transform
+                if len(self.conditions) > 0:
+                    S_transform = deepcopy(self.data_transform)
+                    s_indices = list(np.where(xyz==2)[0])
+                    S_transform.fit(array[s_indices, :].T) 
+                    self.fitted_data_transform['S'] = S_transform
+
+                # Now transform whole array
+                all_transform = deepcopy(self.data_transform)
+                array = all_transform.fit_transform(X=array.T).T
 
             # Fit the model 
             # Copy and fit the model
             a_model = deepcopy(self.model)
 
             predictor_indices =  list(np.where(xyz==0)[0]) \
-                               + list(np.where(xyz==2)[0]) \
-                               + list(np.where(xyz==3)[0])
+                               + list(np.where(xyz==3)[0]) \
+                               + list(np.where(xyz==2)[0])
             predictor_array = array[predictor_indices, :].T
             # Target is only first entry of Y, ie [y]
             target_array = array[np.where(xyz==1)[0][0], :]
@@ -244,10 +266,10 @@ 

Source code for tigramite.models

             fit_results[y]['xyz'] = xyz
             fit_results[y]['model'] = a_model
             # Cache the data transform
-            fit_results[y]['data_transform'] = deepcopy(self.data_transform)
-            # Cache the data if needed
-            if return_data:
-                fit_results[y]['data'] = array
+            fit_results[y]['fitted_data_transform'] = self.fitted_data_transform
+            # # Cache the data if needed
+            # if return_data:
+            #     fit_results[y]['data'] = array
 
         # Cache and return the fit results
         self.fit_results = fit_results
@@ -258,6 +280,7 @@ 

Source code for tigramite.models

                 intervention_data,
                 conditions_data=None,
                 pred_params=None,
+                return_further_pred_results=False,
                 ):
         r"""Predict effect of intervention with fitted model.
 
@@ -271,7 +294,9 @@ 

Source code for tigramite.models

             Numpy array of shape (time, len(S)) that contains the S=s values.
         pred_params : dict, optional
             Optional parameters passed on to sklearn prediction function.
-
+        return_further_pred_results : bool, optional (default: False)
+            In case the predictor class returns more than just the expected value,
+            the entire results can be returned.
         Returns
         -------
         Results from prediction.
@@ -289,12 +314,12 @@ 

Source code for tigramite.models

                 raise ValueError("conditions_data.shape[0] must match intervention_data.shape[0].")
 
         lenS = len(self.conditions)
-
         lenY = len(self.Y)
 
         predicted_array = np.zeros((intervention_T, lenY))
         pred_dict = {}
         for iy, y in enumerate(self.Y):
+            pred_dict[iy] = {}
             # Print message
             if self.verbosity > 1:
                 print("\n## Predicting target %s" % str(y))
@@ -309,16 +334,16 @@ 

Source code for tigramite.models

                 raise ValueError("y = %s not yet fitted" % str(y))
 
             # Transform the data if needed
-            a_transform = self.fit_results[y]['data_transform']
-            if a_transform is not None:
-                intervention_data = a_transform.transform(X=intervention_data)
+            fitted_data_transform = self.fit_results[y]['fitted_data_transform']
+            if fitted_data_transform is not None:
+                intervention_data = fitted_data_transform['X'].transform(X=intervention_data)
                 if self.conditions is not None and conditions_data is not None:
-                    conditions_data = a_transform.transform(X=conditions_data)
+                    conditions_data = fitted_data_transform['S'].transform(X=conditions_data)
 
             # Extract observational Z from stored array
             z_indices = list(np.where(self.fit_results[y]['xyz']==3)[0])
             z_array = self.fit_results[y]['observation_array'][z_indices, :].T  
-            Tobs = len(z_array)              
+            Tobs = len(self.fit_results[y]['observation_array'].T) 
 
             if self.conditions is not None and conditions_data is not None:
                 s_indices = list(np.where(self.fit_results[y]['xyz']==2)[0])
@@ -339,20 +364,33 @@ 

Source code for tigramite.models

 
                 if self.conditions is not None and conditions_data is not None:
  
-                    # if a_transform is not None:
-                    #     predicted_vals = a_transform.transform(X=target_array.T).T
                     a_conditional_model = deepcopy(self.conditional_model)
                     
-                    a_conditional_model.fit(X=s_array, y=predicted_vals)
+                    if type(predicted_vals) is tuple:
+                        predicted_vals_here = predicted_vals[0]
+                    else:
+                        predicted_vals_here = predicted_vals
+                    
+                    a_conditional_model.fit(X=s_array, y=predicted_vals_here)
                     self.fit_results[y]['conditional_model'] = a_conditional_model
 
-                    predicted_array[index, iy] = a_conditional_model.predict(
-                        X=conditions_array, **pred_params).mean()
+                    predicted_vals = a_conditional_model.predict(
+                        X=conditions_array, **pred_params)
 
+                if type(predicted_vals) is tuple:
+                    predicted_array[index, iy] = predicted_vals[0].mean()
+                    pred_dict[iy][index] = predicted_vals
                 else:
                     predicted_array[index, iy] = predicted_vals.mean()
 
-        return predicted_array
+ if fitted_data_transform is not None: + rescaled = fitted_data_transform['Y'].inverse_transform(X=predicted_array[index, iy].reshape(-1, 1)) + predicted_array[index, iy] = rescaled.squeeze() + + if return_further_pred_results: + return predicted_array, pred_dict + else: + return predicted_array
[docs] def get_fit(self, all_parents, diff --git a/docs/_build/html/_modules/tigramite/plotting.html b/docs/_build/html/_modules/tigramite/plotting.html index 3bc18132..1bdcf70f 100644 --- a/docs/_build/html/_modules/tigramite/plotting.html +++ b/docs/_build/html/_modules/tigramite/plotting.html @@ -56,7 +56,7 @@

Source code for tigramite.plotting

 # License: GNU General Public License v3.0
 
 import numpy as np
-import json, warnings
+import json, warnings, os, pathlib
 try:
     from importlib import metadata
 except ImportError:
@@ -64,7 +64,7 @@ 

Source code for tigramite.plotting

 try:
     import matplotlib
     import networkx as nx
-    with open('../versions.py', 'r') as vfile:
+    with open(pathlib.Path(os.path.dirname(__file__)) / '../versions.py', 'r') as vfile:
         packages = json.loads(vfile.read())['all']
         packages = dict(map(lambda s: s.split('>='), packages))
         if metadata.version('matplotlib') < packages['matplotlib']:
@@ -89,7 +89,7 @@ 

Source code for tigramite.plotting

 from copy import deepcopy
 import matplotlib.path as mpath
 import matplotlib.patheffects as PathEffects
-
+from mpl_toolkits.axisartist.axislines import Axes
 # TODO: Add proper docstrings to internal functions...
 
 
@@ -861,6 +861,311 @@ 

Source code for tigramite.plotting

             pyplot.show()
+ +
[docs]def plot_scatterplots(dataframe, name=None, setup_args={}, add_scatterplot_args={}): + """Wrapper helper function to plot scatter plots. + Sets up the matrix object and plots the scatter plots, see parameters in + setup_scatter_matrix and add_scatterplot. + + Parameters + ---------- + dataframe : data object + Tigramite dataframe object. It must have the attributes dataframe.values + yielding a numpy array of shape (observations T, variables N) and + optionally a mask of the same shape and a missing values flag. + name : str, optional (default: None) + File name. If None, figure is shown in window. + setup_args : dict + Arguments for setting up the scatter plot matrix, see doc of + setup_scatter_matrix. + add_scatterplot_args : dict + Arguments for adding a scatter plot matrix. + + Returns + ------- + matrix : object + Further scatter plot can be overlaid using the + matrix.add_scatterplot function. + """ + + N = dataframe.N + + matrix = setup_scatter_matrix(N=N, var_names=dataframe.var_names, **setup_args) + matrix.add_scatterplot(dataframe=dataframe, **add_scatterplot_args) + matrix.adjustfig(name=name) + + + return matrix
+ + +
[docs]class setup_scatter_matrix: + """Create matrix of scatter plot panels. + Class to setup figure object. The function add_scatterplot allows to plot + scatterplots of variables in the dataframe. Multiple scatter plots can be + overlaid for comparison. + + Parameters + ---------- + N : int + Number of variables + var_names : list, optional (default: None) + List of variable names. If None, range(N) is used. + figsize : tuple of floats, optional (default: None) + Figure size if new figure is created. If None, default pyplot figsize + is used. + label_space_left : float, optional (default: 0.1) + Fraction of horizontal figure space to allocate left of plot for labels. + label_space_top : float, optional (default: 0.05) + Fraction of vertical figure space to allocate top of plot for labels. + legend_width : float, optional (default: 0.15) + Fraction of horizontal figure space to allocate right of plot for + legend. + plot_gridlines : bool, optional (default: False) + Whether to show a grid. + label_fontsize : int, optional (default: 10) + Fontsize of variable labels. + """ + + def __init__( + self, + N, + var_names=None, + figsize=None, + label_space_left=0.1, + label_space_top=0.05, + legend_width=0.15, + legend_fontsize=10, + plot_gridlines=False, + label_fontsize=10, + ): + + self.labels = [] + + self.legend_width = legend_width + self.legend_fontsize = legend_fontsize + + self.label_space_left = label_space_left + self.label_space_top = label_space_top + self.label_fontsize = label_fontsize + + self.fig = pyplot.figure(figsize=figsize) + + self.axes_dict = {} + + if var_names is None: + var_names = range(N) + + plot_index = 1 + for i in range(N): + for j in range(N): + self.axes_dict[(i, j)] = self.fig.add_subplot(N, N, plot_index, axes_class=Axes) + # Plot process labels + if j == 0: + trans = transforms.blended_transform_factory( + self.fig.transFigure, self.axes_dict[(i, j)].transAxes + ) + self.axes_dict[(i, j)].text( + 0.01, + 0.5, + "%s" % str(var_names[i]), + fontsize=label_fontsize, + horizontalalignment="left", + verticalalignment="center", + transform=trans, + ) + if i == 0: + trans = transforms.blended_transform_factory( + self.axes_dict[(i, j)].transAxes, self.fig.transFigure + ) + self.axes_dict[(i, j)].text( + 0.5, + 0.99, + r"${\to}$ " + "%s" % str(var_names[j]), + fontsize=label_fontsize, + horizontalalignment="center", + verticalalignment="top", + transform=trans, + ) + + self.axes_dict[(i, j)].axis["right"].set_visible(False) + self.axes_dict[(i, j)].axis["top"].set_visible(False) + + if j != 0: + self.axes_dict[(i, j)].get_yaxis().set_ticklabels([]) + if i != N - 1: + self.axes_dict[(i, j)].get_xaxis().set_ticklabels([]) + + if plot_gridlines: + self.axes_dict[(i, j)].grid( + True, + which="major", + color="black", + linestyle="dotted", + dashes=(1, 1), + linewidth=0.05, + zorder=-5, + ) + + plot_index += 1 + +
[docs] def add_scatterplot( + self, + dataframe, + scatter_lags=None, + color="black", + label=None, + marker=".", + markersize=5, + alpha=1.0, + ): + """Add lag function plot from val_matrix array. + + Parameters + ---------- + dataframe : data object + Tigramite dataframe object. It must have the attributes dataframe.values + yielding a numpy array of shape (observations T, variables N) and + optionally a mask of the same shape and a missing values flag. + scatter_lags : array + Lags to use in scatter plots. Either None or of shape (N, N). Then the + entry scatter_lags[i, j] = tau will depict the scatter plot of + time series (i, -tau) vs (j, 0). If None, tau = 0 for i != j and for i = j + tau = 1. + color : str, optional (default: 'black') + Line color. + label : str + Test statistic label. + marker : matplotlib marker symbol, optional (default: '.') + Marker. + markersize : int, optional (default: 5) + Marker size. + alpha : float, optional (default: 1.) + Opacity. + """ + + if label is not None: + self.labels.append((label, color, marker, markersize, alpha)) + + for ij in list(self.axes_dict): + i = ij[0] + j = ij[1] + if scatter_lags is None: + if i == j: + lag = 1 + else: + lag = 0 + else: + lag = scatter_lags[i,j] + if lag == 0: + x = np.copy(dataframe.values[:, i]) + y = np.copy(dataframe.values[:, j]) + else: + x = np.copy(dataframe.values[:-lag, i]) + y = np.copy(dataframe.values[lag:, j]) + if dataframe.mask is not None: + x[dataframe.mask[:-lag, i]] = np.nan + y[dataframe.mask[lag:, j]] = np.nan + # print(i, j, lag, x.shape, y.shape) + self.axes_dict[(i, j)].scatter( + x, y, + color=color, + marker=marker, + s=markersize, + alpha=alpha, + clip_on=False, + label=r"$\tau{=}%d$" %lag, + )
+ # self.axes_dict[(i, j)].text(0., 1., r"$\tau{=}%d$" %lag, + # fontsize=self.legend_fontsize, + # ha='left', va='top', + # transform=self.axes_dict[(i, j)].transAxes) + + +
[docs] def adjustfig(self, name=None): + """Adjust matrix figure. + + Parameters + ---------- + name : str, optional (default: None) + File name. If None, figure is shown in window. + """ + + # Trick to plot legends + colors = [] + for item in self.labels: + colors.append(item[1]) + for ij in list(self.axes_dict): + i = ij[0] + j = ij[1] + + leg = self.axes_dict[(i, j)].legend( + # loc="upper left", + ncol=1, + # bbox_to_anchor=(1.05, 0.0, 0.1, 1.0), + # borderaxespad=0, + fontsize=self.legend_fontsize-2, + labelcolor=colors, + ).draw_frame(False) + + if len(self.labels) > 0: + axlegend = self.fig.add_subplot(111, frameon=False) + axlegend.spines["left"].set_color("none") + axlegend.spines["right"].set_color("none") + axlegend.spines["bottom"].set_color("none") + axlegend.spines["top"].set_color("none") + axlegend.set_xticks([]) + axlegend.set_yticks([]) + + # self.labels.append((label, color, marker, markersize, alpha)) + for item in self.labels: + label = item[0] + color = item[1] + marker = item[2] + markersize = item[3] + alpha = item[4] + + axlegend.plot( + [], + [], + linestyle="", + color=color, + marker=marker, + markersize=markersize, + label=label, + alpha=alpha, + ) + axlegend.legend( + loc="upper left", + ncol=1, + bbox_to_anchor=(1.05, 0.0, 0.1, 1.0), + borderaxespad=0, + fontsize=self.legend_fontsize, + ).draw_frame(False) + + self.fig.subplots_adjust( + bottom=0.05, + left=self.label_space_left, + right=1.0 - self.legend_width, + top=1.0 - self.label_space_top, + hspace=0.5, + wspace=0.35, + ) + + else: + self.fig.subplots_adjust( + left=self.label_space_left, + bottom=0.05, + right=0.95, + top=1.0 - self.label_space_top, + hspace=0.35, + wspace=0.35, + ) + + if name is not None: + self.fig.savefig(name) + else: + pyplot.show()
+ def _draw_network_with_curved_edges( fig, ax, @@ -1440,13 +1745,12 @@

Source code for tigramite.plotting

                 data_to_rgb_links, cax=cax_e, orientation="horizontal"
             )
             # try:
-            cb_e.set_ticks(
-                np.arange(
+            ticks_here = np.arange(
                     _myround(links_vmin, links_ticks, "down"),
                     _myround(links_vmax, links_ticks, "up") + links_ticks,
                     links_ticks,
                 )
-            )
+            cb_e.set_ticks(ticks_here[(links_vmin <= ticks_here) & (ticks_here <= links_vmax)])
             # except:
             #     print('no ticks given')
 
@@ -1531,14 +1835,13 @@ 

Source code for tigramite.plotting

                 )
                 cb_n = pyplot.colorbar(data_to_rgb, cax=cax_n, orientation="horizontal")
                 # try:
-                cb_n.set_ticks(
-                    np.arange(
-                        _myround(vmin, node_rings[ring]["ticks"], "down"),
-                        _myround(vmax, node_rings[ring]["ticks"], "up")
-                        + node_rings[ring]["ticks"],
-                        node_rings[ring]["ticks"],
-                    )
+                ticks_here = np.arange(
+                    _myround(vmin, node_rings[ring]["ticks"], "down"),
+                    _myround(vmax, node_rings[ring]["ticks"], "up")
+                    + node_rings[ring]["ticks"],
+                    node_rings[ring]["ticks"],
                 )
+                cb_n.set_ticks(ticks_here[(vmin <= ticks_here) & (ticks_here <= vmax)])
                 # except:
                 #     print ('no ticks given')
                 cb_n.outline.clear()
@@ -3384,6 +3687,46 @@ 

Source code for tigramite.plotting

 
 if __name__ == "__main__":
 
+    import sys
+    matplotlib.rc('xtick', labelsize=6) 
+    matplotlib.rc('ytick', labelsize=6) 
+
+    # Consider some toy data
+    import tigramite
+    import tigramite.toymodels.structural_causal_processes as toys
+    import tigramite.data_processing as pp
+
+    T = 1000
+    def lin_f(x): return x
+    auto_coeff = 0.3
+    coeff = 1.
+    links = {
+            0: [((0, -1), auto_coeff, lin_f)], 
+            1: [((1, -1), auto_coeff, lin_f), ((0, 0), coeff, lin_f)], 
+            2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
+            }
+    data, nonstat = toys.structural_causal_process(links, T=T, 
+                                noises=None, seed=7)
+
+    dataframe = pp.DataFrame(data, var_names=range(len(links)))
+    plot_scatterplots(dataframe) #, name='scattertest.pdf')
+    
+    # matrix = setup_scatter_matrix(N=dataframe.N, 
+    #     var_names=dataframe.var_names)
+    # scatter_lags = np.ones((3, 3)).astype('int')
+    # matrix.add_scatterplot(dataframe=dataframe, scatter_lags=scatter_lags,
+    #             label='ones', alpha=0.4)
+    # scatter_lags = 2*np.ones((3, 3)).astype('int')
+    # matrix.add_scatterplot(dataframe=dataframe, scatter_lags=scatter_lags, 
+    #     label='twos', color='red', alpha=0.4)
+
+    # matrix.savefig(name='scattertest.pdf')
+    
+
+    # pyplot.show()
+    sys.exit(0)
+
+
     val_matrix = np.zeros((4, 4, 3))
 
     # Complete test case
diff --git a/docs/_build/html/genindex.html b/docs/_build/html/genindex.html
index 7bb74238..7da74fe5 100644
--- a/docs/_build/html/genindex.html
+++ b/docs/_build/html/genindex.html
@@ -75,9 +75,13 @@ 

A

@@ -128,10 +132,12 @@

F

  • set_mask_type() (tigramite.independence_tests.CondIndTest method) +
  • +
  • setup_matrix (class in tigramite.plotting)
    • -
    • setup_matrix (class in tigramite.plotting) +
    • setup_scatter_matrix (class in tigramite.plotting)
    • smooth() (in module tigramite.data_processing)
    • diff --git a/docs/_build/html/index.html b/docs/_build/html/index.html index 0906171f..4d386978 100644 --- a/docs/_build/html/index.html +++ b/docs/_build/html/index.html @@ -2571,6 +2571,29 @@

      +
      +
      +fit_bootstrap_of(method, method_args, boot_samples=1000, boot_blocklength=1, seed=None)[source]
      +

      Runs chosen method on bootstrap samples drawn from DataFrame.

      +

      Bootstraps for tau=0 are drawn from [max_lag, …, T] and all lagged +variables constructed in DataFrame.construct_array are consistently +shifted with respect to this bootsrap sample to ensure that lagged +relations in the bootstrap sample are preserved.

      +

      This function fits the models, predict_bootstrap_of can then be used +to get confidence intervals for the effect of interventions.

      +
      +
      Parameters
      +
        +
      • method (str) – Chosen method among valid functions in this class.

      • +
      • method_args (dict) – Arguments passed to method.

      • +
      • boot_samples (int) – Number of bootstrap samples to draw.

      • +
      • boot_blocklength (int, optional (default: 1)) – Block length for block-bootstrap.

      • +
      • seed (int, optional(default = None)) – Seed for RandomState (default_rng)

      • +
      +
      +
      +
      +
      fit_total_effect(dataframe, estimator, adjustment_set='optimal', conditional_estimator=None, data_transform=None, mask_type=None)[source]
      @@ -2700,9 +2723,32 @@

      +
      +
      +predict_bootstrap_of(method, method_args, conf_lev=0.9)[source]
      +

      Predicts with fitted bootstraps.

      +

      To be used after fitting with fit_bootstrap_of. Only uses the +expected values of the predict function, not potential other output.

      +
      +
      Parameters
      +
        +
      • method (str) – Chosen method among valid functions in this class.

      • +
      • method_args (dict) – Arguments passed to method.

      • +
      • conf_lev (float, optional (default: 0.9)) – Two-sided confidence interval.

      • +
      +
      +
      Returns
      +

      confidence_intervals

      +
      +
      Return type
      +

      numpy array of

      +
      +
      +
      +
      -predict_total_effect(intervention_data, conditions_data=None, pred_params=None)[source]
      +predict_total_effect(intervention_data, conditions_data=None, pred_params=None, return_further_pred_results=False)[source]

      Predict effect of intervention with fitted model.

      Uses the model.predict() function of the sklearn model.

      @@ -2711,13 +2757,16 @@

    • intervention_data (numpy array) – Numpy array of shape (time, len(X)) that contains the do(X) values.

    • conditions_data (data object, optional) – Numpy array of shape (time, len(S)) that contains the S=s values.

    • pred_params (dict, optional) – Optional parameters passed on to sklearn prediction function.

    • +
    • return_further_pred_results (bool, optional (default: False)) – In case the predictor class returns more than just the expected value, +the entire results can be returned.

    Returns
    -

    Results from prediction

    -
    -
    Return type
    -

    an array of shape (time, len(Y))

    +

      +
    • Results from prediction (an array of shape (time, len(Y)).)

    • +
    • If estimate_confidence = True, then a tuple is returned.

    • +
    +

    @@ -2766,7 +2815,8 @@

    If None, model is used.

  • data_transform (sklearn preprocessing object, optional (default: None)) – Used to transform data prior to fitting. For example, sklearn.preprocessing.StandardScaler for simple standardization. The -fitted parameters are stored.

  • +fitted parameters are stored. Note that the inverse_transform is then +applied to the predicted data.

  • mask_type ({None, 'y','x','z','xy','xz','yz','xyz'}) – Masking mode: Indicators for which variables in the dependence measure I(X; Y | Z) the samples should be masked. If None, the mask is not used. Explained in tutorial on masking and missing values.

  • @@ -2858,7 +2908,7 @@

    -get_general_prediction(intervention_data, conditions_data=None, pred_params=None)[source]
    +get_general_prediction(intervention_data, conditions_data=None, pred_params=None, return_further_pred_results=False)[source]

    Predict effect of intervention with fitted model.

    Uses the model.predict() function of the sklearn model.

    @@ -2867,6 +2917,8 @@

  • intervention_data (numpy array) – Numpy array of shape (time, len(X)) that contains the do(X) values.

  • conditions_data (data object, optional) – Numpy array of shape (time, len(S)) that contains the S=s values.

  • pred_params (dict, optional) – Optional parameters passed on to sklearn prediction function.

  • +
  • return_further_pred_results (bool, optional (default: False)) – In case the predictor class returns more than just the expected value, +the entire results can be returned.

  • Returns
    @@ -4066,6 +4118,34 @@

    +
    +
    +tigramite.plotting.plot_scatterplots(dataframe, name=None, setup_args={}, add_scatterplot_args={})[source]
    +

    Wrapper helper function to plot scatter plots. +Sets up the matrix object and plots the scatter plots, see parameters in +setup_scatter_matrix and add_scatterplot.

    +
    +
    Parameters
    +
      +
    • dataframe (data object) – Tigramite dataframe object. It must have the attributes dataframe.values +yielding a numpy array of shape (observations T, variables N) and +optionally a mask of the same shape and a missing values flag.

    • +
    • name (str, optional (default: None)) – File name. If None, figure is shown in window.

    • +
    • setup_args (dict) – Arguments for setting up the scatter plot matrix, see doc of +setup_scatter_matrix.

    • +
    • add_scatterplot_args (dict) – Arguments for adding a scatter plot matrix.

    • +
    +
    +
    Returns
    +

    matrix – Further scatter plot can be overlaid using the +matrix.add_scatterplot function.

    +
    +
    Return type
    +

    object

    +
    +
    +
    +
    tigramite.plotting.plot_time_series_graph(graph, val_matrix=None, var_names=None, fig_ax=None, figsize=None, link_colorbar_label='MCI', save_name=None, link_width=None, link_attribute=None, arrow_linewidth=8, vmin_edges=-1, vmax_edges=1.0, edge_ticks=0.4, cmap_edges='RdBu_r', order=None, node_size=0.1, node_aspect=None, arrowhead_size=20, curved_radius=0.2, label_fontsize=12, alpha=1.0, node_label_size=12, label_space_left=0.1, label_space_top=0.0, network_lower_bound=0.2, inner_edge_style='dashed', link_matrix=None, special_nodes=None, standard_color_links='black', standard_color_nodes='lightgrey')[source]
    @@ -4213,6 +4293,66 @@

    +
    +
    +class tigramite.plotting.setup_scatter_matrix(N, var_names=None, figsize=None, label_space_left=0.1, label_space_top=0.05, legend_width=0.15, legend_fontsize=10, plot_gridlines=False, label_fontsize=10)[source]
    +

    Create matrix of scatter plot panels. +Class to setup figure object. The function add_scatterplot allows to plot +scatterplots of variables in the dataframe. Multiple scatter plots can be +overlaid for comparison.

    +
    +
    Parameters
    +
      +
    • N (int) – Number of variables

    • +
    • var_names (list, optional (default: None)) – List of variable names. If None, range(N) is used.

    • +
    • figsize (tuple of floats, optional (default: None)) – Figure size if new figure is created. If None, default pyplot figsize +is used.

    • +
    • label_space_left (float, optional (default: 0.1)) – Fraction of horizontal figure space to allocate left of plot for labels.

    • +
    • label_space_top (float, optional (default: 0.05)) – Fraction of vertical figure space to allocate top of plot for labels.

    • +
    • legend_width (float, optional (default: 0.15)) – Fraction of horizontal figure space to allocate right of plot for +legend.

    • +
    • plot_gridlines (bool, optional (default: False)) – Whether to show a grid.

    • +
    • label_fontsize (int, optional (default: 10)) – Fontsize of variable labels.

    • +
    +
    +
    +
    +
    +add_scatterplot(dataframe, scatter_lags=None, color='black', label=None, marker='.', markersize=5, alpha=1.0)[source]
    +

    Add lag function plot from val_matrix array.

    +
    +
    Parameters
    +
      +
    • dataframe (data object) – Tigramite dataframe object. It must have the attributes dataframe.values +yielding a numpy array of shape (observations T, variables N) and +optionally a mask of the same shape and a missing values flag.

    • +
    • scatter_lags (array) – Lags to use in scatter plots. Either None or of shape (N, N). Then the +entry scatter_lags[i, j] = tau will depict the scatter plot of +time series (i, -tau) vs (j, 0). If None, tau = 0 for i != j and for i = j +tau = 1.

    • +
    • color (str, optional (default: 'black')) – Line color.

    • +
    • label (str) – Test statistic label.

    • +
    • marker (matplotlib marker symbol, optional (default: '.')) – Marker.

    • +
    • markersize (int, optional (default: 5)) – Marker size.

    • +
    • alpha (float, optional (default: 1.)) – Opacity.

    • +
    +
    +
    +
    + +
    +
    +adjustfig(name=None)[source]
    +

    Adjust matrix figure.

    +
    +
    Parameters
    +

    name (str, optional (default: None)) – File name. If None, figure is shown in window.

    +
    +
    +
    + +
    +

    Indices and tables

    diff --git a/docs/_build/html/objects.inv b/docs/_build/html/objects.inv index 480c1c789f2ddf177abe371597d0e757437741c9..3dd062c04734a721c6a1de91b2d41ceee22ec3f5 100644 GIT binary patch delta 1404 zcmV-?1%vv^3-b$*h=0~J*W5Zzn$b+udKw?v69ytd5;X|0z|yk%>$?C+iBe<-1XdSY z{CFQO7K`PA0La?%R)Sa;ymwqNQB|S>5^C)3Q>MQCm?;4#qkn-q_*H2?`54D|}n2dws$Z_xyxS=>3udXPq^L za8Bwvh)mflvHE2$8qVFnt6hJ>@v4+oUCyMgOs?OpXw8dYla+l3hPC{a#@H8bnZ_S3 znWfCW!Qs+jn6gSL5Z0rrUKb#ZUP3aqlo|&ozQJZ8n?m}x=NhCEY$tUd$+eidnq+kt ze!ay;jfrQxmDa<=((>U>h zeyaFxV1N1zkd%RXfv)5$CP`?laJTU_wZT}W3O@r-BII#aSQJ{H(W#z5JAN?R7Xy3S*YLqJK#8jLNPoJb6Sn}y>Aog^kF z<}CvA#3qi;6ZkeEdg7DE>4464!XK6wN<3^*V|CJxpOsx>Y&9 zS-6yAz!03V&VQHT@)=6e*b+EI_OuiRQ9wu#e(fS3V?{$WO;_X z!Wx&Rqu+ktlM>_M@$A8|y>L>kmpXDL^=6L^kKW*Lof7663s%A3pjbX%PfWp#&54r_ zulxA=V0Qod_vi)Px#}rN<=;{rw?czU(qpCjB5cSr4yC$YGB=uohEZ=VR*X3CI)4oL zUbr;OZ2H$N88(+3#p@bvIhKqv#UNk!hCG_)-{G6H6|Ps1@bp1`DwJW#g!l|JY`AZ= z@jvfQx0R;wH_h&N+I;!**X`!%^BvlDh1VVKrwfB%JM`EMz$z;B*1+D delta 1363 zcmV-Z1+4n>3(5WU_WSDo z4x#`>*|PGP{PXV*(o<+Xuw&4wDwC*s;2jkl4hYDa0|5occ7G(~Uh}2}JZ8gy*bDoX z)LM0<;%L;4Rh)v-28lP04lxYF!d^4iSL`90unEIdQJ|#Ps$|A+*?5tv2EkT;%thhc z{hQk2vpxRPwy~(m_Nuxll{BCS+aanoJtTExhI1{BK>;-14#3heHWnBHs-xx^1H=6p zQVZH3;CjvF=zns;Wvz1ku34vcj7(MzJt)%A7aU`ER1;}`m}Hhv`_@jE-i9fuxd5ge zsvcwsT*)OQr7JG&t`vWa^90-L({z?q<&e=Flyr6Gw-n8kD_O~$o21v|6 zy+GIe#eXJAXf-pp@in%=wn}BLR2R(WaZ+k4)GniA-2r$0Uc#}VnEnmbVSHWq4o(l! zpGAccP4_53<0h7^8tQ2^gFIjO{1Jy>)elPR)Y&o0(U*KzxhR=sPDaeNb1Z%w&grOmb^9 zj>@*k>K#VLZvT#$jsLeKM+L<(NKC@*#($S~kSY!9CE*ZmcVu~nyuuo{rlX&JzmgK; z;qmOov7>NO6-ymClRC42Bxx2+ z5QM(C>U+y~vBmeLv>t>=)pn`E-Y))tZUsw~Q_*BdiL_Oc`+~vPWgIgLN~K?M89uPb zy%-XQ+z4K|1huycwI`}xjxmSM3V$^JkCEQLuwD9Op2NJB%lH{36u{CC)FzStamvjx z-+7!%Z8CHslcv5XwR0ie@td&p!z82 z)-Gf2Kdh#+{<_uL{k%I}R;kimG`r$y{q^rpoAuL|J8Rn&UVpfs8iHUGMl6txT}GDe Vxgwkk7yk(DkF;TT{{twB3NFU}vWEZw diff --git a/docs/_build/html/searchindex.js b/docs/_build/html/searchindex.js index 6a85b8e8..d9fa690b 100644 --- a/docs/_build/html/searchindex.js +++ b/docs/_build/html/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.index":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"tigramite.causal_effects":{CausalEffects:[0,0,1,""]},"tigramite.causal_effects.CausalEffects":{check_XYS_paths:[0,1,1,""],check_optimality:[0,1,1,""],fit_total_effect:[0,1,1,""],fit_wright_effect:[0,1,1,""],get_graph_from_dict:[0,1,1,""],get_mediators:[0,1,1,""],get_optimal_set:[0,1,1,""],predict_total_effect:[0,1,1,""],predict_wright_effect:[0,1,1,""]},"tigramite.data_processing":{DataFrame:[0,0,1,""],lowhighpass_filter:[0,4,1,""],ordinal_patt_array:[0,4,1,""],quantile_bin_array:[0,4,1,""],smooth:[0,4,1,""],structural_causal_process:[0,4,1,""],time_bin_with_mask:[0,4,1,""],var_process:[0,4,1,""],weighted_avg_and_std:[0,4,1,""]},"tigramite.data_processing.DataFrame":{construct_array:[0,1,1,""],data:[0,3,1,""],datatime:[0,3,1,""],mask:[0,3,1,""],missing_flag:[0,3,1,""],print_array_info:[0,1,1,""],remove_missing_upto_maxlag:[0,3,1,""],var_names:[0,3,1,""]},"tigramite.independence_tests":{CMIknn:[0,0,1,""],CMIsymb:[0,0,1,""],CondIndTest:[0,0,1,""],GPDC:[0,0,1,""],GPDCtorch:[0,0,1,""],OracleCI:[0,0,1,""],ParCorr:[0,0,1,""]},"tigramite.independence_tests.CMIknn":{get_conditional_entropy:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CMIsymb":{get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CondIndTest":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_bootstrap_confidence:[0,1,1,""],get_confidence:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_fixed_thres_significance:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],get_significance:[0,1,1,""],measure:[0,1,1,""],print_info:[0,1,1,""],run_test:[0,1,1,""],run_test_raw:[0,1,1,""],set_dataframe:[0,1,1,""],set_mask_type:[0,1,1,""]},"tigramite.independence_tests.GPDC":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.GPDCtorch":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.OracleCI":{check_shortest_path:[0,1,1,""],get_confidence:[0,1,1,""],get_graph_from_links:[0,1,1,""],get_links_from_graph:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],measure:[0,1,1,""],run_test:[0,1,1,""],set_dataframe:[0,1,1,""]},"tigramite.independence_tests.ParCorr":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.lpcmci":{LPCMCI:[0,0,1,""]},"tigramite.lpcmci.LPCMCI":{run_lpcmci:[0,1,1,""]},"tigramite.models":{LinearMediation:[0,0,1,""],Models:[0,0,1,""],Prediction:[0,0,1,""]},"tigramite.models.LinearMediation":{fit_model:[0,1,1,""],get_ace:[0,1,1,""],get_acs:[0,1,1,""],get_all_ace:[0,1,1,""],get_all_acs:[0,1,1,""],get_all_amce:[0,1,1,""],get_amce:[0,1,1,""],get_ce:[0,1,1,""],get_ce_max:[0,1,1,""],get_coeff:[0,1,1,""],get_mce:[0,1,1,""],get_mediation_graph_data:[0,1,1,""],get_tsg:[0,1,1,""],get_val_matrix:[0,1,1,""],net_to_tsg:[0,1,1,""],tsg_to_net:[0,1,1,""]},"tigramite.models.Models":{get_coefs:[0,1,1,""],get_fit:[0,1,1,""],get_general_fitted_model:[0,1,1,""],get_general_prediction:[0,1,1,""],get_val_matrix:[0,1,1,""]},"tigramite.models.Prediction":{fit:[0,1,1,""],get_predictors:[0,1,1,""],get_test_array:[0,1,1,""],get_train_array:[0,1,1,""],predict:[0,1,1,""]},"tigramite.pcmci":{PCMCI:[0,0,1,""]},"tigramite.pcmci.PCMCI":{N:[0,3,1,""],T:[0,3,1,""],all_parents:[0,3,1,""],convert_to_string_graph:[0,1,1,""],get_corrected_pvalues:[0,1,1,""],get_graph_from_pmatrix:[0,1,1,""],get_lagged_dependencies:[0,1,1,""],iterations:[0,3,1,""],print_results:[0,1,1,""],print_significant_links:[0,1,1,""],pval_max:[0,3,1,""],return_parents_dict:[0,1,1,""],return_significant_links:[0,1,1,""],run_bivci:[0,1,1,""],run_fullci:[0,1,1,""],run_mci:[0,1,1,""],run_pc_stable:[0,1,1,""],run_pcalg:[0,1,1,""],run_pcalg_non_timeseries_data:[0,1,1,""],run_pcmci:[0,1,1,""],run_pcmciplus:[0,1,1,""],run_sliding_window_of:[0,1,1,""],symmetrize_p_and_val_matrix:[0,1,1,""],val_min:[0,3,1,""]},"tigramite.plotting":{plot_graph:[0,4,1,""],plot_lagfuncs:[0,4,1,""],plot_mediation_graph:[0,4,1,""],plot_mediation_time_series_graph:[0,4,1,""],plot_time_series_graph:[0,4,1,""],plot_timeseries:[0,4,1,""],plot_tsg:[0,4,1,""],setup_matrix:[0,0,1,""]},"tigramite.plotting.setup_matrix":{add_lagfuncs:[0,1,1,""],savefig:[0,1,1,""]},"tigramite.toymodels":{structural_causal_processes:[0,2,0,"-"]},"tigramite.toymodels.structural_causal_processes":{links_to_graph:[0,4,1,""],structural_causal_process:[0,4,1,""],var_process:[0,4,1,""]},tigramite:{data_processing:[0,2,0,"-"],plotting:[0,2,0,"-"]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","module","Python module"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:module","3":"py:attribute","4":"py:function"},terms:{"21st":0,"2xtau_max":0,"36th":0,"579_main_pap":0,"8485ae387a981d783f8764e508151cd9":0,"94e70705efae423efda1088614128d0b":0,"abstract":0,"boolean":0,"break":0,"case":0,"class":0,"default":0,"float":0,"import":0,"int":0,"long":0,"new":0,"null":0,"return":0,"static":0,"true":0,"var":0,"while":0,ACE:0,ACS:0,For:0,Its:0,Not:0,OLS:0,The:0,Then:0,There:0,These:0,Used:0,Useful:0,Uses:0,Using:0,Will:0,With:0,_get_single_residu:0,_run_ancestral_removal_phas:0,_run_dsep_removal_phas:0,_run_non_ancestral_removal_phas:0,about:0,abov:0,abs:0,absent:0,absmax:0,absolut:0,accept:0,accord:0,account:0,ace:0,across:0,acs:0,act:0,actual:0,adapt:0,add:0,add_lagfunc:0,add_lagfunc_arg:0,add_to_null_dist:0,added:0,adding:0,addit:0,address:0,adj:0,adjac:0,adjust:0,adjustment_set:0,admg:0,adv:0,advanc:0,affect:0,after:0,again:0,ahead:0,aic:0,aip:0,akaik:0,algorithm:0,all:0,all_lag:0,all_par:0,all_result:0,alloc:0,allow:0,along:0,alpha:0,alpha_level:0,alreadi:0,also:0,altern:0,alternative_condit:0,although:0,alwai:0,ambigu:0,ambiguous_tripl:0,amc:0,among:0,analyt:0,analyz:0,anc_all_i:0,anc_all_x:0,anc_all_z:0,anc_i:0,anc_x:0,anc_xi:0,ancestor:0,ancestr:0,ani:0,anoth:0,apds_t:0,appli:0,applic:0,appropri:0,apr:0,arang:0,arbitrari:0,argument:0,around:0,arrai:0,array_lik:0,array_mask:0,arrohead:0,arrow:0,arrow_linewidth:0,arrowhead_s:0,articl:0,artifici:0,arxiv:0,assess:0,assign:0,associ:0,assum:0,assumpt:0,ast:0,asymptot:0,attribut:0,au_i:0,au_j:0,auai:0,auto:0,auto_first:0,autocorrel:0,autocovari:0,autodepend:0,automat:0,autoregress:0,auxadmg:0,auxiliari:0,avail:0,averag:0,avoid:0,axes:0,axi:0,backdoor:0,backward:0,bakirov:0,bandwidth:0,base:0,basemap:0,been:0,befor:0,beforehand:0,begin:0,being:0,below:0,benjamini:0,best:0,beta:0,beta_i:0,beta_x:0,better:0,between:0,bia:0,bias:0,bin:0,bincount:0,bindata:0,bivci:0,black:0,block:0,blue:0,bold:0,bool:0,bootstrap:0,both:0,bottom:0,bound:0,box:0,breadth:0,break_once_separ:0,briefli:0,butterworth:0,call:0,callabl:0,can:0,canada:0,canon:0,cardin:0,care:0,caus:0,causaleffect:0,cdot:0,certain:0,chain:0,chao:0,check:0,check_optim:0,check_optimality_cond:0,check_shortest_path:0,check_sm_overlap:0,check_xys_path:0,child:0,choic:0,chosen:0,cite:0,ckdtree:0,clash:0,clean:0,cmap_edg:0,cmap_nod:0,cmi:0,cmiknn:0,cmisymb:0,coef1:0,coef2:0,coeff:0,coeffici:0,collid:0,collider_par:0,colliders_minimized_optim:0,colliders_onli:0,color:0,colorbar:0,colormap:0,column:0,com:0,combin:0,come:0,command:0,common:0,commun:0,compar:0,comparison:0,compat:0,complex:0,comprehens:0,comput:0,compute_ancestor:0,concret:0,cond_ind_test:0,condindtest:0,conditional_estim:0,conditional_model:0,conditions_data:0,conduct:0,conf_blocklength:0,conf_lev:0,conf_low:0,conf_matrix:0,conf_sampl:0,conf_upp:0,confer:0,confid:0,conflict:0,conflict_resolut:0,confound:0,conserv:0,consid:0,consider:0,considerd:0,consist:0,constant:0,constrain:0,construct:0,construct_arrai:0,constructor:0,contain:0,contemp_collider_rul:0,contemp_cond:0,contemporan:0,content:0,continu:0,contrast:0,control:0,conveni:0,convert:0,convert_to_string_graph:0,coordin:0,correct:0,corrected_a:0,correl:0,correspond:0,cost:0,could:0,coupl:0,covari:0,creat:0,criteria:0,criterion:0,cross:0,cube:0,current:0,curv:0,curvatur:0,curved_radiu:0,cut_off:0,cutoff:0,cutperiod:0,cython:0,d_z:0,dag:0,dash:0,data_linewidth:0,data_transform:0,datafram:0,dataset:0,datatim:0,dcor:0,debug:0,decai:0,def:0,default_rng:0,defin:0,definin:0,degre:0,delai:0,denot:0,densiti:0,depend:0,dependence_measur:0,deprec:0,depth:0,deriv:0,describ:0,descript:0,detail:0,detect:0,determin:0,deviat:0,dict:0,dictionari:0,differ:0,digamma:0,digest:0,dim:0,dimens:0,dimension:0,direct:0,direction:0,directli:0,disabl:0,discov:0,discoveri:0,discret:0,discuss:0,disk:0,dismiss:0,dist:0,distanc:0,distribut:0,do_check:0,doc:0,doe:0,doi:0,dpag:0,draw:0,drawn:0,driver:0,due:0,dummi:0,duplic:0,dure:0,eaau4996:0,each:0,easi:0,edg:0,edge_tick:0,effici:0,either:0,element:0,els:0,eman:0,embed:0,empti:0,end:0,ends_with:0,ensur:0,entri:0,entropi:0,enumer:0,epsilon_:0,equal:0,equival:0,error:0,estim:0,eta:0,etc:0,evalu:0,even:0,everi:0,exampl:0,except:0,exclud:0,exclude_contemporan:0,exclude_i:0,exclude_j:0,exclude_k:0,exclude_self_effect:0,execut:0,exist:0,expect:0,experi:0,experiment:0,explain:0,extern:0,extraz:0,f_x:0,f_y:0,factor:0,faculti:0,faith:0,fals:0,fancyarrowpatch:0,faster:0,fdr:0,fdr_bh:0,fdr_method:0,featur:0,feedback:0,fig:0,fig_ax:0,figsiz:0,figur:0,file:0,fill:0,filter:0,fine:0,first:0,fit:0,fit_model:0,fit_result:0,fit_total_effect:0,fit_wright_effect:0,fix:0,fix_all_edges_before_final_orient:0,fixed_thr:0,flag:0,flaxman:0,flexibl:0,follow:0,fontsiz:0,forbidden_nod:0,forc:0,forecast:0,form:0,format:0,forward:0,found:0,four:0,frac:0,fraction:0,framework:0,free:0,freedom:0,frenzel:0,frequenc:0,frequent:0,friendli:0,from:0,full:0,fullci:0,fulli:0,func:0,further:0,futur:0,gabor:0,gatewai:0,gauss_pr:0,gaussian:0,gaussianprocessregressor:0,gaussprocreg:0,gaussprocregtorch:0,generate_and_save_nulldist:0,generate_nulldist:0,gerhardu:0,get:0,get_ac:0,get_all_ac:0,get_all_amc:0,get_amc:0,get_analytic_confid:0,get_analytic_signific:0,get_bootstrap_confid:0,get_c:0,get_ce_max:0,get_coef:0,get_coeff:0,get_conditional_entropi:0,get_confid:0,get_corrected_pvalu:0,get_dependence_measur:0,get_fit:0,get_fixed_thres_signific:0,get_general_fitted_model:0,get_general_predict:0,get_graph_from_dict:0,get_graph_from_link:0,get_graph_from_pmatrix:0,get_lagged_depend:0,get_links_from_graph:0,get_mc:0,get_measur:0,get_medi:0,get_mediation_graph_data:0,get_model_selection_criterion:0,get_optimal_set:0,get_predictor:0,get_shuffle_signific:0,get_signific:0,get_test_arrai:0,get_train_arrai:0,get_tsg:0,get_val_matrix:0,github:0,give:0,given:0,going:0,gp_param:0,gpdc:0,gpdctorch:0,gpytorch:0,graph:0,graph_bool:0,graph_data:0,graph_is_mag:0,graph_typ:0,graphic:0,greater:0,grei:0,grey_masked_sampl:0,grid:0,ground:0,guarante:0,guidanc:0,handl:0,hard:0,has:0,has_path:0,hash:0,have:0,head:0,heavisid:0,heigth:0,help:0,helper:0,henc:0,here:0,hidden:0,hidden_vari:0,high:0,higher:0,histogram:0,hochberg:0,horizont:0,how:0,howev:0,html:0,http:0,hyper:0,hyperparamet:0,hypothesi:0,hypothet:0,identifi:0,iint:0,implement:0,impli:0,importantli:0,improv:0,includ:0,include_lagzero_link:0,include_lagzero_par:0,include_neighbor:0,incom:0,index:0,indirect:0,individu:0,inf:0,infin:0,info:0,inform:0,inherit:0,initi:0,initial_valu:0,inner_edg:0,inner_edge_styl:0,inno_cov:0,innov:0,input:0,instanc:0,instanti:0,instead:0,instruct:0,integ:0,intellig:0,interdisciplinari:0,interest:0,intern:0,interpret:0,interv:0,interven:0,intervent:0,intervention_data:0,intervention_typ:0,introduc:0,introduct:0,inv_inno_cov:0,invalid:0,invers:0,invit:0,irrelev:0,iter:0,its:0,itself:0,j_t:0,joint:0,journal:0,just:0,kei:0,kernel:0,kind:0,knn:0,kretschmer:0,kwarg:0,label:0,label_fonts:0,label_space_left:0,label_space_top:0,lag1:0,lag2:0,lag:0,lag_arrai:0,lag_mod:0,lag_unit:0,lagfunct:0,lagged_par:0,larg:0,larger:0,last:0,latent:0,later:0,latter:0,lead:0,learn:0,least:0,leav:0,left:0,legend:0,legend_fonts:0,legend_width:0,len:0,length:0,less:0,let:0,lett:0,level:0,lightgrei:0,like:0,likelihood:0,limit:0,lin_f:0,line:0,linear:0,linear_model:0,linearmedi:0,linearregress:0,linewidth:0,link:0,link_attribut:0,link_coeff:0,link_colorbar_label:0,link_frequ:0,link_label_fonts:0,link_matrix:0,link_width:0,links_coeff:0,links_to_graph:0,list:0,load:0,log:0,look:0,low:0,lower:0,lowhighpass_filt:0,made:0,mag:0,magnitud:0,mai:0,main:0,major:0,make:0,mani:0,map:0,margin:0,maria:0,mark:0,marker:0,markers:0,markov:0,mask:0,mask_typ:0,match:0,mathcal:0,matplotlib:0,matric:0,matrix:0,matter:0,max:0,max_combin:0,max_cond_px:0,max_conds_dim:0,max_conds_pi:0,max_conds_px:0,max_conds_px_lag:0,max_delai:0,max_lag:0,max_lag_or_tau_max:0,max_p_glob:0,max_p_non_ancestr:0,max_pds_set:0,max_q_glob:0,maxim:0,maximum:0,mce:0,mci:0,mean:0,measur:0,med:0,member:0,memori:0,method:0,method_arg:0,middl:0,might:0,minim:0,minimized_optim:0,minimum:0,minu:0,miss:0,missing_flag:0,mlr:0,mmr:0,mode:0,model_param:0,modul:0,modulo:0,momentari:0,more:0,most:0,most_frequent_link:0,mostli:0,motif:0,much:0,multi:0,multipl:0,multivari:0,must:0,mutual:0,n_preliminary_iter:0,n_symb:0,nail:0,name:0,nan:0,napds_t:0,natur:0,ncomms9502:0,nearest:0,necessari:0,need:0,neg:0,neighbor:0,nest:0,net_to_tsg:0,network:0,network_lower_bound:0,neural:0,neurip:0,never:0,nevertheless:0,new_data:0,niehgbor:0,no_apr:0,no_nois:0,no_non_ancestral_phas:0,node:0,node_aspect:0,node_colorbar_label:0,node_label_s:0,node_po:0,node_s:0,node_tick:0,nois:0,non:0,non_rep:0,none:0,nonlinear:0,nonstat:0,nonstationari:0,nonzero:0,normal:0,note:0,nowack:0,npz:0,null_dist:0,null_dist_filenam:0,nulldist:0,number:0,numer:0,numpi:0,object:0,observ:0,observed_var:0,occur:0,onc:0,one:0,onli:0,only_non_causal_path:0,opac:0,oper:0,opposit:0,optim:0,optimality_cond_des_ym:0,optimality_cond_i:0,optimz:0,option:0,oracl:0,oracleci:0,order:0,ordin:0,ordinal_patt_arrai:0,ordinari:0,org:0,orient:0,orient_comtemp:0,orient_contemp:0,origin:0,orrd:0,oset:0,oset_:0,other:0,otherwis:0,otion:0,ouput:0,out:0,outcom:0,output:0,over:0,overlaid:0,overlap:0,overrid:0,overwrit:0,p_matrix:0,packag:0,page:0,pair:0,pairwis:0,panel:0,paper:0,parallel:0,paramet:0,parametr:0,parcorr:0,parent:0,parent_node_id:0,parents_dict:0,parents_neighbors_coeff:0,parents_of_lag:0,part:0,partial:0,particular:0,pass:0,pass_period:0,path:0,path_node_arrai:0,path_val_matrix:0,pathwai:0,patt:0,patt_mask:0,patt_tim:0,pattern:0,pc1:0,pc_1:0,pc_alpha:0,pcmciplu:0,pdf:0,peak:0,pearl:0,pearson:0,percentil:0,perform:0,period:0,permut:0,perp:0,perspect:0,phase:0,phi:0,phy:0,physrev:0,pip:0,plai:0,pleas:0,plot_graph:0,plot_gridlin:0,plot_lagfunc:0,plot_mediation_graph:0,plot_mediation_time_series_graph:0,plot_time_series_graph:0,plot_timeseri:0,plot_tsg:0,point:0,pomp:0,pos:0,posit:0,possibl:0,post:0,potenti:0,power:0,pq_matrix:0,practic:0,pre:0,precis:0,precomput:0,pred_param:0,predict_total_effect:0,predict_wright_effect:0,prediction_model:0,predictor:0,prelim_onli:0,prelim_rul:0,prelim_with_collider_rul:0,preliminari:0,preprocess:0,present:0,preserv:0,press:0,previou:0,prime:0,print:0,print_array_info:0,print_info:0,print_result:0,print_significant_link:0,prior:0,priorit:0,prl:0,procedur:0,proceed:0,processor:0,project:0,proper:0,properti:0,provid:0,pseudcod:0,pseudoc:0,pseudocod:0,psi:0,purpos:0,pval:0,pval_max:0,pyplot:0,python:0,q_matrix:0,qualiti:0,quantifi:0,quantil:0,quantile_bin_arrai:0,quantiti:0,r10:0,r_x:0,r_y:0,rais:0,randn:0,random:0,randomst:0,rang:0,rank:0,rate:0,rather:0,ratio:0,rdbu_r:0,recal:0,recommend:0,reconstruct:0,recycle_residu:0,red:0,reduc:0,refer:0,regard:0,regress:0,regular:0,rel:0,relat:0,relationship:0,relev:0,remain:0,remember_only_par:0,remov:0,remove_missing_upto_maxlag:0,repeat:0,replac:0,repo:0,repres:0,requir:0,reset_lagged_link:0,residu:0,respect:0,restrict:0,result:0,return_cleaned_xyz:0,return_data:0,return_dict:0,return_null_dist:0,return_parents_dict:0,return_path:0,return_separate_set:0,return_significant_link:0,rev:0,rho:0,richardson:0,right:0,rizzo:0,robust:0,role:0,row:0,rtype:0,rule:0,run:0,run_bivci:0,run_fullci:0,run_lpcmci:0,run_mci:0,run_pc_stabl:0,run_pcalg:0,run_pcalg_non_timeseries_data:0,run_pcmci:0,run_pcmciplu:0,run_sliding_window_of:0,run_test:0,run_test_raw:0,rung:0,runge18a:0,runtim:0,s41467:0,same:0,sampl:0,sample_s:0,saniti:0,save:0,save_iter:0,save_nam:0,savefig:0,scale:0,sci:0,scienc:0,sciencemag:0,scikit:0,scipi:0,scitat:0,score:0,script:0,search:0,second:0,section:0,see:0,seed:0,seen:0,sejdinov:0,select:0,selected_link:0,selected_target:0,selected_vari:0,selection_var:0,self:0,separ:0,sepset:0,set:0,set_datafram:0,set_mask_typ:0,setter:0,setup:0,setup_arg:0,setup_matrix:0,sever:0,shape:0,shorter:0,should:0,show:0,show_colorbar:0,shown:0,shuffl:0,shuffle_neighbor:0,shuffle_test:0,side:0,sig_blocklength:0,sig_overrid:0,sig_sampl:0,sig_thr:0,sigma:0,signfic:0,signficic:0,signific:0,sim:0,simpl:0,simpli:0,sinc:0,size:0,skeleton:0,skip:0,skip_ticks_data_i:0,skip_ticks_data_x:0,sklearn:0,slice:0,slide:0,slightli:0,smaller:0,smooth:0,smooth_width:0,soft:0,some:0,sort:0,sound:0,sourc:0,space:0,spatial:0,spatio:0,special:0,special_nod:0,specif:0,specifi:0,spirt:0,squar:0,stack:0,standard:0,standard_color_link:0,standard_color_nod:0,standardscal:0,star:0,start:0,starts_with:0,stationar:0,statist:0,std:0,step:0,steps_ahead:0,still:0,stop:0,store:0,str:0,straight:0,strength:0,string:0,structur:0,structural_causal_process:0,student:0,style:0,sub:0,subplot:0,subset:0,subspac:0,suffici:0,suitabl:0,sum:0,sum_:0,summar:0,summari:0,summary_result:0,superset:0,supplement:0,suppli:0,support:0,sure:0,surrog:0,suscept:0,symb_arrai:0,symbol:0,symbolifi:0,symmetr:0,symmetrize_p_and_val_matrix:0,system:0,szeke:0,tail:0,take:0,taken:0,target:0,target_predictor:0,tau:0,tau_:0,tau_max:0,tau_min:0,tau_mix:0,taumax:0,techniqu:0,tempor:0,termin:0,test_indic:0,than:0,thei:0,them:0,themselv:0,theorem:0,theoret:0,thi:0,thm:0,those:0,threshold:0,through:0,tick:0,tickmark:0,tild:0,time_bin_length:0,time_bin_with_mask:0,time_label:0,time_lag:0,timelabel:0,togeth:0,top:0,toronto:0,total:0,toward:0,train:0,train_indic:0,transfer:0,transform:0,translat:0,tripl:0,true_par:0,true_parent_neighbor:0,truncat:0,truth:0,tsg:0,tsg_path_val_matrix:0,tsg_to_net:0,tune:0,tupl:0,tutori:0,twice:0,two:0,two_sided_thr:0,type:0,typic:0,uai2020:0,uai:0,uncertainti:0,unclear:0,uncondit:0,undecid:0,under:0,underli:0,undirect:0,uniform:0,uniqu:0,unit:0,unlik:0,unori:0,unrestrict:0,unshield:0,unshuffl:0,update_middle_mark:0,upper:0,use:0,use_a_pds_t_for_major:0,use_mask:0,used:0,useful:0,user:0,uses:0,using:0,v84:0,val:0,val_matrix:0,val_matrix_interv:0,val_matrix_mean:0,val_min:0,val_onli:0,valid:0,valu:0,var1:0,var2:0,var_nam:0,var_network:0,var_process:0,var_unit:0,vari:0,variabl:0,varianc:0,variant:0,varibl:0,variou:0,varlag:0,varx:0,vector:0,verbos:0,veri:0,vertic:0,via:0,view:0,visual:0,vmax_edg:0,vmax_nod:0,vmin_edg:0,vmin_nod:0,weight:0,weighted_avg_and_std:0,well:0,when:0,where:0,whether:0,which:0,whichev:0,wide:0,widehat:0,width:0,wildcard:0,window:0,window_length:0,window_step:0,within:0,without:0,work:0,worker:0,wrapper:0,wright:0,www:0,x_base:0,x_i:0,x_j:0,x_t:0,xyz:0,y_base:0,y_t:0,yield:0,you:0,z_i:0,z_j:0,z_t:0,zero:0},titles:["TIGRAMITE"],titleterms:{"function":0,analysi:0,causal:0,causal_effect:0,condit:0,data:0,data_process:0,effect:0,gener:0,independ:0,independence_test:0,indic:0,lpcmci:0,mediat:0,model:0,pcmci:0,plot:0,predict:0,process:0,seri:0,tabl:0,test:0,tigramit:0,time:0,toi:0,toymodel:0}}) \ No newline at end of file +Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.index":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"tigramite.causal_effects":{CausalEffects:[0,0,1,""]},"tigramite.causal_effects.CausalEffects":{check_XYS_paths:[0,1,1,""],check_optimality:[0,1,1,""],fit_bootstrap_of:[0,1,1,""],fit_total_effect:[0,1,1,""],fit_wright_effect:[0,1,1,""],get_graph_from_dict:[0,1,1,""],get_mediators:[0,1,1,""],get_optimal_set:[0,1,1,""],predict_bootstrap_of:[0,1,1,""],predict_total_effect:[0,1,1,""],predict_wright_effect:[0,1,1,""]},"tigramite.data_processing":{DataFrame:[0,0,1,""],lowhighpass_filter:[0,4,1,""],ordinal_patt_array:[0,4,1,""],quantile_bin_array:[0,4,1,""],smooth:[0,4,1,""],structural_causal_process:[0,4,1,""],time_bin_with_mask:[0,4,1,""],var_process:[0,4,1,""],weighted_avg_and_std:[0,4,1,""]},"tigramite.data_processing.DataFrame":{construct_array:[0,1,1,""],data:[0,3,1,""],datatime:[0,3,1,""],mask:[0,3,1,""],missing_flag:[0,3,1,""],print_array_info:[0,1,1,""],remove_missing_upto_maxlag:[0,3,1,""],var_names:[0,3,1,""]},"tigramite.independence_tests":{CMIknn:[0,0,1,""],CMIsymb:[0,0,1,""],CondIndTest:[0,0,1,""],GPDC:[0,0,1,""],GPDCtorch:[0,0,1,""],OracleCI:[0,0,1,""],ParCorr:[0,0,1,""]},"tigramite.independence_tests.CMIknn":{get_conditional_entropy:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CMIsymb":{get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CondIndTest":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_bootstrap_confidence:[0,1,1,""],get_confidence:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_fixed_thres_significance:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],get_significance:[0,1,1,""],measure:[0,1,1,""],print_info:[0,1,1,""],run_test:[0,1,1,""],run_test_raw:[0,1,1,""],set_dataframe:[0,1,1,""],set_mask_type:[0,1,1,""]},"tigramite.independence_tests.GPDC":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.GPDCtorch":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.OracleCI":{check_shortest_path:[0,1,1,""],get_confidence:[0,1,1,""],get_graph_from_links:[0,1,1,""],get_links_from_graph:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],measure:[0,1,1,""],run_test:[0,1,1,""],set_dataframe:[0,1,1,""]},"tigramite.independence_tests.ParCorr":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.lpcmci":{LPCMCI:[0,0,1,""]},"tigramite.lpcmci.LPCMCI":{run_lpcmci:[0,1,1,""]},"tigramite.models":{LinearMediation:[0,0,1,""],Models:[0,0,1,""],Prediction:[0,0,1,""]},"tigramite.models.LinearMediation":{fit_model:[0,1,1,""],get_ace:[0,1,1,""],get_acs:[0,1,1,""],get_all_ace:[0,1,1,""],get_all_acs:[0,1,1,""],get_all_amce:[0,1,1,""],get_amce:[0,1,1,""],get_ce:[0,1,1,""],get_ce_max:[0,1,1,""],get_coeff:[0,1,1,""],get_mce:[0,1,1,""],get_mediation_graph_data:[0,1,1,""],get_tsg:[0,1,1,""],get_val_matrix:[0,1,1,""],net_to_tsg:[0,1,1,""],tsg_to_net:[0,1,1,""]},"tigramite.models.Models":{get_coefs:[0,1,1,""],get_fit:[0,1,1,""],get_general_fitted_model:[0,1,1,""],get_general_prediction:[0,1,1,""],get_val_matrix:[0,1,1,""]},"tigramite.models.Prediction":{fit:[0,1,1,""],get_predictors:[0,1,1,""],get_test_array:[0,1,1,""],get_train_array:[0,1,1,""],predict:[0,1,1,""]},"tigramite.pcmci":{PCMCI:[0,0,1,""]},"tigramite.pcmci.PCMCI":{N:[0,3,1,""],T:[0,3,1,""],all_parents:[0,3,1,""],convert_to_string_graph:[0,1,1,""],get_corrected_pvalues:[0,1,1,""],get_graph_from_pmatrix:[0,1,1,""],get_lagged_dependencies:[0,1,1,""],iterations:[0,3,1,""],print_results:[0,1,1,""],print_significant_links:[0,1,1,""],pval_max:[0,3,1,""],return_parents_dict:[0,1,1,""],return_significant_links:[0,1,1,""],run_bivci:[0,1,1,""],run_fullci:[0,1,1,""],run_mci:[0,1,1,""],run_pc_stable:[0,1,1,""],run_pcalg:[0,1,1,""],run_pcalg_non_timeseries_data:[0,1,1,""],run_pcmci:[0,1,1,""],run_pcmciplus:[0,1,1,""],run_sliding_window_of:[0,1,1,""],symmetrize_p_and_val_matrix:[0,1,1,""],val_min:[0,3,1,""]},"tigramite.plotting":{plot_graph:[0,4,1,""],plot_lagfuncs:[0,4,1,""],plot_mediation_graph:[0,4,1,""],plot_mediation_time_series_graph:[0,4,1,""],plot_scatterplots:[0,4,1,""],plot_time_series_graph:[0,4,1,""],plot_timeseries:[0,4,1,""],plot_tsg:[0,4,1,""],setup_matrix:[0,0,1,""],setup_scatter_matrix:[0,0,1,""]},"tigramite.plotting.setup_matrix":{add_lagfuncs:[0,1,1,""],savefig:[0,1,1,""]},"tigramite.plotting.setup_scatter_matrix":{add_scatterplot:[0,1,1,""],adjustfig:[0,1,1,""]},"tigramite.toymodels":{structural_causal_processes:[0,2,0,"-"]},"tigramite.toymodels.structural_causal_processes":{links_to_graph:[0,4,1,""],structural_causal_process:[0,4,1,""],var_process:[0,4,1,""]},tigramite:{data_processing:[0,2,0,"-"],plotting:[0,2,0,"-"]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","module","Python module"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:module","3":"py:attribute","4":"py:function"},terms:{"21st":0,"2xtau_max":0,"36th":0,"579_main_pap":0,"8485ae387a981d783f8764e508151cd9":0,"94e70705efae423efda1088614128d0b":0,"abstract":0,"boolean":0,"break":0,"case":0,"class":0,"default":0,"float":0,"import":0,"int":0,"long":0,"new":0,"null":0,"return":0,"static":0,"true":0,"var":0,"while":0,ACE:0,ACS:0,For:0,Its:0,Not:0,OLS:0,The:0,Then:0,There:0,These:0,Used:0,Useful:0,Uses:0,Using:0,Will:0,With:0,_get_single_residu:0,_run_ancestral_removal_phas:0,_run_dsep_removal_phas:0,_run_non_ancestral_removal_phas:0,about:0,abov:0,abs:0,absent:0,absmax:0,absolut:0,accept:0,accord:0,account:0,ace:0,across:0,acs:0,act:0,actual:0,adapt:0,add:0,add_lagfunc:0,add_lagfunc_arg:0,add_scatterplot:0,add_scatterplot_arg:0,add_to_null_dist:0,added:0,adding:0,addit:0,address:0,adj:0,adjac:0,adjust:0,adjustfig:0,adjustment_set:0,admg:0,adv:0,advanc:0,affect:0,after:0,again:0,ahead:0,aic:0,aip:0,akaik:0,algorithm:0,all:0,all_lag:0,all_par:0,all_result:0,alloc:0,allow:0,along:0,alpha:0,alpha_level:0,alreadi:0,also:0,altern:0,alternative_condit:0,although:0,alwai:0,ambigu:0,ambiguous_tripl:0,amc:0,among:0,analyt:0,analyz:0,anc_all_i:0,anc_all_x:0,anc_all_z:0,anc_i:0,anc_x:0,anc_xi:0,ancestor:0,ancestr:0,ani:0,anoth:0,apds_t:0,appli:0,applic:0,appropri:0,apr:0,arang:0,arbitrari:0,argument:0,around:0,arrai:0,array_lik:0,array_mask:0,arrohead:0,arrow:0,arrow_linewidth:0,arrowhead_s:0,articl:0,artifici:0,arxiv:0,assess:0,assign:0,associ:0,assum:0,assumpt:0,ast:0,asymptot:0,attribut:0,au_i:0,au_j:0,auai:0,auto:0,auto_first:0,autocorrel:0,autocovari:0,autodepend:0,automat:0,autoregress:0,auxadmg:0,auxiliari:0,avail:0,averag:0,avoid:0,axes:0,axi:0,backdoor:0,backward:0,bakirov:0,bandwidth:0,base:0,basemap:0,been:0,befor:0,beforehand:0,begin:0,being:0,below:0,benjamini:0,best:0,beta:0,beta_i:0,beta_x:0,better:0,between:0,bia:0,bias:0,bin:0,bincount:0,bindata:0,bivci:0,black:0,block:0,blue:0,bold:0,bool:0,boot_blocklength:0,boot_sampl:0,bootsrap:0,bootstrap:0,both:0,bottom:0,bound:0,box:0,breadth:0,break_once_separ:0,briefli:0,butterworth:0,call:0,callabl:0,can:0,canada:0,canon:0,cardin:0,care:0,caus:0,causaleffect:0,cdot:0,certain:0,chain:0,chao:0,check:0,check_optim:0,check_optimality_cond:0,check_shortest_path:0,check_sm_overlap:0,check_xys_path:0,child:0,choic:0,chosen:0,cite:0,ckdtree:0,clash:0,clean:0,cmap_edg:0,cmap_nod:0,cmi:0,cmiknn:0,cmisymb:0,coef1:0,coef2:0,coeff:0,coeffici:0,collid:0,collider_par:0,colliders_minimized_optim:0,colliders_onli:0,color:0,colorbar:0,colormap:0,column:0,com:0,combin:0,come:0,command:0,common:0,commun:0,compar:0,comparison:0,compat:0,complex:0,comprehens:0,comput:0,compute_ancestor:0,concret:0,cond_ind_test:0,condindtest:0,conditional_estim:0,conditional_model:0,conditions_data:0,conduct:0,conf_blocklength:0,conf_lev:0,conf_low:0,conf_matrix:0,conf_sampl:0,conf_upp:0,confer:0,confid:0,confidence_interv:0,conflict:0,conflict_resolut:0,confound:0,conserv:0,consid:0,consider:0,considerd:0,consist:0,constant:0,constrain:0,construct:0,construct_arrai:0,constructor:0,contain:0,contemp_collider_rul:0,contemp_cond:0,contemporan:0,content:0,continu:0,contrast:0,control:0,conveni:0,convert:0,convert_to_string_graph:0,coordin:0,correct:0,corrected_a:0,correl:0,correspond:0,cost:0,could:0,coupl:0,covari:0,creat:0,criteria:0,criterion:0,cross:0,cube:0,current:0,curv:0,curvatur:0,curved_radiu:0,cut_off:0,cutoff:0,cutperiod:0,cython:0,d_z:0,dag:0,dash:0,data_linewidth:0,data_transform:0,datafram:0,dataset:0,datatim:0,dcor:0,debug:0,decai:0,def:0,default_rng:0,defin:0,definin:0,degre:0,delai:0,denot:0,densiti:0,depend:0,dependence_measur:0,depict:0,deprec:0,depth:0,deriv:0,describ:0,descript:0,detail:0,detect:0,determin:0,deviat:0,dict:0,dictionari:0,differ:0,digamma:0,digest:0,dim:0,dimens:0,dimension:0,direct:0,direction:0,directli:0,disabl:0,discov:0,discoveri:0,discret:0,discuss:0,disk:0,dismiss:0,dist:0,distanc:0,distribut:0,do_check:0,doc:0,doe:0,doi:0,dpag:0,draw:0,drawn:0,driver:0,due:0,dummi:0,duplic:0,dure:0,eaau4996:0,each:0,easi:0,edg:0,edge_tick:0,effici:0,either:0,element:0,els:0,eman:0,embed:0,empti:0,end:0,ends_with:0,ensur:0,entir:0,entri:0,entropi:0,enumer:0,epsilon_:0,equal:0,equival:0,error:0,estim:0,estimate_confid:0,eta:0,etc:0,evalu:0,even:0,everi:0,exampl:0,except:0,exclud:0,exclude_contemporan:0,exclude_i:0,exclude_j:0,exclude_k:0,exclude_self_effect:0,execut:0,exist:0,expect:0,experi:0,experiment:0,explain:0,extern:0,extraz:0,f_x:0,f_y:0,factor:0,faculti:0,faith:0,fals:0,fancyarrowpatch:0,faster:0,fdr:0,fdr_bh:0,fdr_method:0,featur:0,feedback:0,fig:0,fig_ax:0,figsiz:0,figur:0,file:0,fill:0,filter:0,fine:0,first:0,fit:0,fit_bootstrap_of:0,fit_model:0,fit_result:0,fit_total_effect:0,fit_wright_effect:0,fix:0,fix_all_edges_before_final_orient:0,fixed_thr:0,flag:0,flaxman:0,flexibl:0,follow:0,fontsiz:0,forbidden_nod:0,forc:0,forecast:0,form:0,format:0,forward:0,found:0,four:0,frac:0,fraction:0,framework:0,free:0,freedom:0,frenzel:0,frequenc:0,frequent:0,friendli:0,from:0,full:0,fullci:0,fulli:0,func:0,further:0,futur:0,gabor:0,gatewai:0,gauss_pr:0,gaussian:0,gaussianprocessregressor:0,gaussprocreg:0,gaussprocregtorch:0,generate_and_save_nulldist:0,generate_nulldist:0,gerhardu:0,get:0,get_ac:0,get_all_ac:0,get_all_amc:0,get_amc:0,get_analytic_confid:0,get_analytic_signific:0,get_bootstrap_confid:0,get_c:0,get_ce_max:0,get_coef:0,get_coeff:0,get_conditional_entropi:0,get_confid:0,get_corrected_pvalu:0,get_dependence_measur:0,get_fit:0,get_fixed_thres_signific:0,get_general_fitted_model:0,get_general_predict:0,get_graph_from_dict:0,get_graph_from_link:0,get_graph_from_pmatrix:0,get_lagged_depend:0,get_links_from_graph:0,get_mc:0,get_measur:0,get_medi:0,get_mediation_graph_data:0,get_model_selection_criterion:0,get_optimal_set:0,get_predictor:0,get_shuffle_signific:0,get_signific:0,get_test_arrai:0,get_train_arrai:0,get_tsg:0,get_val_matrix:0,github:0,give:0,given:0,going:0,gp_param:0,gpdc:0,gpdctorch:0,gpytorch:0,graph:0,graph_bool:0,graph_data:0,graph_is_mag:0,graph_typ:0,graphic:0,greater:0,grei:0,grey_masked_sampl:0,grid:0,ground:0,guarante:0,guidanc:0,handl:0,hard:0,has:0,has_path:0,hash:0,have:0,head:0,heavisid:0,heigth:0,help:0,helper:0,henc:0,here:0,hidden:0,hidden_vari:0,high:0,higher:0,histogram:0,hochberg:0,horizont:0,how:0,howev:0,html:0,http:0,hyper:0,hyperparamet:0,hypothesi:0,hypothet:0,identifi:0,iint:0,implement:0,impli:0,importantli:0,improv:0,includ:0,include_lagzero_link:0,include_lagzero_par:0,include_neighbor:0,incom:0,index:0,indirect:0,individu:0,inf:0,infin:0,info:0,inform:0,inherit:0,initi:0,initial_valu:0,inner_edg:0,inner_edge_styl:0,inno_cov:0,innov:0,input:0,instanc:0,instanti:0,instead:0,instruct:0,integ:0,intellig:0,interdisciplinari:0,interest:0,intern:0,interpret:0,interv:0,interven:0,intervent:0,intervention_data:0,intervention_typ:0,introduc:0,introduct:0,inv_inno_cov:0,invalid:0,invers:0,inverse_transform:0,invit:0,irrelev:0,iter:0,its:0,itself:0,j_t:0,joint:0,journal:0,just:0,kei:0,kernel:0,kind:0,knn:0,kretschmer:0,kwarg:0,label:0,label_fonts:0,label_space_left:0,label_space_top:0,lag1:0,lag2:0,lag:0,lag_arrai:0,lag_mod:0,lag_unit:0,lagfunct:0,lagged_par:0,larg:0,larger:0,last:0,latent:0,later:0,latter:0,lead:0,learn:0,least:0,leav:0,left:0,legend:0,legend_fonts:0,legend_width:0,len:0,length:0,less:0,let:0,lett:0,level:0,lightgrei:0,like:0,likelihood:0,limit:0,lin_f:0,line:0,linear:0,linear_model:0,linearmedi:0,linearregress:0,linewidth:0,link:0,link_attribut:0,link_coeff:0,link_colorbar_label:0,link_frequ:0,link_label_fonts:0,link_matrix:0,link_width:0,links_coeff:0,links_to_graph:0,list:0,load:0,log:0,look:0,low:0,lower:0,lowhighpass_filt:0,made:0,mag:0,magnitud:0,mai:0,main:0,major:0,make:0,mani:0,map:0,margin:0,maria:0,mark:0,marker:0,markers:0,markov:0,mask:0,mask_typ:0,match:0,mathcal:0,matplotlib:0,matric:0,matrix:0,matter:0,max:0,max_combin:0,max_cond_px:0,max_conds_dim:0,max_conds_pi:0,max_conds_px:0,max_conds_px_lag:0,max_delai:0,max_lag:0,max_lag_or_tau_max:0,max_p_glob:0,max_p_non_ancestr:0,max_pds_set:0,max_q_glob:0,maxim:0,maximum:0,mce:0,mci:0,mean:0,measur:0,med:0,member:0,memori:0,method:0,method_arg:0,middl:0,might:0,minim:0,minimized_optim:0,minimum:0,minu:0,miss:0,missing_flag:0,mlr:0,mmr:0,mode:0,model_param:0,modul:0,modulo:0,momentari:0,more:0,most:0,most_frequent_link:0,mostli:0,motif:0,much:0,multi:0,multipl:0,multivari:0,must:0,mutual:0,n_preliminary_iter:0,n_symb:0,nail:0,name:0,nan:0,napds_t:0,natur:0,ncomms9502:0,nearest:0,necessari:0,need:0,neg:0,neighbor:0,nest:0,net_to_tsg:0,network:0,network_lower_bound:0,neural:0,neurip:0,never:0,nevertheless:0,new_data:0,niehgbor:0,no_apr:0,no_nois:0,no_non_ancestral_phas:0,node:0,node_aspect:0,node_colorbar_label:0,node_label_s:0,node_po:0,node_s:0,node_tick:0,nois:0,non:0,non_rep:0,none:0,nonlinear:0,nonstat:0,nonstationari:0,nonzero:0,normal:0,note:0,nowack:0,npz:0,null_dist:0,null_dist_filenam:0,nulldist:0,number:0,numer:0,numpi:0,object:0,observ:0,observed_var:0,occur:0,onc:0,one:0,onli:0,only_non_causal_path:0,opac:0,oper:0,opposit:0,optim:0,optimality_cond_des_ym:0,optimality_cond_i:0,optimz:0,option:0,oracl:0,oracleci:0,order:0,ordin:0,ordinal_patt_arrai:0,ordinari:0,org:0,orient:0,orient_comtemp:0,orient_contemp:0,origin:0,orrd:0,oset:0,oset_:0,other:0,otherwis:0,otion:0,ouput:0,out:0,outcom:0,output:0,over:0,overlaid:0,overlap:0,overrid:0,overwrit:0,p_matrix:0,packag:0,page:0,pair:0,pairwis:0,panel:0,paper:0,parallel:0,paramet:0,parametr:0,parcorr:0,parent:0,parent_node_id:0,parents_dict:0,parents_neighbors_coeff:0,parents_of_lag:0,part:0,partial:0,particular:0,pass:0,pass_period:0,path:0,path_node_arrai:0,path_val_matrix:0,pathwai:0,patt:0,patt_mask:0,patt_tim:0,pattern:0,pc1:0,pc_1:0,pc_alpha:0,pcmciplu:0,pdf:0,peak:0,pearl:0,pearson:0,percentil:0,perform:0,period:0,permut:0,perp:0,perspect:0,phase:0,phi:0,phy:0,physrev:0,pip:0,plai:0,pleas:0,plot_graph:0,plot_gridlin:0,plot_lagfunc:0,plot_mediation_graph:0,plot_mediation_time_series_graph:0,plot_scatterplot:0,plot_time_series_graph:0,plot_timeseri:0,plot_tsg:0,point:0,pomp:0,pos:0,posit:0,possibl:0,post:0,potenti:0,power:0,pq_matrix:0,practic:0,pre:0,precis:0,precomput:0,pred_param:0,predict_bootstrap_of:0,predict_total_effect:0,predict_wright_effect:0,prediction_model:0,predictor:0,prelim_onli:0,prelim_rul:0,prelim_with_collider_rul:0,preliminari:0,preprocess:0,present:0,preserv:0,press:0,previou:0,prime:0,print:0,print_array_info:0,print_info:0,print_result:0,print_significant_link:0,prior:0,priorit:0,prl:0,procedur:0,proceed:0,processor:0,project:0,proper:0,properti:0,provid:0,pseudcod:0,pseudoc:0,pseudocod:0,psi:0,purpos:0,pval:0,pval_max:0,pyplot:0,python:0,q_matrix:0,qualiti:0,quantifi:0,quantil:0,quantile_bin_arrai:0,quantiti:0,r10:0,r_x:0,r_y:0,rais:0,randn:0,random:0,randomst:0,rang:0,rank:0,rate:0,rather:0,ratio:0,rdbu_r:0,recal:0,recommend:0,reconstruct:0,recycle_residu:0,red:0,reduc:0,refer:0,regard:0,regress:0,regular:0,rel:0,relat:0,relationship:0,relev:0,remain:0,remember_only_par:0,remov:0,remove_missing_upto_maxlag:0,repeat:0,replac:0,repo:0,repres:0,requir:0,reset_lagged_link:0,residu:0,respect:0,restrict:0,result:0,return_cleaned_xyz:0,return_data:0,return_dict:0,return_further_pred_result:0,return_null_dist:0,return_parents_dict:0,return_path:0,return_separate_set:0,return_significant_link:0,rev:0,rho:0,richardson:0,right:0,rizzo:0,robust:0,role:0,row:0,rtype:0,rule:0,run:0,run_bivci:0,run_fullci:0,run_lpcmci:0,run_mci:0,run_pc_stabl:0,run_pcalg:0,run_pcalg_non_timeseries_data:0,run_pcmci:0,run_pcmciplu:0,run_sliding_window_of:0,run_test:0,run_test_raw:0,rung:0,runge18a:0,runtim:0,s41467:0,same:0,sampl:0,sample_s:0,saniti:0,save:0,save_iter:0,save_nam:0,savefig:0,scale:0,scatter:0,scatter_lag:0,scatterplot:0,sci:0,scienc:0,sciencemag:0,scikit:0,scipi:0,scitat:0,score:0,script:0,search:0,second:0,section:0,see:0,seed:0,seen:0,sejdinov:0,select:0,selected_link:0,selected_target:0,selected_vari:0,selection_var:0,self:0,separ:0,sepset:0,set:0,set_datafram:0,set_mask_typ:0,setter:0,setup:0,setup_arg:0,setup_matrix:0,setup_scatter_matrix:0,sever:0,shape:0,shift:0,shorter:0,should:0,show:0,show_colorbar:0,shown:0,shuffl:0,shuffle_neighbor:0,shuffle_test:0,side:0,sig_blocklength:0,sig_overrid:0,sig_sampl:0,sig_thr:0,sigma:0,signfic:0,signficic:0,signific:0,sim:0,simpl:0,simpli:0,sinc:0,size:0,skeleton:0,skip:0,skip_ticks_data_i:0,skip_ticks_data_x:0,sklearn:0,slice:0,slide:0,slightli:0,smaller:0,smooth:0,smooth_width:0,soft:0,some:0,sort:0,sound:0,sourc:0,space:0,spatial:0,spatio:0,special:0,special_nod:0,specif:0,specifi:0,spirt:0,squar:0,stack:0,standard:0,standard_color_link:0,standard_color_nod:0,standardscal:0,star:0,start:0,starts_with:0,stationar:0,statist:0,std:0,step:0,steps_ahead:0,still:0,stop:0,store:0,str:0,straight:0,strength:0,string:0,structur:0,structural_causal_process:0,student:0,style:0,sub:0,subplot:0,subset:0,subspac:0,suffici:0,suitabl:0,sum:0,sum_:0,summar:0,summari:0,summary_result:0,superset:0,supplement:0,suppli:0,support:0,sure:0,surrog:0,suscept:0,symb_arrai:0,symbol:0,symbolifi:0,symmetr:0,symmetrize_p_and_val_matrix:0,system:0,szeke:0,tail:0,take:0,taken:0,target:0,target_predictor:0,tau:0,tau_:0,tau_max:0,tau_min:0,tau_mix:0,taumax:0,techniqu:0,tempor:0,termin:0,test_indic:0,than:0,thei:0,them:0,themselv:0,theorem:0,theoret:0,thi:0,thm:0,those:0,threshold:0,through:0,tick:0,tickmark:0,tild:0,time_bin_length:0,time_bin_with_mask:0,time_label:0,time_lag:0,timelabel:0,togeth:0,top:0,toronto:0,total:0,toward:0,train:0,train_indic:0,transfer:0,transform:0,translat:0,tripl:0,true_par:0,true_parent_neighbor:0,truncat:0,truth:0,tsg:0,tsg_path_val_matrix:0,tsg_to_net:0,tune:0,tupl:0,tutori:0,twice:0,two:0,two_sided_thr:0,type:0,typic:0,uai2020:0,uai:0,uncertainti:0,unclear:0,uncondit:0,undecid:0,under:0,underli:0,undirect:0,uniform:0,uniqu:0,unit:0,unlik:0,unori:0,unrestrict:0,unshield:0,unshuffl:0,update_middle_mark:0,upper:0,use:0,use_a_pds_t_for_major:0,use_mask:0,used:0,useful:0,user:0,uses:0,using:0,v84:0,val:0,val_matrix:0,val_matrix_interv:0,val_matrix_mean:0,val_min:0,val_onli:0,valid:0,valu:0,var1:0,var2:0,var_nam:0,var_network:0,var_process:0,var_unit:0,vari:0,variabl:0,varianc:0,variant:0,varibl:0,variou:0,varlag:0,varx:0,vector:0,verbos:0,veri:0,vertic:0,via:0,view:0,visual:0,vmax_edg:0,vmax_nod:0,vmin_edg:0,vmin_nod:0,weight:0,weighted_avg_and_std:0,well:0,when:0,where:0,whether:0,which:0,whichev:0,wide:0,widehat:0,width:0,wildcard:0,window:0,window_length:0,window_step:0,within:0,without:0,work:0,worker:0,wrapper:0,wright:0,www:0,x_base:0,x_i:0,x_j:0,x_t:0,xyz:0,y_base:0,y_t:0,yield:0,you:0,z_i:0,z_j:0,z_t:0,zero:0},titles:["TIGRAMITE"],titleterms:{"function":0,analysi:0,causal:0,causal_effect:0,condit:0,data:0,data_process:0,effect:0,gener:0,independ:0,independence_test:0,indic:0,lpcmci:0,mediat:0,model:0,pcmci:0,plot:0,predict:0,process:0,seri:0,tabl:0,test:0,tigramit:0,time:0,toi:0,toymodel:0}}) \ No newline at end of file diff --git a/docs/_modules/tigramite/causal_effects.html b/docs/_modules/tigramite/causal_effects.html index b88b016c..9b668b6e 100644 --- a/docs/_modules/tigramite/causal_effects.html +++ b/docs/_modules/tigramite/causal_effects.html @@ -56,6 +56,7 @@

    Source code for tigramite.causal_effects

     # License: GNU General Public License v3.0
     
     import numpy as np
    +import math
     import itertools
     from copy import deepcopy
     from collections import defaultdict
    @@ -185,6 +186,8 @@ 

    Source code for tigramite.causal_effects

             # print(self.graph.shape)
             self._check_graph(self.graph)
     
    +        self._check_XYS()
    +
             self.ancX = self._get_ancestors(X)
             self.ancY = self._get_ancestors(Y)
             self.ancS = self._get_ancestors(S)
    @@ -402,6 +405,18 @@ 

    Source code for tigramite.causal_effects

             #     self.graph_type = "tsg_admg"
             # else:
     
    +    def _check_XYS(self):
    +        """Check whether XYS are sober.
    +        """
    +
    +        XYS = self.X.union(self.Y).union(self.S)
    +        for xys in XYS:
    +            var, lag = xys 
    +            if var < 0 or var >= self.N:
    +                raise ValueError("XYS vars must be in [0...N]")
    +            if lag < -self.tau_max or lag > 0:
    +                raise ValueError("XYS lags must be in [-taumax...0]")
    +
     
     
    [docs] def check_XYS_paths(self): """Check whether one can remove nodes from X and Y with no proper causal paths. @@ -1855,6 +1870,10 @@

    Source code for tigramite.causal_effects

             conditional_estimator=None,  
             data_transform=None,
             mask_type=None,
    +        # estimate_confidence=False,
    +        # boot_samples=100,
    +        # boot_blocklength=1,
    +        # conf_lev=0.95, seed=None
             ):
             """Returns a fitted model for the total causal effect of X on Y 
                conditional on S.
    @@ -1923,9 +1942,70 @@ 

    Source code for tigramite.causal_effects

                     Y=self.listY, X=self.listX, Z=list(self.adjustment_set),
                     conditions=self.listS,
                     tau_max=self.tau_max,
    -                cut_off='max_lag_or_tau_max',
    +                cut_off='tau_max',
                     return_data=False)
     
    +        # # Optionally estimate confidence bounds via bootstrap
    +        # self.estimate_confidence = estimate_confidence
    +        # self.conf_lev = conf_lev
    +        # if self.estimate_confidence:
    +        #     self.bootstrap_results = {}
    +        #     random_state = np.random.default_rng(seed)
    +
    +        #     # Extract max_lag to construct bootstrap draws
    +        #     XYZ = self.listY + \
    +        #           self.listX + \
    +        #           list(self.adjustment_set) + \
    +        #           self.listS
    +        #     max_lag = max(abs(np.array(XYZ)[:, 1].min()), self.tau_max)
    +
    +        #     # Determine the number of blocks total, rounding up for non-integer
    +        #     # amounts
    +        #     n_blks = int(math.ceil(float(T-max_lag)/boot_blocklength))
    +
    +        #     if n_blks < 10:
    +        #         raise ValueError("Only %d block(s) for block-sampling,"  %n_blks +
    +        #                          "choose smaller boot_blocklength!")
    +
    +
    +        #     if self.verbosity > 0:
    +        #         print("\n##\n## Running bootstrap confidence estimate"  +
    +        #               "\n##\n" +
    +        #               "\nboot_samples = %s \n" % boot_samples +
    +        #               "\nboot_blocklength = %s \n" % boot_blocklength
    +        #               )
    +        #     boot_dataframe = deepcopy(dataframe)
    +        #     for b in range(boot_samples):
    +        #         # Get the starting indices for the blocks
    +        #         blk_strt = random_state.integers(max_lag, T - boot_blocklength + 1, n_blks)
    +        #         # Get the empty array of block resampled values
    +        #         boot_draw = np.zeros(n_blks*boot_blocklength, dtype='int')
    +        #         # Fill the array of block resamples
    +        #         for i in range(boot_blocklength):
    +        #             boot_draw[i::boot_blocklength] = np.arange(0, T, dtype='int')[blk_strt + i]
    +        #         # Cut to proper length
    +        #         boot_draw = boot_draw[:T-max_lag]
    +
    +        #         # boot_draw = random_state.integers(2*tau_max, T, size=T-2*tau_max)
    +        #         boot_dataframe.bootstrap = boot_draw
    +                
    +        #         # Fit model of Y on X and Z (and conditions)
    +        #         # Build the model
    +        #         self.bootstrap_results[b] = Models(
    +        #                         dataframe=boot_dataframe,
    +        #                         model=estimator,
    +        #                         conditional_model=conditional_estimator,
    +        #                         data_transform=data_transform,
    +        #                         mask_type=mask_type,
    +        #                         verbosity=self.verbosity)      
    +
    +        #         self.bootstrap_results[b].get_general_fitted_model(
    +        #                 Y=self.listY, X=self.listX, Z=list(self.adjustment_set),
    +        #                 conditions=self.listS,
    +        #                 tau_max=self.tau_max,
    +        #                 cut_off='max_lag_or_tau_max',
    +        #                 return_data=False)
    +
             return self
    # @profile @@ -1933,6 +2013,7 @@

    Source code for tigramite.causal_effects

             intervention_data, 
             conditions_data=None,
             pred_params=None,
    +        return_further_pred_results=False,
             ):
             """Predict effect of intervention with fitted model.
     
    @@ -1946,10 +2027,14 @@ 

    Source code for tigramite.causal_effects

                 Numpy array of shape (time, len(S)) that contains the S=s values.
             pred_params : dict, optional
                 Optional parameters passed on to sklearn prediction function.
    +        return_further_pred_results : bool, optional (default: False)
    +            In case the predictor class returns more than just the expected value,
    +            the entire results can be returned.
     
             Returns
             -------
             Results from prediction: an array of shape  (time, len(Y)).
    +        If estimate_confidence = True, then a tuple is returned.
             """
     
             if intervention_data.shape[1] != len(self.listX):
    @@ -1969,10 +2054,37 @@ 

    Source code for tigramite.causal_effects

             effect = self.model.get_general_prediction(
                 intervention_data=intervention_data,
                 conditions_data=conditions_data,
    -            pred_params=pred_params) 
    +            pred_params=pred_params,
    +            return_further_pred_results=return_further_pred_results) 
     
             return effect
    + # # Optionally get confidence bounds + # if self.estimate_confidence: + # lenY = len(self.listY) + # intervention_T, lenX = intervention_data.shape + # boot_samples = len(self.bootstrap_results) + # bootstrap_predicted_array = np.zeros((boot_samples, intervention_T, lenY)) + # for b in self.bootstrap_results.keys(): + # boot_effect = self.bootstrap_results[b].get_general_prediction( + # intervention_data=intervention_data, + # conditions_data=conditions_data, + # pred_params=pred_params, + # return_further_pred_results=return_further_pred_results) + # if return_further_pred_results: + # bootstrap_predicted_array[b] = boot_effect[0] + # else: + # bootstrap_predicted_array[b] = boot_effect + + # # Confidence intervals for val_matrix; interval is two-sided + # c_int = (1. - (1. - self.conf_lev)/2.) + # confidence_interval = np.percentile( + # bootstrap_predicted_array, axis=0, + # q = [100*(1. - c_int), 100*c_int]) + # return effect, confidence_interval + # else: + # return effect + # @profile
    [docs] def fit_wright_effect(self, dataframe, @@ -2080,7 +2192,7 @@

    Source code for tigramite.causal_effects

                         fit_res = self.model.get_general_fitted_model(
                             Y=[medy], X=[par], Z=oset,
                             tau_max=self.tau_max,
    -                        cut_off='max_lag_or_tau_max',
    +                        cut_off='tau_max',
                             return_data=False)
                         coeffs[medy][par] = fit_res[medy]['model'].coef_[0]
                         # print(mediators, par, medy, coeffs[medy][par])
    @@ -2100,7 +2212,7 @@ 

    Source code for tigramite.causal_effects

                         Y=[medy], X=list(all_parents), Z=[],
                         conditions=None,
                         tau_max=self.tau_max,
    -                    cut_off='max_lag_or_tau_max',
    +                    cut_off='tau_max',
                         return_data=False)
     
                     for ipar, par in enumerate(all_parents):
    @@ -2125,13 +2237,15 @@ 

    Source code for tigramite.causal_effects

     
                     effect[(x, y)] += effect_here
                    
    +        # Make fitted coefficients available as attribute
    +        self.coeffs = coeffs
     
             # Modify and overwrite variables in self.model
             self.model.Y = self.listY
             self.model.X = self.listX  
             self.model.Z = []
             self.model.conditions = [] 
    -        self.model.cut_off = 'max_lag_or_tau_max'
    +        self.model.cut_off = 'tau_max' # 'max_lag_or_tau_max'
     
             class dummy_fit_class():
                 def __init__(self, y_here, listX_here, effect_here):
    @@ -2214,6 +2328,157 @@ 

    Source code for tigramite.causal_effects

     
             return predicted_array
    + +
    [docs] def fit_bootstrap_of(self, method, method_args, + boot_samples=1000, + boot_blocklength=1, + seed=None): + """Runs chosen method on bootstrap samples drawn from DataFrame. + + Bootstraps for tau=0 are drawn from [max_lag, ..., T] and all lagged + variables constructed in DataFrame.construct_array are consistently + shifted with respect to this bootsrap sample to ensure that lagged + relations in the bootstrap sample are preserved. + + This function fits the models, predict_bootstrap_of can then be used + to get confidence intervals for the effect of interventions. + + Parameters + ---------- + method : str + Chosen method among valid functions in this class. + method_args : dict + Arguments passed to method. + boot_samples : int + Number of bootstrap samples to draw. + boot_blocklength : int, optional (default: 1) + Block length for block-bootstrap. + seed : int, optional(default = None) + Seed for RandomState (default_rng) + """ + + valid_methods = ['fit_total_effect', + 'fit_wright_effect', + ] + + if method not in valid_methods: + raise ValueError("method must be one of %s" % str(valid_methods)) + + # First call the method on the original dataframe + # to make available adjustment set etc + getattr(self, method)(**method_args) + + self.original_model = deepcopy(self.model) + + T = self.model.T + + # # Extract max_lag to construct bootstrap draws + # XYZ = self.listY + \ + # self.listX + \ + # list(self.adjustment_set) + \ + # self.listS + max_lag = self.tau_max #max(abs(np.array(XYZ)[:, 1].min()), self.tau_max) + + # Init seed + random_state = np.random.default_rng(seed) + + # Determine the number of blocks total, rounding up for non-integer + # amounts + n_blks = int(math.ceil(float(T-max_lag)/boot_blocklength)) + + if n_blks < 10: + raise ValueError("Only %d block(s) for block-sampling," %n_blks + + "choose smaller boot_blocklength!") + + if self.verbosity > 0: + print("\n##\n## Running Bootstrap of %s " % method + + "\n##\n" + + "\nboot_samples = %s \n" % boot_samples + + "\nboot_blocklength = %s \n" % boot_blocklength + ) + + method_args_bootstrap = deepcopy(method_args) + self.bootstrap_results = {} + + for b in range(boot_samples): + # Get the starting indices for the blocks + blk_strt = random_state.integers(max_lag, T - boot_blocklength + 1, n_blks) + # Get the empty array of block resampled values + boot_draw = np.zeros(n_blks*boot_blocklength, dtype='int') + # Fill the array of block resamples + for i in range(boot_blocklength): + boot_draw[i::boot_blocklength] = np.arange(0, T, dtype='int')[blk_strt + i] + # Cut to proper length + boot_draw = boot_draw[:T-max_lag] + + # Replace dataframe in method args by bootstrapped dataframe + method_args_bootstrap['dataframe'].bootstrap = boot_draw + + # Call method and save fitted model + getattr(self, method)(**method_args_bootstrap) + self.bootstrap_results[b] = deepcopy(self.model) + + # Reset model + self.model = self.original_model + + return self
    + + +
    [docs] def predict_bootstrap_of(self, method, method_args, + conf_lev=0.9): + """Predicts with fitted bootstraps. + + To be used after fitting with fit_bootstrap_of. Only uses the + expected values of the predict function, not potential other output. + + Parameters + ---------- + method : str + Chosen method among valid functions in this class. + method_args : dict + Arguments passed to method. + conf_lev : float, optional (default: 0.9) + Two-sided confidence interval. + + Returns + ------- + confidence_intervals : numpy array of + """ + + valid_methods = ['predict_total_effect', + 'predict_wright_effect', + ] + + if method not in valid_methods: + raise ValueError("method must be one of %s" % str(valid_methods)) + + + lenY = len(self.listY) + intervention_T, lenX = method_args['intervention_data'].shape + boot_samples = len(self.bootstrap_results) + bootstrap_predicted_array = np.zeros((boot_samples, intervention_T, lenY)) + + for b in self.bootstrap_results.keys(): + self.model = self.bootstrap_results[b] + boot_effect = getattr(self, method)(**method_args) + + if isinstance(boot_effect, tuple): + bootstrap_predicted_array[b] = boot_effect[0] + else: + bootstrap_predicted_array[b] = boot_effect + + # Reset model + self.model = self.original_model + + # Confidence intervals for val_matrix; interval is two-sided + c_int = (1. - (1. - conf_lev)/2.) + confidence_interval = np.percentile( + bootstrap_predicted_array, axis=0, + q = [100*(1. - c_int), 100*c_int])[:,:,0] + + return confidence_interval
    + +
    [docs] @staticmethod def get_graph_from_dict(links, tau_max=None): """Helper function to convert dictionary of links to graph array format. @@ -2299,72 +2564,108 @@

    Source code for tigramite.causal_effects

         import sklearn
         from sklearn.linear_model import LinearRegression
     
    -    T = 1000
    +    T = 100
         def lin_f(x): return x
         auto_coeff = 0.3
         coeff = 2.
         links = {
                 0: [((0, -1), auto_coeff, lin_f)], 
                 1: [((1, -1), auto_coeff, lin_f), ((0, -1), coeff, lin_f)], 
    -            2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
    +            # 2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
                 }
         data, nonstat = toys.structural_causal_process(links, T=T, 
                                     noises=None, seed=7)
     
         # Create some missing values
         data[-10:,:] = 999.
    -    dataframe = pp.DataFrame(data, missing_flag=999.) 
    +    var_names = range(2)
    +    dataframe = pp.DataFrame(data, var_names=var_names,
    +     missing_flag=999.) 
     
     
         # Construct expert knowledge graph from links here 
    -    links = {0: [(0, -1)],
    -             1: [(1, -1), (0, -1)],
    -             2: [(2, -1), (1, 0),],
    -             }
    +    # links = {0: [(0, -1)],
    +    #          1: [(1, -1), (0, -1)],
    +    #          2: [(2, -1), (1, 0),],
    +    #          }
         # Use staticmethod to get graph
         graph = CausalEffects.get_graph_from_dict(links, tau_max=None)
         
         # We are interested in lagged total effect of X on Y
         X = [(0, -1)]
    -    Y = [(2, 0)]
    +    Y = [(1, 0)]
     
         # Initialize class as `stationary_dag`
         causal_effects = CausalEffects(graph, graph_type='stationary_dag', 
                                     X=X, Y=Y, S=None, 
                                     hidden_variables=None, 
    -                                verbosity=5)
    +                                verbosity=0)
     
    -    print(data)
    +    # print(data)
         # Optimal adjustment set (is used by default)
         # print(causal_effects.get_optimal_set())
     
         # # Fit causal effect model from observational data
    -    # causal_effects.fit_total_effect(
    -    #     dataframe=dataframe, 
    -    #     # mask_type='y',
    -    #     estimator=LinearRegression(),
    -    #     )
    +    causal_effects.fit_total_effect(
    +        dataframe=dataframe, 
    +        # mask_type='y',
    +        estimator=LinearRegression(),
    +        )
     
    -    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
    -    # dox_vals = np.linspace(0., 1., 5)
    -    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
    -    # pred_Y = causal_effects.predict_total_effect( 
    -    #         intervention_data=intervention_data)
    -    # print(pred_Y)
     
    -    # Fit causal effect model from observational data
    -    causal_effects.fit_wright_effect(
    -        dataframe=dataframe, 
    +    # # Fit causal effect model from observational data
    +    causal_effects.fit_bootstrap_of(
    +        method='fit_total_effect',
    +        method_args={'dataframe':dataframe,  
             # mask_type='y',
    -        # estimator=LinearRegression(),
    +        'estimator':LinearRegression()
    +        },
    +        seed=4
             )
     
    +
         # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
    -    dox_vals = np.linspace(0., 1., 5)
    +    dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
         intervention_data = dox_vals.reshape(len(dox_vals), len(X))
    -    pred_Y = causal_effects.predict_wright_effect( 
    +    pred_Y = causal_effects.predict_total_effect( 
                 intervention_data=intervention_data)
         print(pred_Y)
    +
    +
    +
    +
    +    # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
    +    dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
    +    intervention_data = dox_vals.reshape(len(dox_vals), len(X))
    +    conf = causal_effects.predict_bootstrap_of(
    +        method='predict_total_effect',
    +        method_args={'intervention_data':intervention_data})
    +    print(conf)
    +
    +
    +
    +    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
    +    # dox_vals = np.array([1.]) #np.linspace(0., 1., 1)
    +    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
    +    # pred_Y = causal_effects.predict_total_effect( 
    +    #         intervention_data=intervention_data)
    +    # print(pred_Y)
    +
    +
    +
    +    # # Fit causal effect model from observational data
    +    # causal_effects.fit_wright_effect(
    +    #     dataframe=dataframe, 
    +    #     # mask_type='y',
    +    #     # estimator=LinearRegression(),
    +    #     )
    +
    +    # # Predict effect of interventions do(X=0.), ..., do(X=1.) in one go
    +    # dox_vals = np.linspace(0., 1., 5)
    +    # intervention_data = dox_vals.reshape(len(dox_vals), len(X))
    +    # pred_Y = causal_effects.predict_wright_effect( 
    +    #         intervention_data=intervention_data)
    +    # print(pred_Y)
     
    diff --git a/docs/_modules/tigramite/data_processing.html b/docs/_modules/tigramite/data_processing.html index 11366b61..db34d87b 100644 --- a/docs/_modules/tigramite/data_processing.html +++ b/docs/_modules/tigramite/data_processing.html @@ -252,6 +252,8 @@

    Source code for tigramite.data_processing

                 max_lag = 2*tau_max
             elif cut_off == 'max_lag':
                 max_lag = abs(np.array(XYZ)[:, 1].min())
    +        elif cut_off == 'tau_max':
    +            max_lag = tau_max
             elif cut_off == 'max_lag_or_tau_max':
                 max_lag = max(abs(np.array(XYZ)[:, 1].min()), tau_max)
             else:
    @@ -269,7 +271,7 @@ 

    Source code for tigramite.data_processing

             # Setup and fill array with lagged time series
             time_length = T - max_lag
             array = np.zeros((dim, time_length), dtype=self.values.dtype)
    -        # Note, lags are negative here
    +        # Note, lags are negative or zero here
             for i, (var, lag) in enumerate(XYZ):
                 if self.bootstrap is None:
                     array[i, :] = self.values[max_lag + lag:T + lag, var]
    @@ -285,17 +287,11 @@ 

    Source code for tigramite.data_processing

                 missing_anywhere = np.array(np.where(np.any(np.isnan(array), axis=0))[0])
                 if self.remove_missing_upto_maxlag:
                     for tau in range(max_lag+1):
    -                    if self.bootstrap is None:
    -                        delete = missing_anywhere + tau 
    -                        delete = delete[delete < time_length]
    -                        use_indices[delete] = 0
    -                    else:
    -                        use_indices[missing_anywhere[self.bootstrap] + tau] = 0
    +                    delete = missing_anywhere + tau 
    +                    delete = delete[delete < time_length]
    +                    use_indices[delete] = 0
                 else:
    -                if self.bootstrap is None:
    -                    use_indices[missing_anywhere] = 0
    -                else:
    -                    use_indices[missing_anywhere[self.bootstrap]] = 0
    +                use_indices[missing_anywhere] = 0
     
             # Use the mask override if needed
             _use_mask = mask
    @@ -323,6 +319,7 @@ 

    Source code for tigramite.data_processing

                 for idx, cde in index_code.items():
                     # Check if the letter index is in the mask type
                     if (mask_type is not None) and (idx in mask_type):
    +                    print(idx, cde, xyz,  xyz == cde)
                         # If so, check if any of the data that correspond to the
                         # letter index is masked by taking the product along the
                         # node-data to return a time slice selection, where 0 means
    @@ -332,7 +329,7 @@ 

    Source code for tigramite.data_processing

     
             if (self.missing_flag is not None) or (_use_mask is not None):
                 if use_indices.sum() == 0:
    -                raise ValueError("No unmasked samples")
    +                raise ValueError("No unmasked samples!")
                 array = array[:, use_indices == 1]
     
             # Print information about the constructed array
    diff --git a/docs/_modules/tigramite/independence_tests/gpdc.html b/docs/_modules/tigramite/independence_tests/gpdc.html
    index 9235c461..63b49be5 100644
    --- a/docs/_modules/tigramite/independence_tests/gpdc.html
    +++ b/docs/_modules/tigramite/independence_tests/gpdc.html
    @@ -56,7 +56,7 @@ 

    Source code for tigramite.independence_tests.gpdc

    # License: GNU General Public License v3.0 from __future__ import print_function -import json, warnings +import json, warnings, os, pathlib import numpy as np try: from importlib import metadata @@ -65,7 +65,7 @@

    Source code for tigramite.independence_tests.gpdc

    try: import dcor from sklearn import gaussian_process - with open('../versions.py', 'r') as vfile: + with open(pathlib.Path(os.path.dirname(__file__)) / '../../versions.py', 'r') as vfile: packages = json.loads(vfile.read())['all'] packages = dict(map(lambda s: s.split('>='), packages)) if metadata.version('dcor') < packages['dcor']: diff --git a/docs/_modules/tigramite/independence_tests/gpdc_torch.html b/docs/_modules/tigramite/independence_tests/gpdc_torch.html index f88154fa..185d8891 100644 --- a/docs/_modules/tigramite/independence_tests/gpdc_torch.html +++ b/docs/_modules/tigramite/independence_tests/gpdc_torch.html @@ -56,7 +56,7 @@

    Source code for tigramite.independence_tests.gpdc_torch

    # License: GNU General Public License v3.0 from __future__ import print_function -import json, warnings +import json, warnings, os, pathlib import numpy as np import gc try: @@ -68,15 +68,15 @@

    Source code for tigramite.independence_tests.gpdc_torch

    import torch import gpytorch from .LBFGS import FullBatchLBFGS - with open('../versions.py', 'r') as vfile: + with open(pathlib.Path(os.path.dirname(__file__)) / '../../versions.py', 'r') as vfile: packages = json.loads(vfile.read())['all'] packages = dict(map(lambda s: s.split('>='), packages)) if metadata.version('dcor') < packages['dcor']: raise Exception('Version mismatch. Installed version of dcor', metadata.version('dcor'), 'Please install dcor>=', packages['dcor']) - if metadata.version('torch') < packages['pytorch']: - raise Exception('Version mismatch. Installed version of pytorch', metadata.version('torch'), - 'Please install pytorch>=', packages['pytorch']) + if metadata.version('torch') < packages['torch']: + raise Exception('Version mismatch. Installed version of torch', metadata.version('torch'), + 'Please install torch>=', packages['torch']) if metadata.version('gpytorch') < packages['gpytorch']: raise Exception('Version mismatch. Installed version of gpytorch', metadata.version('gpytorch'), 'Please install gpytorch>=', packages['gpytorch']) diff --git a/docs/_modules/tigramite/models.html b/docs/_modules/tigramite/models.html index 32848d7b..85ea6c6c 100644 --- a/docs/_modules/tigramite/models.html +++ b/docs/_modules/tigramite/models.html @@ -57,7 +57,7 @@

    Source code for tigramite.models

     
     from __future__ import print_function
     from copy import deepcopy
    -import json, warnings
    +import json, warnings, os, pathlib
     import numpy as np
     try:
         from importlib import metadata
    @@ -67,7 +67,7 @@ 

    Source code for tigramite.models

         import sklearn
         import sklearn.linear_model
         import networkx
    -    with open('../versions.py', 'r') as vfile:
    +    with open(pathlib.Path(os.path.dirname(__file__)) / '../versions.py', 'r') as vfile:
             packages = json.loads(vfile.read())['all']
             packages = dict(map(lambda s: s.split('>='), packages))
             if metadata.version('scikit-learn') < packages['scikit-learn']:
    @@ -81,6 +81,10 @@ 

    Source code for tigramite.models

     from tigramite.data_processing import DataFrame
     from tigramite.pcmci import PCMCI
     
    +### remove!!!
    +from matplotlib import pyplot as plt
    +from scipy.stats import kde
    +
     
    [docs]class Models(): """Base class for time series models. @@ -102,7 +106,8 @@

    Source code for tigramite.models

         data_transform : sklearn preprocessing object, optional (default: None)
             Used to transform data prior to fitting. For example,
             sklearn.preprocessing.StandardScaler for simple standardization. The
    -        fitted parameters are stored.
    +        fitted parameters are stored. Note that the inverse_transform is then
    +        applied to the predicted data.
         mask_type : {None, 'y','x','z','xy','xz','yz','xyz'}
             Masking mode: Indicators for which variables in the dependence
             measure I(X; Y | Z) the samples should be masked. If None, the mask
    @@ -121,8 +126,9 @@ 

    Source code for tigramite.models

             # Set the mask type and dataframe object
             self.mask_type = mask_type
             self.dataframe = dataframe
    -        # Get the number of nodes for this dataset
    -        self.N = self.dataframe.values.shape[1]
    +        # Get the number of nodes and length for this dataset
    +        self.N = self.dataframe.N
    +        self.T = self.dataframe.T
             # Set the model to be used
             self.model = model
             if conditional_model is None:
    @@ -209,8 +215,7 @@ 

    Source code for tigramite.models

             fit_results = {}
             for y in self.Y:
     
    -            # Construct array of shape (var, time) with first entry being
    -            # a dummy, second is y followed by joint X and Z (ignore the notation in construct_array)
    +            # Construct array of shape (var, time)
                 array, xyz = \
                     self.dataframe.construct_array(X=self.X, Y=[y], # + self.Z, 
                                                    Z=self.conditions,
    @@ -220,18 +225,35 @@ 

    Source code for tigramite.models

                                                    cut_off=self.cut_off,
                                                    verbosity=self.verbosity)
     
    -
                 # Transform the data if needed
    +            self.fitted_data_transform = None
                 if self.data_transform is not None:
    -                array = self.data_transform.fit_transform(X=array.T).T
    +                # Fit only X, Y, and S for later use in transforming input
    +                X_transform = deepcopy(self.data_transform)
    +                x_indices = list(np.where(xyz==0)[0])
    +                X_transform.fit(array[x_indices, :].T)
    +                self.fitted_data_transform = {'X': X_transform}
    +                Y_transform = deepcopy(self.data_transform)
    +                y_indices = list(np.where(xyz==1)[0])
    +                Y_transform.fit(array[y_indices, :].T)
    +                self.fitted_data_transform['Y'] = Y_transform
    +                if len(self.conditions) > 0:
    +                    S_transform = deepcopy(self.data_transform)
    +                    s_indices = list(np.where(xyz==2)[0])
    +                    S_transform.fit(array[s_indices, :].T) 
    +                    self.fitted_data_transform['S'] = S_transform
    +
    +                # Now transform whole array
    +                all_transform = deepcopy(self.data_transform)
    +                array = all_transform.fit_transform(X=array.T).T
     
                 # Fit the model 
                 # Copy and fit the model
                 a_model = deepcopy(self.model)
     
                 predictor_indices =  list(np.where(xyz==0)[0]) \
    -                               + list(np.where(xyz==2)[0]) \
    -                               + list(np.where(xyz==3)[0])
    +                               + list(np.where(xyz==3)[0]) \
    +                               + list(np.where(xyz==2)[0])
                 predictor_array = array[predictor_indices, :].T
                 # Target is only first entry of Y, ie [y]
                 target_array = array[np.where(xyz==1)[0][0], :]
    @@ -244,10 +266,10 @@ 

    Source code for tigramite.models

                 fit_results[y]['xyz'] = xyz
                 fit_results[y]['model'] = a_model
                 # Cache the data transform
    -            fit_results[y]['data_transform'] = deepcopy(self.data_transform)
    -            # Cache the data if needed
    -            if return_data:
    -                fit_results[y]['data'] = array
    +            fit_results[y]['fitted_data_transform'] = self.fitted_data_transform
    +            # # Cache the data if needed
    +            # if return_data:
    +            #     fit_results[y]['data'] = array
     
             # Cache and return the fit results
             self.fit_results = fit_results
    @@ -258,6 +280,7 @@ 

    Source code for tigramite.models

                     intervention_data,
                     conditions_data=None,
                     pred_params=None,
    +                return_further_pred_results=False,
                     ):
             r"""Predict effect of intervention with fitted model.
     
    @@ -271,7 +294,9 @@ 

    Source code for tigramite.models

                 Numpy array of shape (time, len(S)) that contains the S=s values.
             pred_params : dict, optional
                 Optional parameters passed on to sklearn prediction function.
    -
    +        return_further_pred_results : bool, optional (default: False)
    +            In case the predictor class returns more than just the expected value,
    +            the entire results can be returned.
             Returns
             -------
             Results from prediction.
    @@ -289,12 +314,12 @@ 

    Source code for tigramite.models

                     raise ValueError("conditions_data.shape[0] must match intervention_data.shape[0].")
     
             lenS = len(self.conditions)
    -
             lenY = len(self.Y)
     
             predicted_array = np.zeros((intervention_T, lenY))
             pred_dict = {}
             for iy, y in enumerate(self.Y):
    +            pred_dict[iy] = {}
                 # Print message
                 if self.verbosity > 1:
                     print("\n## Predicting target %s" % str(y))
    @@ -309,16 +334,16 @@ 

    Source code for tigramite.models

                     raise ValueError("y = %s not yet fitted" % str(y))
     
                 # Transform the data if needed
    -            a_transform = self.fit_results[y]['data_transform']
    -            if a_transform is not None:
    -                intervention_data = a_transform.transform(X=intervention_data)
    +            fitted_data_transform = self.fit_results[y]['fitted_data_transform']
    +            if fitted_data_transform is not None:
    +                intervention_data = fitted_data_transform['X'].transform(X=intervention_data)
                     if self.conditions is not None and conditions_data is not None:
    -                    conditions_data = a_transform.transform(X=conditions_data)
    +                    conditions_data = fitted_data_transform['S'].transform(X=conditions_data)
     
                 # Extract observational Z from stored array
                 z_indices = list(np.where(self.fit_results[y]['xyz']==3)[0])
                 z_array = self.fit_results[y]['observation_array'][z_indices, :].T  
    -            Tobs = len(z_array)              
    +            Tobs = len(self.fit_results[y]['observation_array'].T) 
     
                 if self.conditions is not None and conditions_data is not None:
                     s_indices = list(np.where(self.fit_results[y]['xyz']==2)[0])
    @@ -339,20 +364,33 @@ 

    Source code for tigramite.models

     
                     if self.conditions is not None and conditions_data is not None:
      
    -                    # if a_transform is not None:
    -                    #     predicted_vals = a_transform.transform(X=target_array.T).T
                         a_conditional_model = deepcopy(self.conditional_model)
                         
    -                    a_conditional_model.fit(X=s_array, y=predicted_vals)
    +                    if type(predicted_vals) is tuple:
    +                        predicted_vals_here = predicted_vals[0]
    +                    else:
    +                        predicted_vals_here = predicted_vals
    +                    
    +                    a_conditional_model.fit(X=s_array, y=predicted_vals_here)
                         self.fit_results[y]['conditional_model'] = a_conditional_model
     
    -                    predicted_array[index, iy] = a_conditional_model.predict(
    -                        X=conditions_array, **pred_params).mean()
    +                    predicted_vals = a_conditional_model.predict(
    +                        X=conditions_array, **pred_params)
     
    +                if type(predicted_vals) is tuple:
    +                    predicted_array[index, iy] = predicted_vals[0].mean()
    +                    pred_dict[iy][index] = predicted_vals
                     else:
                         predicted_array[index, iy] = predicted_vals.mean()
     
    -        return predicted_array
    + if fitted_data_transform is not None: + rescaled = fitted_data_transform['Y'].inverse_transform(X=predicted_array[index, iy].reshape(-1, 1)) + predicted_array[index, iy] = rescaled.squeeze() + + if return_further_pred_results: + return predicted_array, pred_dict + else: + return predicted_array
    [docs] def get_fit(self, all_parents, diff --git a/docs/_modules/tigramite/plotting.html b/docs/_modules/tigramite/plotting.html index 3bc18132..1bdcf70f 100644 --- a/docs/_modules/tigramite/plotting.html +++ b/docs/_modules/tigramite/plotting.html @@ -56,7 +56,7 @@

    Source code for tigramite.plotting

     # License: GNU General Public License v3.0
     
     import numpy as np
    -import json, warnings
    +import json, warnings, os, pathlib
     try:
         from importlib import metadata
     except ImportError:
    @@ -64,7 +64,7 @@ 

    Source code for tigramite.plotting

     try:
         import matplotlib
         import networkx as nx
    -    with open('../versions.py', 'r') as vfile:
    +    with open(pathlib.Path(os.path.dirname(__file__)) / '../versions.py', 'r') as vfile:
             packages = json.loads(vfile.read())['all']
             packages = dict(map(lambda s: s.split('>='), packages))
             if metadata.version('matplotlib') < packages['matplotlib']:
    @@ -89,7 +89,7 @@ 

    Source code for tigramite.plotting

     from copy import deepcopy
     import matplotlib.path as mpath
     import matplotlib.patheffects as PathEffects
    -
    +from mpl_toolkits.axisartist.axislines import Axes
     # TODO: Add proper docstrings to internal functions...
     
     
    @@ -861,6 +861,311 @@ 

    Source code for tigramite.plotting

                 pyplot.show()
    + +
    [docs]def plot_scatterplots(dataframe, name=None, setup_args={}, add_scatterplot_args={}): + """Wrapper helper function to plot scatter plots. + Sets up the matrix object and plots the scatter plots, see parameters in + setup_scatter_matrix and add_scatterplot. + + Parameters + ---------- + dataframe : data object + Tigramite dataframe object. It must have the attributes dataframe.values + yielding a numpy array of shape (observations T, variables N) and + optionally a mask of the same shape and a missing values flag. + name : str, optional (default: None) + File name. If None, figure is shown in window. + setup_args : dict + Arguments for setting up the scatter plot matrix, see doc of + setup_scatter_matrix. + add_scatterplot_args : dict + Arguments for adding a scatter plot matrix. + + Returns + ------- + matrix : object + Further scatter plot can be overlaid using the + matrix.add_scatterplot function. + """ + + N = dataframe.N + + matrix = setup_scatter_matrix(N=N, var_names=dataframe.var_names, **setup_args) + matrix.add_scatterplot(dataframe=dataframe, **add_scatterplot_args) + matrix.adjustfig(name=name) + + + return matrix
    + + +
    [docs]class setup_scatter_matrix: + """Create matrix of scatter plot panels. + Class to setup figure object. The function add_scatterplot allows to plot + scatterplots of variables in the dataframe. Multiple scatter plots can be + overlaid for comparison. + + Parameters + ---------- + N : int + Number of variables + var_names : list, optional (default: None) + List of variable names. If None, range(N) is used. + figsize : tuple of floats, optional (default: None) + Figure size if new figure is created. If None, default pyplot figsize + is used. + label_space_left : float, optional (default: 0.1) + Fraction of horizontal figure space to allocate left of plot for labels. + label_space_top : float, optional (default: 0.05) + Fraction of vertical figure space to allocate top of plot for labels. + legend_width : float, optional (default: 0.15) + Fraction of horizontal figure space to allocate right of plot for + legend. + plot_gridlines : bool, optional (default: False) + Whether to show a grid. + label_fontsize : int, optional (default: 10) + Fontsize of variable labels. + """ + + def __init__( + self, + N, + var_names=None, + figsize=None, + label_space_left=0.1, + label_space_top=0.05, + legend_width=0.15, + legend_fontsize=10, + plot_gridlines=False, + label_fontsize=10, + ): + + self.labels = [] + + self.legend_width = legend_width + self.legend_fontsize = legend_fontsize + + self.label_space_left = label_space_left + self.label_space_top = label_space_top + self.label_fontsize = label_fontsize + + self.fig = pyplot.figure(figsize=figsize) + + self.axes_dict = {} + + if var_names is None: + var_names = range(N) + + plot_index = 1 + for i in range(N): + for j in range(N): + self.axes_dict[(i, j)] = self.fig.add_subplot(N, N, plot_index, axes_class=Axes) + # Plot process labels + if j == 0: + trans = transforms.blended_transform_factory( + self.fig.transFigure, self.axes_dict[(i, j)].transAxes + ) + self.axes_dict[(i, j)].text( + 0.01, + 0.5, + "%s" % str(var_names[i]), + fontsize=label_fontsize, + horizontalalignment="left", + verticalalignment="center", + transform=trans, + ) + if i == 0: + trans = transforms.blended_transform_factory( + self.axes_dict[(i, j)].transAxes, self.fig.transFigure + ) + self.axes_dict[(i, j)].text( + 0.5, + 0.99, + r"${\to}$ " + "%s" % str(var_names[j]), + fontsize=label_fontsize, + horizontalalignment="center", + verticalalignment="top", + transform=trans, + ) + + self.axes_dict[(i, j)].axis["right"].set_visible(False) + self.axes_dict[(i, j)].axis["top"].set_visible(False) + + if j != 0: + self.axes_dict[(i, j)].get_yaxis().set_ticklabels([]) + if i != N - 1: + self.axes_dict[(i, j)].get_xaxis().set_ticklabels([]) + + if plot_gridlines: + self.axes_dict[(i, j)].grid( + True, + which="major", + color="black", + linestyle="dotted", + dashes=(1, 1), + linewidth=0.05, + zorder=-5, + ) + + plot_index += 1 + +
    [docs] def add_scatterplot( + self, + dataframe, + scatter_lags=None, + color="black", + label=None, + marker=".", + markersize=5, + alpha=1.0, + ): + """Add lag function plot from val_matrix array. + + Parameters + ---------- + dataframe : data object + Tigramite dataframe object. It must have the attributes dataframe.values + yielding a numpy array of shape (observations T, variables N) and + optionally a mask of the same shape and a missing values flag. + scatter_lags : array + Lags to use in scatter plots. Either None or of shape (N, N). Then the + entry scatter_lags[i, j] = tau will depict the scatter plot of + time series (i, -tau) vs (j, 0). If None, tau = 0 for i != j and for i = j + tau = 1. + color : str, optional (default: 'black') + Line color. + label : str + Test statistic label. + marker : matplotlib marker symbol, optional (default: '.') + Marker. + markersize : int, optional (default: 5) + Marker size. + alpha : float, optional (default: 1.) + Opacity. + """ + + if label is not None: + self.labels.append((label, color, marker, markersize, alpha)) + + for ij in list(self.axes_dict): + i = ij[0] + j = ij[1] + if scatter_lags is None: + if i == j: + lag = 1 + else: + lag = 0 + else: + lag = scatter_lags[i,j] + if lag == 0: + x = np.copy(dataframe.values[:, i]) + y = np.copy(dataframe.values[:, j]) + else: + x = np.copy(dataframe.values[:-lag, i]) + y = np.copy(dataframe.values[lag:, j]) + if dataframe.mask is not None: + x[dataframe.mask[:-lag, i]] = np.nan + y[dataframe.mask[lag:, j]] = np.nan + # print(i, j, lag, x.shape, y.shape) + self.axes_dict[(i, j)].scatter( + x, y, + color=color, + marker=marker, + s=markersize, + alpha=alpha, + clip_on=False, + label=r"$\tau{=}%d$" %lag, + )
    + # self.axes_dict[(i, j)].text(0., 1., r"$\tau{=}%d$" %lag, + # fontsize=self.legend_fontsize, + # ha='left', va='top', + # transform=self.axes_dict[(i, j)].transAxes) + + +
    [docs] def adjustfig(self, name=None): + """Adjust matrix figure. + + Parameters + ---------- + name : str, optional (default: None) + File name. If None, figure is shown in window. + """ + + # Trick to plot legends + colors = [] + for item in self.labels: + colors.append(item[1]) + for ij in list(self.axes_dict): + i = ij[0] + j = ij[1] + + leg = self.axes_dict[(i, j)].legend( + # loc="upper left", + ncol=1, + # bbox_to_anchor=(1.05, 0.0, 0.1, 1.0), + # borderaxespad=0, + fontsize=self.legend_fontsize-2, + labelcolor=colors, + ).draw_frame(False) + + if len(self.labels) > 0: + axlegend = self.fig.add_subplot(111, frameon=False) + axlegend.spines["left"].set_color("none") + axlegend.spines["right"].set_color("none") + axlegend.spines["bottom"].set_color("none") + axlegend.spines["top"].set_color("none") + axlegend.set_xticks([]) + axlegend.set_yticks([]) + + # self.labels.append((label, color, marker, markersize, alpha)) + for item in self.labels: + label = item[0] + color = item[1] + marker = item[2] + markersize = item[3] + alpha = item[4] + + axlegend.plot( + [], + [], + linestyle="", + color=color, + marker=marker, + markersize=markersize, + label=label, + alpha=alpha, + ) + axlegend.legend( + loc="upper left", + ncol=1, + bbox_to_anchor=(1.05, 0.0, 0.1, 1.0), + borderaxespad=0, + fontsize=self.legend_fontsize, + ).draw_frame(False) + + self.fig.subplots_adjust( + bottom=0.05, + left=self.label_space_left, + right=1.0 - self.legend_width, + top=1.0 - self.label_space_top, + hspace=0.5, + wspace=0.35, + ) + + else: + self.fig.subplots_adjust( + left=self.label_space_left, + bottom=0.05, + right=0.95, + top=1.0 - self.label_space_top, + hspace=0.35, + wspace=0.35, + ) + + if name is not None: + self.fig.savefig(name) + else: + pyplot.show()
    + def _draw_network_with_curved_edges( fig, ax, @@ -1440,13 +1745,12 @@

    Source code for tigramite.plotting

                     data_to_rgb_links, cax=cax_e, orientation="horizontal"
                 )
                 # try:
    -            cb_e.set_ticks(
    -                np.arange(
    +            ticks_here = np.arange(
                         _myround(links_vmin, links_ticks, "down"),
                         _myround(links_vmax, links_ticks, "up") + links_ticks,
                         links_ticks,
                     )
    -            )
    +            cb_e.set_ticks(ticks_here[(links_vmin <= ticks_here) & (ticks_here <= links_vmax)])
                 # except:
                 #     print('no ticks given')
     
    @@ -1531,14 +1835,13 @@ 

    Source code for tigramite.plotting

                     )
                     cb_n = pyplot.colorbar(data_to_rgb, cax=cax_n, orientation="horizontal")
                     # try:
    -                cb_n.set_ticks(
    -                    np.arange(
    -                        _myround(vmin, node_rings[ring]["ticks"], "down"),
    -                        _myround(vmax, node_rings[ring]["ticks"], "up")
    -                        + node_rings[ring]["ticks"],
    -                        node_rings[ring]["ticks"],
    -                    )
    +                ticks_here = np.arange(
    +                    _myround(vmin, node_rings[ring]["ticks"], "down"),
    +                    _myround(vmax, node_rings[ring]["ticks"], "up")
    +                    + node_rings[ring]["ticks"],
    +                    node_rings[ring]["ticks"],
                     )
    +                cb_n.set_ticks(ticks_here[(vmin <= ticks_here) & (ticks_here <= vmax)])
                     # except:
                     #     print ('no ticks given')
                     cb_n.outline.clear()
    @@ -3384,6 +3687,46 @@ 

    Source code for tigramite.plotting

     
     if __name__ == "__main__":
     
    +    import sys
    +    matplotlib.rc('xtick', labelsize=6) 
    +    matplotlib.rc('ytick', labelsize=6) 
    +
    +    # Consider some toy data
    +    import tigramite
    +    import tigramite.toymodels.structural_causal_processes as toys
    +    import tigramite.data_processing as pp
    +
    +    T = 1000
    +    def lin_f(x): return x
    +    auto_coeff = 0.3
    +    coeff = 1.
    +    links = {
    +            0: [((0, -1), auto_coeff, lin_f)], 
    +            1: [((1, -1), auto_coeff, lin_f), ((0, 0), coeff, lin_f)], 
    +            2: [((2, -1), auto_coeff, lin_f), ((1, 0), coeff, lin_f)],
    +            }
    +    data, nonstat = toys.structural_causal_process(links, T=T, 
    +                                noises=None, seed=7)
    +
    +    dataframe = pp.DataFrame(data, var_names=range(len(links)))
    +    plot_scatterplots(dataframe) #, name='scattertest.pdf')
    +    
    +    # matrix = setup_scatter_matrix(N=dataframe.N, 
    +    #     var_names=dataframe.var_names)
    +    # scatter_lags = np.ones((3, 3)).astype('int')
    +    # matrix.add_scatterplot(dataframe=dataframe, scatter_lags=scatter_lags,
    +    #             label='ones', alpha=0.4)
    +    # scatter_lags = 2*np.ones((3, 3)).astype('int')
    +    # matrix.add_scatterplot(dataframe=dataframe, scatter_lags=scatter_lags, 
    +    #     label='twos', color='red', alpha=0.4)
    +
    +    # matrix.savefig(name='scattertest.pdf')
    +    
    +
    +    # pyplot.show()
    +    sys.exit(0)
    +
    +
         val_matrix = np.zeros((4, 4, 3))
     
         # Complete test case
    diff --git a/docs/genindex.html b/docs/genindex.html
    index 7bb74238..7da74fe5 100644
    --- a/docs/genindex.html
    +++ b/docs/genindex.html
    @@ -75,9 +75,13 @@ 

    A

    @@ -128,10 +132,12 @@

    F

  • set_mask_type() (tigramite.independence_tests.CondIndTest method) +
  • +
  • setup_matrix (class in tigramite.plotting)
    • -
    • setup_matrix (class in tigramite.plotting) +
    • setup_scatter_matrix (class in tigramite.plotting)
    • smooth() (in module tigramite.data_processing)
    • diff --git a/docs/index.html b/docs/index.html index 0906171f..4d386978 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2571,6 +2571,29 @@

      +
      +
      +fit_bootstrap_of(method, method_args, boot_samples=1000, boot_blocklength=1, seed=None)[source]
      +

      Runs chosen method on bootstrap samples drawn from DataFrame.

      +

      Bootstraps for tau=0 are drawn from [max_lag, …, T] and all lagged +variables constructed in DataFrame.construct_array are consistently +shifted with respect to this bootsrap sample to ensure that lagged +relations in the bootstrap sample are preserved.

      +

      This function fits the models, predict_bootstrap_of can then be used +to get confidence intervals for the effect of interventions.

      +
      +
      Parameters
      +
        +
      • method (str) – Chosen method among valid functions in this class.

      • +
      • method_args (dict) – Arguments passed to method.

      • +
      • boot_samples (int) – Number of bootstrap samples to draw.

      • +
      • boot_blocklength (int, optional (default: 1)) – Block length for block-bootstrap.

      • +
      • seed (int, optional(default = None)) – Seed for RandomState (default_rng)

      • +
      +
      +
      +
      +
      fit_total_effect(dataframe, estimator, adjustment_set='optimal', conditional_estimator=None, data_transform=None, mask_type=None)[source]
      @@ -2700,9 +2723,32 @@

      +
      +
      +predict_bootstrap_of(method, method_args, conf_lev=0.9)[source]
      +

      Predicts with fitted bootstraps.

      +

      To be used after fitting with fit_bootstrap_of. Only uses the +expected values of the predict function, not potential other output.

      +
      +
      Parameters
      +
        +
      • method (str) – Chosen method among valid functions in this class.

      • +
      • method_args (dict) – Arguments passed to method.

      • +
      • conf_lev (float, optional (default: 0.9)) – Two-sided confidence interval.

      • +
      +
      +
      Returns
      +

      confidence_intervals

      +
      +
      Return type
      +

      numpy array of

      +
      +
      +
      +
      -predict_total_effect(intervention_data, conditions_data=None, pred_params=None)[source]
      +predict_total_effect(intervention_data, conditions_data=None, pred_params=None, return_further_pred_results=False)[source]

      Predict effect of intervention with fitted model.

      Uses the model.predict() function of the sklearn model.

      @@ -2711,13 +2757,16 @@

    • intervention_data (numpy array) – Numpy array of shape (time, len(X)) that contains the do(X) values.

    • conditions_data (data object, optional) – Numpy array of shape (time, len(S)) that contains the S=s values.

    • pred_params (dict, optional) – Optional parameters passed on to sklearn prediction function.

    • +
    • return_further_pred_results (bool, optional (default: False)) – In case the predictor class returns more than just the expected value, +the entire results can be returned.

    Returns
    -

    Results from prediction

    -
    -
    Return type
    -

    an array of shape (time, len(Y))

    +

      +
    • Results from prediction (an array of shape (time, len(Y)).)

    • +
    • If estimate_confidence = True, then a tuple is returned.

    • +
    +

    @@ -2766,7 +2815,8 @@

    If None, model is used.

  • data_transform (sklearn preprocessing object, optional (default: None)) – Used to transform data prior to fitting. For example, sklearn.preprocessing.StandardScaler for simple standardization. The -fitted parameters are stored.

  • +fitted parameters are stored. Note that the inverse_transform is then +applied to the predicted data.

  • mask_type ({None, 'y','x','z','xy','xz','yz','xyz'}) – Masking mode: Indicators for which variables in the dependence measure I(X; Y | Z) the samples should be masked. If None, the mask is not used. Explained in tutorial on masking and missing values.

  • @@ -2858,7 +2908,7 @@

    -get_general_prediction(intervention_data, conditions_data=None, pred_params=None)[source]
    +get_general_prediction(intervention_data, conditions_data=None, pred_params=None, return_further_pred_results=False)[source]

    Predict effect of intervention with fitted model.

    Uses the model.predict() function of the sklearn model.

    @@ -2867,6 +2917,8 @@

  • intervention_data (numpy array) – Numpy array of shape (time, len(X)) that contains the do(X) values.

  • conditions_data (data object, optional) – Numpy array of shape (time, len(S)) that contains the S=s values.

  • pred_params (dict, optional) – Optional parameters passed on to sklearn prediction function.

  • +
  • return_further_pred_results (bool, optional (default: False)) – In case the predictor class returns more than just the expected value, +the entire results can be returned.

  • Returns
    @@ -4066,6 +4118,34 @@

    +
    +
    +tigramite.plotting.plot_scatterplots(dataframe, name=None, setup_args={}, add_scatterplot_args={})[source]
    +

    Wrapper helper function to plot scatter plots. +Sets up the matrix object and plots the scatter plots, see parameters in +setup_scatter_matrix and add_scatterplot.

    +
    +
    Parameters
    +
      +
    • dataframe (data object) – Tigramite dataframe object. It must have the attributes dataframe.values +yielding a numpy array of shape (observations T, variables N) and +optionally a mask of the same shape and a missing values flag.

    • +
    • name (str, optional (default: None)) – File name. If None, figure is shown in window.

    • +
    • setup_args (dict) – Arguments for setting up the scatter plot matrix, see doc of +setup_scatter_matrix.

    • +
    • add_scatterplot_args (dict) – Arguments for adding a scatter plot matrix.

    • +
    +
    +
    Returns
    +

    matrix – Further scatter plot can be overlaid using the +matrix.add_scatterplot function.

    +
    +
    Return type
    +

    object

    +
    +
    +
    +
    tigramite.plotting.plot_time_series_graph(graph, val_matrix=None, var_names=None, fig_ax=None, figsize=None, link_colorbar_label='MCI', save_name=None, link_width=None, link_attribute=None, arrow_linewidth=8, vmin_edges=-1, vmax_edges=1.0, edge_ticks=0.4, cmap_edges='RdBu_r', order=None, node_size=0.1, node_aspect=None, arrowhead_size=20, curved_radius=0.2, label_fontsize=12, alpha=1.0, node_label_size=12, label_space_left=0.1, label_space_top=0.0, network_lower_bound=0.2, inner_edge_style='dashed', link_matrix=None, special_nodes=None, standard_color_links='black', standard_color_nodes='lightgrey')[source]
    @@ -4213,6 +4293,66 @@

    +
    +
    +class tigramite.plotting.setup_scatter_matrix(N, var_names=None, figsize=None, label_space_left=0.1, label_space_top=0.05, legend_width=0.15, legend_fontsize=10, plot_gridlines=False, label_fontsize=10)[source]
    +

    Create matrix of scatter plot panels. +Class to setup figure object. The function add_scatterplot allows to plot +scatterplots of variables in the dataframe. Multiple scatter plots can be +overlaid for comparison.

    +
    +
    Parameters
    +
      +
    • N (int) – Number of variables

    • +
    • var_names (list, optional (default: None)) – List of variable names. If None, range(N) is used.

    • +
    • figsize (tuple of floats, optional (default: None)) – Figure size if new figure is created. If None, default pyplot figsize +is used.

    • +
    • label_space_left (float, optional (default: 0.1)) – Fraction of horizontal figure space to allocate left of plot for labels.

    • +
    • label_space_top (float, optional (default: 0.05)) – Fraction of vertical figure space to allocate top of plot for labels.

    • +
    • legend_width (float, optional (default: 0.15)) – Fraction of horizontal figure space to allocate right of plot for +legend.

    • +
    • plot_gridlines (bool, optional (default: False)) – Whether to show a grid.

    • +
    • label_fontsize (int, optional (default: 10)) – Fontsize of variable labels.

    • +
    +
    +
    +
    +
    +add_scatterplot(dataframe, scatter_lags=None, color='black', label=None, marker='.', markersize=5, alpha=1.0)[source]
    +

    Add lag function plot from val_matrix array.

    +
    +
    Parameters
    +
      +
    • dataframe (data object) – Tigramite dataframe object. It must have the attributes dataframe.values +yielding a numpy array of shape (observations T, variables N) and +optionally a mask of the same shape and a missing values flag.

    • +
    • scatter_lags (array) – Lags to use in scatter plots. Either None or of shape (N, N). Then the +entry scatter_lags[i, j] = tau will depict the scatter plot of +time series (i, -tau) vs (j, 0). If None, tau = 0 for i != j and for i = j +tau = 1.

    • +
    • color (str, optional (default: 'black')) – Line color.

    • +
    • label (str) – Test statistic label.

    • +
    • marker (matplotlib marker symbol, optional (default: '.')) – Marker.

    • +
    • markersize (int, optional (default: 5)) – Marker size.

    • +
    • alpha (float, optional (default: 1.)) – Opacity.

    • +
    +
    +
    +
    + +
    +
    +adjustfig(name=None)[source]
    +

    Adjust matrix figure.

    +
    +
    Parameters
    +

    name (str, optional (default: None)) – File name. If None, figure is shown in window.

    +
    +
    +
    + +
    +

    Indices and tables

    diff --git a/docs/objects.inv b/docs/objects.inv index 480c1c789f2ddf177abe371597d0e757437741c9..3dd062c04734a721c6a1de91b2d41ceee22ec3f5 100644 GIT binary patch delta 1404 zcmV-?1%vv^3-b$*h=0~J*W5Zzn$b+udKw?v69ytd5;X|0z|yk%>$?C+iBe<-1XdSY z{CFQO7K`PA0La?%R)Sa;ymwqNQB|S>5^C)3Q>MQCm?;4#qkn-q_*H2?`54D|}n2dws$Z_xyxS=>3udXPq^L za8Bwvh)mflvHE2$8qVFnt6hJ>@v4+oUCyMgOs?OpXw8dYla+l3hPC{a#@H8bnZ_S3 znWfCW!Qs+jn6gSL5Z0rrUKb#ZUP3aqlo|&ozQJZ8n?m}x=NhCEY$tUd$+eidnq+kt ze!ay;jfrQxmDa<=((>U>h zeyaFxV1N1zkd%RXfv)5$CP`?laJTU_wZT}W3O@r-BII#aSQJ{H(W#z5JAN?R7Xy3S*YLqJK#8jLNPoJb6Sn}y>Aog^kF z<}CvA#3qi;6ZkeEdg7DE>4464!XK6wN<3^*V|CJxpOsx>Y&9 zS-6yAz!03V&VQHT@)=6e*b+EI_OuiRQ9wu#e(fS3V?{$WO;_X z!Wx&Rqu+ktlM>_M@$A8|y>L>kmpXDL^=6L^kKW*Lof7663s%A3pjbX%PfWp#&54r_ zulxA=V0Qod_vi)Px#}rN<=;{rw?czU(qpCjB5cSr4yC$YGB=uohEZ=VR*X3CI)4oL zUbr;OZ2H$N88(+3#p@bvIhKqv#UNk!hCG_)-{G6H6|Ps1@bp1`DwJW#g!l|JY`AZ= z@jvfQx0R;wH_h&N+I;!**X`!%^BvlDh1VVKrwfB%JM`EMz$z;B*1+D delta 1363 zcmV-Z1+4n>3(5WU_WSDo z4x#`>*|PGP{PXV*(o<+Xuw&4wDwC*s;2jkl4hYDa0|5occ7G(~Uh}2}JZ8gy*bDoX z)LM0<;%L;4Rh)v-28lP04lxYF!d^4iSL`90unEIdQJ|#Ps$|A+*?5tv2EkT;%thhc z{hQk2vpxRPwy~(m_Nuxll{BCS+aanoJtTExhI1{BK>;-14#3heHWnBHs-xx^1H=6p zQVZH3;CjvF=zns;Wvz1ku34vcj7(MzJt)%A7aU`ER1;}`m}Hhv`_@jE-i9fuxd5ge zsvcwsT*)OQr7JG&t`vWa^90-L({z?q<&e=Flyr6Gw-n8kD_O~$o21v|6 zy+GIe#eXJAXf-pp@in%=wn}BLR2R(WaZ+k4)GniA-2r$0Uc#}VnEnmbVSHWq4o(l! zpGAccP4_53<0h7^8tQ2^gFIjO{1Jy>)elPR)Y&o0(U*KzxhR=sPDaeNb1Z%w&grOmb^9 zj>@*k>K#VLZvT#$jsLeKM+L<(NKC@*#($S~kSY!9CE*ZmcVu~nyuuo{rlX&JzmgK; z;qmOov7>NO6-ymClRC42Bxx2+ z5QM(C>U+y~vBmeLv>t>=)pn`E-Y))tZUsw~Q_*BdiL_Oc`+~vPWgIgLN~K?M89uPb zy%-XQ+z4K|1huycwI`}xjxmSM3V$^JkCEQLuwD9Op2NJB%lH{36u{CC)FzStamvjx z-+7!%Z8CHslcv5XwR0ie@td&p!z82 z)-Gf2Kdh#+{<_uL{k%I}R;kimG`r$y{q^rpoAuL|J8Rn&UVpfs8iHUGMl6txT}GDe Vxgwkk7yk(DkF;TT{{twB3NFU}vWEZw diff --git a/docs/searchindex.js b/docs/searchindex.js index 6a85b8e8..d9fa690b 100644 --- a/docs/searchindex.js +++ b/docs/searchindex.js @@ -1 +1 @@ -Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.index":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"tigramite.causal_effects":{CausalEffects:[0,0,1,""]},"tigramite.causal_effects.CausalEffects":{check_XYS_paths:[0,1,1,""],check_optimality:[0,1,1,""],fit_total_effect:[0,1,1,""],fit_wright_effect:[0,1,1,""],get_graph_from_dict:[0,1,1,""],get_mediators:[0,1,1,""],get_optimal_set:[0,1,1,""],predict_total_effect:[0,1,1,""],predict_wright_effect:[0,1,1,""]},"tigramite.data_processing":{DataFrame:[0,0,1,""],lowhighpass_filter:[0,4,1,""],ordinal_patt_array:[0,4,1,""],quantile_bin_array:[0,4,1,""],smooth:[0,4,1,""],structural_causal_process:[0,4,1,""],time_bin_with_mask:[0,4,1,""],var_process:[0,4,1,""],weighted_avg_and_std:[0,4,1,""]},"tigramite.data_processing.DataFrame":{construct_array:[0,1,1,""],data:[0,3,1,""],datatime:[0,3,1,""],mask:[0,3,1,""],missing_flag:[0,3,1,""],print_array_info:[0,1,1,""],remove_missing_upto_maxlag:[0,3,1,""],var_names:[0,3,1,""]},"tigramite.independence_tests":{CMIknn:[0,0,1,""],CMIsymb:[0,0,1,""],CondIndTest:[0,0,1,""],GPDC:[0,0,1,""],GPDCtorch:[0,0,1,""],OracleCI:[0,0,1,""],ParCorr:[0,0,1,""]},"tigramite.independence_tests.CMIknn":{get_conditional_entropy:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CMIsymb":{get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CondIndTest":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_bootstrap_confidence:[0,1,1,""],get_confidence:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_fixed_thres_significance:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],get_significance:[0,1,1,""],measure:[0,1,1,""],print_info:[0,1,1,""],run_test:[0,1,1,""],run_test_raw:[0,1,1,""],set_dataframe:[0,1,1,""],set_mask_type:[0,1,1,""]},"tigramite.independence_tests.GPDC":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.GPDCtorch":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.OracleCI":{check_shortest_path:[0,1,1,""],get_confidence:[0,1,1,""],get_graph_from_links:[0,1,1,""],get_links_from_graph:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],measure:[0,1,1,""],run_test:[0,1,1,""],set_dataframe:[0,1,1,""]},"tigramite.independence_tests.ParCorr":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.lpcmci":{LPCMCI:[0,0,1,""]},"tigramite.lpcmci.LPCMCI":{run_lpcmci:[0,1,1,""]},"tigramite.models":{LinearMediation:[0,0,1,""],Models:[0,0,1,""],Prediction:[0,0,1,""]},"tigramite.models.LinearMediation":{fit_model:[0,1,1,""],get_ace:[0,1,1,""],get_acs:[0,1,1,""],get_all_ace:[0,1,1,""],get_all_acs:[0,1,1,""],get_all_amce:[0,1,1,""],get_amce:[0,1,1,""],get_ce:[0,1,1,""],get_ce_max:[0,1,1,""],get_coeff:[0,1,1,""],get_mce:[0,1,1,""],get_mediation_graph_data:[0,1,1,""],get_tsg:[0,1,1,""],get_val_matrix:[0,1,1,""],net_to_tsg:[0,1,1,""],tsg_to_net:[0,1,1,""]},"tigramite.models.Models":{get_coefs:[0,1,1,""],get_fit:[0,1,1,""],get_general_fitted_model:[0,1,1,""],get_general_prediction:[0,1,1,""],get_val_matrix:[0,1,1,""]},"tigramite.models.Prediction":{fit:[0,1,1,""],get_predictors:[0,1,1,""],get_test_array:[0,1,1,""],get_train_array:[0,1,1,""],predict:[0,1,1,""]},"tigramite.pcmci":{PCMCI:[0,0,1,""]},"tigramite.pcmci.PCMCI":{N:[0,3,1,""],T:[0,3,1,""],all_parents:[0,3,1,""],convert_to_string_graph:[0,1,1,""],get_corrected_pvalues:[0,1,1,""],get_graph_from_pmatrix:[0,1,1,""],get_lagged_dependencies:[0,1,1,""],iterations:[0,3,1,""],print_results:[0,1,1,""],print_significant_links:[0,1,1,""],pval_max:[0,3,1,""],return_parents_dict:[0,1,1,""],return_significant_links:[0,1,1,""],run_bivci:[0,1,1,""],run_fullci:[0,1,1,""],run_mci:[0,1,1,""],run_pc_stable:[0,1,1,""],run_pcalg:[0,1,1,""],run_pcalg_non_timeseries_data:[0,1,1,""],run_pcmci:[0,1,1,""],run_pcmciplus:[0,1,1,""],run_sliding_window_of:[0,1,1,""],symmetrize_p_and_val_matrix:[0,1,1,""],val_min:[0,3,1,""]},"tigramite.plotting":{plot_graph:[0,4,1,""],plot_lagfuncs:[0,4,1,""],plot_mediation_graph:[0,4,1,""],plot_mediation_time_series_graph:[0,4,1,""],plot_time_series_graph:[0,4,1,""],plot_timeseries:[0,4,1,""],plot_tsg:[0,4,1,""],setup_matrix:[0,0,1,""]},"tigramite.plotting.setup_matrix":{add_lagfuncs:[0,1,1,""],savefig:[0,1,1,""]},"tigramite.toymodels":{structural_causal_processes:[0,2,0,"-"]},"tigramite.toymodels.structural_causal_processes":{links_to_graph:[0,4,1,""],structural_causal_process:[0,4,1,""],var_process:[0,4,1,""]},tigramite:{data_processing:[0,2,0,"-"],plotting:[0,2,0,"-"]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","module","Python module"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:module","3":"py:attribute","4":"py:function"},terms:{"21st":0,"2xtau_max":0,"36th":0,"579_main_pap":0,"8485ae387a981d783f8764e508151cd9":0,"94e70705efae423efda1088614128d0b":0,"abstract":0,"boolean":0,"break":0,"case":0,"class":0,"default":0,"float":0,"import":0,"int":0,"long":0,"new":0,"null":0,"return":0,"static":0,"true":0,"var":0,"while":0,ACE:0,ACS:0,For:0,Its:0,Not:0,OLS:0,The:0,Then:0,There:0,These:0,Used:0,Useful:0,Uses:0,Using:0,Will:0,With:0,_get_single_residu:0,_run_ancestral_removal_phas:0,_run_dsep_removal_phas:0,_run_non_ancestral_removal_phas:0,about:0,abov:0,abs:0,absent:0,absmax:0,absolut:0,accept:0,accord:0,account:0,ace:0,across:0,acs:0,act:0,actual:0,adapt:0,add:0,add_lagfunc:0,add_lagfunc_arg:0,add_to_null_dist:0,added:0,adding:0,addit:0,address:0,adj:0,adjac:0,adjust:0,adjustment_set:0,admg:0,adv:0,advanc:0,affect:0,after:0,again:0,ahead:0,aic:0,aip:0,akaik:0,algorithm:0,all:0,all_lag:0,all_par:0,all_result:0,alloc:0,allow:0,along:0,alpha:0,alpha_level:0,alreadi:0,also:0,altern:0,alternative_condit:0,although:0,alwai:0,ambigu:0,ambiguous_tripl:0,amc:0,among:0,analyt:0,analyz:0,anc_all_i:0,anc_all_x:0,anc_all_z:0,anc_i:0,anc_x:0,anc_xi:0,ancestor:0,ancestr:0,ani:0,anoth:0,apds_t:0,appli:0,applic:0,appropri:0,apr:0,arang:0,arbitrari:0,argument:0,around:0,arrai:0,array_lik:0,array_mask:0,arrohead:0,arrow:0,arrow_linewidth:0,arrowhead_s:0,articl:0,artifici:0,arxiv:0,assess:0,assign:0,associ:0,assum:0,assumpt:0,ast:0,asymptot:0,attribut:0,au_i:0,au_j:0,auai:0,auto:0,auto_first:0,autocorrel:0,autocovari:0,autodepend:0,automat:0,autoregress:0,auxadmg:0,auxiliari:0,avail:0,averag:0,avoid:0,axes:0,axi:0,backdoor:0,backward:0,bakirov:0,bandwidth:0,base:0,basemap:0,been:0,befor:0,beforehand:0,begin:0,being:0,below:0,benjamini:0,best:0,beta:0,beta_i:0,beta_x:0,better:0,between:0,bia:0,bias:0,bin:0,bincount:0,bindata:0,bivci:0,black:0,block:0,blue:0,bold:0,bool:0,bootstrap:0,both:0,bottom:0,bound:0,box:0,breadth:0,break_once_separ:0,briefli:0,butterworth:0,call:0,callabl:0,can:0,canada:0,canon:0,cardin:0,care:0,caus:0,causaleffect:0,cdot:0,certain:0,chain:0,chao:0,check:0,check_optim:0,check_optimality_cond:0,check_shortest_path:0,check_sm_overlap:0,check_xys_path:0,child:0,choic:0,chosen:0,cite:0,ckdtree:0,clash:0,clean:0,cmap_edg:0,cmap_nod:0,cmi:0,cmiknn:0,cmisymb:0,coef1:0,coef2:0,coeff:0,coeffici:0,collid:0,collider_par:0,colliders_minimized_optim:0,colliders_onli:0,color:0,colorbar:0,colormap:0,column:0,com:0,combin:0,come:0,command:0,common:0,commun:0,compar:0,comparison:0,compat:0,complex:0,comprehens:0,comput:0,compute_ancestor:0,concret:0,cond_ind_test:0,condindtest:0,conditional_estim:0,conditional_model:0,conditions_data:0,conduct:0,conf_blocklength:0,conf_lev:0,conf_low:0,conf_matrix:0,conf_sampl:0,conf_upp:0,confer:0,confid:0,conflict:0,conflict_resolut:0,confound:0,conserv:0,consid:0,consider:0,considerd:0,consist:0,constant:0,constrain:0,construct:0,construct_arrai:0,constructor:0,contain:0,contemp_collider_rul:0,contemp_cond:0,contemporan:0,content:0,continu:0,contrast:0,control:0,conveni:0,convert:0,convert_to_string_graph:0,coordin:0,correct:0,corrected_a:0,correl:0,correspond:0,cost:0,could:0,coupl:0,covari:0,creat:0,criteria:0,criterion:0,cross:0,cube:0,current:0,curv:0,curvatur:0,curved_radiu:0,cut_off:0,cutoff:0,cutperiod:0,cython:0,d_z:0,dag:0,dash:0,data_linewidth:0,data_transform:0,datafram:0,dataset:0,datatim:0,dcor:0,debug:0,decai:0,def:0,default_rng:0,defin:0,definin:0,degre:0,delai:0,denot:0,densiti:0,depend:0,dependence_measur:0,deprec:0,depth:0,deriv:0,describ:0,descript:0,detail:0,detect:0,determin:0,deviat:0,dict:0,dictionari:0,differ:0,digamma:0,digest:0,dim:0,dimens:0,dimension:0,direct:0,direction:0,directli:0,disabl:0,discov:0,discoveri:0,discret:0,discuss:0,disk:0,dismiss:0,dist:0,distanc:0,distribut:0,do_check:0,doc:0,doe:0,doi:0,dpag:0,draw:0,drawn:0,driver:0,due:0,dummi:0,duplic:0,dure:0,eaau4996:0,each:0,easi:0,edg:0,edge_tick:0,effici:0,either:0,element:0,els:0,eman:0,embed:0,empti:0,end:0,ends_with:0,ensur:0,entri:0,entropi:0,enumer:0,epsilon_:0,equal:0,equival:0,error:0,estim:0,eta:0,etc:0,evalu:0,even:0,everi:0,exampl:0,except:0,exclud:0,exclude_contemporan:0,exclude_i:0,exclude_j:0,exclude_k:0,exclude_self_effect:0,execut:0,exist:0,expect:0,experi:0,experiment:0,explain:0,extern:0,extraz:0,f_x:0,f_y:0,factor:0,faculti:0,faith:0,fals:0,fancyarrowpatch:0,faster:0,fdr:0,fdr_bh:0,fdr_method:0,featur:0,feedback:0,fig:0,fig_ax:0,figsiz:0,figur:0,file:0,fill:0,filter:0,fine:0,first:0,fit:0,fit_model:0,fit_result:0,fit_total_effect:0,fit_wright_effect:0,fix:0,fix_all_edges_before_final_orient:0,fixed_thr:0,flag:0,flaxman:0,flexibl:0,follow:0,fontsiz:0,forbidden_nod:0,forc:0,forecast:0,form:0,format:0,forward:0,found:0,four:0,frac:0,fraction:0,framework:0,free:0,freedom:0,frenzel:0,frequenc:0,frequent:0,friendli:0,from:0,full:0,fullci:0,fulli:0,func:0,further:0,futur:0,gabor:0,gatewai:0,gauss_pr:0,gaussian:0,gaussianprocessregressor:0,gaussprocreg:0,gaussprocregtorch:0,generate_and_save_nulldist:0,generate_nulldist:0,gerhardu:0,get:0,get_ac:0,get_all_ac:0,get_all_amc:0,get_amc:0,get_analytic_confid:0,get_analytic_signific:0,get_bootstrap_confid:0,get_c:0,get_ce_max:0,get_coef:0,get_coeff:0,get_conditional_entropi:0,get_confid:0,get_corrected_pvalu:0,get_dependence_measur:0,get_fit:0,get_fixed_thres_signific:0,get_general_fitted_model:0,get_general_predict:0,get_graph_from_dict:0,get_graph_from_link:0,get_graph_from_pmatrix:0,get_lagged_depend:0,get_links_from_graph:0,get_mc:0,get_measur:0,get_medi:0,get_mediation_graph_data:0,get_model_selection_criterion:0,get_optimal_set:0,get_predictor:0,get_shuffle_signific:0,get_signific:0,get_test_arrai:0,get_train_arrai:0,get_tsg:0,get_val_matrix:0,github:0,give:0,given:0,going:0,gp_param:0,gpdc:0,gpdctorch:0,gpytorch:0,graph:0,graph_bool:0,graph_data:0,graph_is_mag:0,graph_typ:0,graphic:0,greater:0,grei:0,grey_masked_sampl:0,grid:0,ground:0,guarante:0,guidanc:0,handl:0,hard:0,has:0,has_path:0,hash:0,have:0,head:0,heavisid:0,heigth:0,help:0,helper:0,henc:0,here:0,hidden:0,hidden_vari:0,high:0,higher:0,histogram:0,hochberg:0,horizont:0,how:0,howev:0,html:0,http:0,hyper:0,hyperparamet:0,hypothesi:0,hypothet:0,identifi:0,iint:0,implement:0,impli:0,importantli:0,improv:0,includ:0,include_lagzero_link:0,include_lagzero_par:0,include_neighbor:0,incom:0,index:0,indirect:0,individu:0,inf:0,infin:0,info:0,inform:0,inherit:0,initi:0,initial_valu:0,inner_edg:0,inner_edge_styl:0,inno_cov:0,innov:0,input:0,instanc:0,instanti:0,instead:0,instruct:0,integ:0,intellig:0,interdisciplinari:0,interest:0,intern:0,interpret:0,interv:0,interven:0,intervent:0,intervention_data:0,intervention_typ:0,introduc:0,introduct:0,inv_inno_cov:0,invalid:0,invers:0,invit:0,irrelev:0,iter:0,its:0,itself:0,j_t:0,joint:0,journal:0,just:0,kei:0,kernel:0,kind:0,knn:0,kretschmer:0,kwarg:0,label:0,label_fonts:0,label_space_left:0,label_space_top:0,lag1:0,lag2:0,lag:0,lag_arrai:0,lag_mod:0,lag_unit:0,lagfunct:0,lagged_par:0,larg:0,larger:0,last:0,latent:0,later:0,latter:0,lead:0,learn:0,least:0,leav:0,left:0,legend:0,legend_fonts:0,legend_width:0,len:0,length:0,less:0,let:0,lett:0,level:0,lightgrei:0,like:0,likelihood:0,limit:0,lin_f:0,line:0,linear:0,linear_model:0,linearmedi:0,linearregress:0,linewidth:0,link:0,link_attribut:0,link_coeff:0,link_colorbar_label:0,link_frequ:0,link_label_fonts:0,link_matrix:0,link_width:0,links_coeff:0,links_to_graph:0,list:0,load:0,log:0,look:0,low:0,lower:0,lowhighpass_filt:0,made:0,mag:0,magnitud:0,mai:0,main:0,major:0,make:0,mani:0,map:0,margin:0,maria:0,mark:0,marker:0,markers:0,markov:0,mask:0,mask_typ:0,match:0,mathcal:0,matplotlib:0,matric:0,matrix:0,matter:0,max:0,max_combin:0,max_cond_px:0,max_conds_dim:0,max_conds_pi:0,max_conds_px:0,max_conds_px_lag:0,max_delai:0,max_lag:0,max_lag_or_tau_max:0,max_p_glob:0,max_p_non_ancestr:0,max_pds_set:0,max_q_glob:0,maxim:0,maximum:0,mce:0,mci:0,mean:0,measur:0,med:0,member:0,memori:0,method:0,method_arg:0,middl:0,might:0,minim:0,minimized_optim:0,minimum:0,minu:0,miss:0,missing_flag:0,mlr:0,mmr:0,mode:0,model_param:0,modul:0,modulo:0,momentari:0,more:0,most:0,most_frequent_link:0,mostli:0,motif:0,much:0,multi:0,multipl:0,multivari:0,must:0,mutual:0,n_preliminary_iter:0,n_symb:0,nail:0,name:0,nan:0,napds_t:0,natur:0,ncomms9502:0,nearest:0,necessari:0,need:0,neg:0,neighbor:0,nest:0,net_to_tsg:0,network:0,network_lower_bound:0,neural:0,neurip:0,never:0,nevertheless:0,new_data:0,niehgbor:0,no_apr:0,no_nois:0,no_non_ancestral_phas:0,node:0,node_aspect:0,node_colorbar_label:0,node_label_s:0,node_po:0,node_s:0,node_tick:0,nois:0,non:0,non_rep:0,none:0,nonlinear:0,nonstat:0,nonstationari:0,nonzero:0,normal:0,note:0,nowack:0,npz:0,null_dist:0,null_dist_filenam:0,nulldist:0,number:0,numer:0,numpi:0,object:0,observ:0,observed_var:0,occur:0,onc:0,one:0,onli:0,only_non_causal_path:0,opac:0,oper:0,opposit:0,optim:0,optimality_cond_des_ym:0,optimality_cond_i:0,optimz:0,option:0,oracl:0,oracleci:0,order:0,ordin:0,ordinal_patt_arrai:0,ordinari:0,org:0,orient:0,orient_comtemp:0,orient_contemp:0,origin:0,orrd:0,oset:0,oset_:0,other:0,otherwis:0,otion:0,ouput:0,out:0,outcom:0,output:0,over:0,overlaid:0,overlap:0,overrid:0,overwrit:0,p_matrix:0,packag:0,page:0,pair:0,pairwis:0,panel:0,paper:0,parallel:0,paramet:0,parametr:0,parcorr:0,parent:0,parent_node_id:0,parents_dict:0,parents_neighbors_coeff:0,parents_of_lag:0,part:0,partial:0,particular:0,pass:0,pass_period:0,path:0,path_node_arrai:0,path_val_matrix:0,pathwai:0,patt:0,patt_mask:0,patt_tim:0,pattern:0,pc1:0,pc_1:0,pc_alpha:0,pcmciplu:0,pdf:0,peak:0,pearl:0,pearson:0,percentil:0,perform:0,period:0,permut:0,perp:0,perspect:0,phase:0,phi:0,phy:0,physrev:0,pip:0,plai:0,pleas:0,plot_graph:0,plot_gridlin:0,plot_lagfunc:0,plot_mediation_graph:0,plot_mediation_time_series_graph:0,plot_time_series_graph:0,plot_timeseri:0,plot_tsg:0,point:0,pomp:0,pos:0,posit:0,possibl:0,post:0,potenti:0,power:0,pq_matrix:0,practic:0,pre:0,precis:0,precomput:0,pred_param:0,predict_total_effect:0,predict_wright_effect:0,prediction_model:0,predictor:0,prelim_onli:0,prelim_rul:0,prelim_with_collider_rul:0,preliminari:0,preprocess:0,present:0,preserv:0,press:0,previou:0,prime:0,print:0,print_array_info:0,print_info:0,print_result:0,print_significant_link:0,prior:0,priorit:0,prl:0,procedur:0,proceed:0,processor:0,project:0,proper:0,properti:0,provid:0,pseudcod:0,pseudoc:0,pseudocod:0,psi:0,purpos:0,pval:0,pval_max:0,pyplot:0,python:0,q_matrix:0,qualiti:0,quantifi:0,quantil:0,quantile_bin_arrai:0,quantiti:0,r10:0,r_x:0,r_y:0,rais:0,randn:0,random:0,randomst:0,rang:0,rank:0,rate:0,rather:0,ratio:0,rdbu_r:0,recal:0,recommend:0,reconstruct:0,recycle_residu:0,red:0,reduc:0,refer:0,regard:0,regress:0,regular:0,rel:0,relat:0,relationship:0,relev:0,remain:0,remember_only_par:0,remov:0,remove_missing_upto_maxlag:0,repeat:0,replac:0,repo:0,repres:0,requir:0,reset_lagged_link:0,residu:0,respect:0,restrict:0,result:0,return_cleaned_xyz:0,return_data:0,return_dict:0,return_null_dist:0,return_parents_dict:0,return_path:0,return_separate_set:0,return_significant_link:0,rev:0,rho:0,richardson:0,right:0,rizzo:0,robust:0,role:0,row:0,rtype:0,rule:0,run:0,run_bivci:0,run_fullci:0,run_lpcmci:0,run_mci:0,run_pc_stabl:0,run_pcalg:0,run_pcalg_non_timeseries_data:0,run_pcmci:0,run_pcmciplu:0,run_sliding_window_of:0,run_test:0,run_test_raw:0,rung:0,runge18a:0,runtim:0,s41467:0,same:0,sampl:0,sample_s:0,saniti:0,save:0,save_iter:0,save_nam:0,savefig:0,scale:0,sci:0,scienc:0,sciencemag:0,scikit:0,scipi:0,scitat:0,score:0,script:0,search:0,second:0,section:0,see:0,seed:0,seen:0,sejdinov:0,select:0,selected_link:0,selected_target:0,selected_vari:0,selection_var:0,self:0,separ:0,sepset:0,set:0,set_datafram:0,set_mask_typ:0,setter:0,setup:0,setup_arg:0,setup_matrix:0,sever:0,shape:0,shorter:0,should:0,show:0,show_colorbar:0,shown:0,shuffl:0,shuffle_neighbor:0,shuffle_test:0,side:0,sig_blocklength:0,sig_overrid:0,sig_sampl:0,sig_thr:0,sigma:0,signfic:0,signficic:0,signific:0,sim:0,simpl:0,simpli:0,sinc:0,size:0,skeleton:0,skip:0,skip_ticks_data_i:0,skip_ticks_data_x:0,sklearn:0,slice:0,slide:0,slightli:0,smaller:0,smooth:0,smooth_width:0,soft:0,some:0,sort:0,sound:0,sourc:0,space:0,spatial:0,spatio:0,special:0,special_nod:0,specif:0,specifi:0,spirt:0,squar:0,stack:0,standard:0,standard_color_link:0,standard_color_nod:0,standardscal:0,star:0,start:0,starts_with:0,stationar:0,statist:0,std:0,step:0,steps_ahead:0,still:0,stop:0,store:0,str:0,straight:0,strength:0,string:0,structur:0,structural_causal_process:0,student:0,style:0,sub:0,subplot:0,subset:0,subspac:0,suffici:0,suitabl:0,sum:0,sum_:0,summar:0,summari:0,summary_result:0,superset:0,supplement:0,suppli:0,support:0,sure:0,surrog:0,suscept:0,symb_arrai:0,symbol:0,symbolifi:0,symmetr:0,symmetrize_p_and_val_matrix:0,system:0,szeke:0,tail:0,take:0,taken:0,target:0,target_predictor:0,tau:0,tau_:0,tau_max:0,tau_min:0,tau_mix:0,taumax:0,techniqu:0,tempor:0,termin:0,test_indic:0,than:0,thei:0,them:0,themselv:0,theorem:0,theoret:0,thi:0,thm:0,those:0,threshold:0,through:0,tick:0,tickmark:0,tild:0,time_bin_length:0,time_bin_with_mask:0,time_label:0,time_lag:0,timelabel:0,togeth:0,top:0,toronto:0,total:0,toward:0,train:0,train_indic:0,transfer:0,transform:0,translat:0,tripl:0,true_par:0,true_parent_neighbor:0,truncat:0,truth:0,tsg:0,tsg_path_val_matrix:0,tsg_to_net:0,tune:0,tupl:0,tutori:0,twice:0,two:0,two_sided_thr:0,type:0,typic:0,uai2020:0,uai:0,uncertainti:0,unclear:0,uncondit:0,undecid:0,under:0,underli:0,undirect:0,uniform:0,uniqu:0,unit:0,unlik:0,unori:0,unrestrict:0,unshield:0,unshuffl:0,update_middle_mark:0,upper:0,use:0,use_a_pds_t_for_major:0,use_mask:0,used:0,useful:0,user:0,uses:0,using:0,v84:0,val:0,val_matrix:0,val_matrix_interv:0,val_matrix_mean:0,val_min:0,val_onli:0,valid:0,valu:0,var1:0,var2:0,var_nam:0,var_network:0,var_process:0,var_unit:0,vari:0,variabl:0,varianc:0,variant:0,varibl:0,variou:0,varlag:0,varx:0,vector:0,verbos:0,veri:0,vertic:0,via:0,view:0,visual:0,vmax_edg:0,vmax_nod:0,vmin_edg:0,vmin_nod:0,weight:0,weighted_avg_and_std:0,well:0,when:0,where:0,whether:0,which:0,whichev:0,wide:0,widehat:0,width:0,wildcard:0,window:0,window_length:0,window_step:0,within:0,without:0,work:0,worker:0,wrapper:0,wright:0,www:0,x_base:0,x_i:0,x_j:0,x_t:0,xyz:0,y_base:0,y_t:0,yield:0,you:0,z_i:0,z_j:0,z_t:0,zero:0},titles:["TIGRAMITE"],titleterms:{"function":0,analysi:0,causal:0,causal_effect:0,condit:0,data:0,data_process:0,effect:0,gener:0,independ:0,independence_test:0,indic:0,lpcmci:0,mediat:0,model:0,pcmci:0,plot:0,predict:0,process:0,seri:0,tabl:0,test:0,tigramit:0,time:0,toi:0,toymodel:0}}) \ No newline at end of file +Search.setIndex({docnames:["index"],envversion:{"sphinx.domains.c":1,"sphinx.domains.changeset":1,"sphinx.domains.citation":1,"sphinx.domains.cpp":1,"sphinx.domains.index":1,"sphinx.domains.javascript":1,"sphinx.domains.math":2,"sphinx.domains.python":1,"sphinx.domains.rst":1,"sphinx.domains.std":1,"sphinx.ext.viewcode":1,sphinx:56},filenames:["index.rst"],objects:{"tigramite.causal_effects":{CausalEffects:[0,0,1,""]},"tigramite.causal_effects.CausalEffects":{check_XYS_paths:[0,1,1,""],check_optimality:[0,1,1,""],fit_bootstrap_of:[0,1,1,""],fit_total_effect:[0,1,1,""],fit_wright_effect:[0,1,1,""],get_graph_from_dict:[0,1,1,""],get_mediators:[0,1,1,""],get_optimal_set:[0,1,1,""],predict_bootstrap_of:[0,1,1,""],predict_total_effect:[0,1,1,""],predict_wright_effect:[0,1,1,""]},"tigramite.data_processing":{DataFrame:[0,0,1,""],lowhighpass_filter:[0,4,1,""],ordinal_patt_array:[0,4,1,""],quantile_bin_array:[0,4,1,""],smooth:[0,4,1,""],structural_causal_process:[0,4,1,""],time_bin_with_mask:[0,4,1,""],var_process:[0,4,1,""],weighted_avg_and_std:[0,4,1,""]},"tigramite.data_processing.DataFrame":{construct_array:[0,1,1,""],data:[0,3,1,""],datatime:[0,3,1,""],mask:[0,3,1,""],missing_flag:[0,3,1,""],print_array_info:[0,1,1,""],remove_missing_upto_maxlag:[0,3,1,""],var_names:[0,3,1,""]},"tigramite.independence_tests":{CMIknn:[0,0,1,""],CMIsymb:[0,0,1,""],CondIndTest:[0,0,1,""],GPDC:[0,0,1,""],GPDCtorch:[0,0,1,""],OracleCI:[0,0,1,""],ParCorr:[0,0,1,""]},"tigramite.independence_tests.CMIknn":{get_conditional_entropy:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CMIsymb":{get_dependence_measure:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.CondIndTest":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_bootstrap_confidence:[0,1,1,""],get_confidence:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_fixed_thres_significance:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],get_significance:[0,1,1,""],measure:[0,1,1,""],print_info:[0,1,1,""],run_test:[0,1,1,""],run_test_raw:[0,1,1,""],set_dataframe:[0,1,1,""],set_mask_type:[0,1,1,""]},"tigramite.independence_tests.GPDC":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.GPDCtorch":{generate_and_save_nulldists:[0,1,1,""],generate_nulldist:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.independence_tests.OracleCI":{check_shortest_path:[0,1,1,""],get_confidence:[0,1,1,""],get_graph_from_links:[0,1,1,""],get_links_from_graph:[0,1,1,""],get_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],measure:[0,1,1,""],run_test:[0,1,1,""],set_dataframe:[0,1,1,""]},"tigramite.independence_tests.ParCorr":{get_analytic_confidence:[0,1,1,""],get_analytic_significance:[0,1,1,""],get_dependence_measure:[0,1,1,""],get_model_selection_criterion:[0,1,1,""],get_shuffle_significance:[0,1,1,""],measure:[0,1,1,""]},"tigramite.lpcmci":{LPCMCI:[0,0,1,""]},"tigramite.lpcmci.LPCMCI":{run_lpcmci:[0,1,1,""]},"tigramite.models":{LinearMediation:[0,0,1,""],Models:[0,0,1,""],Prediction:[0,0,1,""]},"tigramite.models.LinearMediation":{fit_model:[0,1,1,""],get_ace:[0,1,1,""],get_acs:[0,1,1,""],get_all_ace:[0,1,1,""],get_all_acs:[0,1,1,""],get_all_amce:[0,1,1,""],get_amce:[0,1,1,""],get_ce:[0,1,1,""],get_ce_max:[0,1,1,""],get_coeff:[0,1,1,""],get_mce:[0,1,1,""],get_mediation_graph_data:[0,1,1,""],get_tsg:[0,1,1,""],get_val_matrix:[0,1,1,""],net_to_tsg:[0,1,1,""],tsg_to_net:[0,1,1,""]},"tigramite.models.Models":{get_coefs:[0,1,1,""],get_fit:[0,1,1,""],get_general_fitted_model:[0,1,1,""],get_general_prediction:[0,1,1,""],get_val_matrix:[0,1,1,""]},"tigramite.models.Prediction":{fit:[0,1,1,""],get_predictors:[0,1,1,""],get_test_array:[0,1,1,""],get_train_array:[0,1,1,""],predict:[0,1,1,""]},"tigramite.pcmci":{PCMCI:[0,0,1,""]},"tigramite.pcmci.PCMCI":{N:[0,3,1,""],T:[0,3,1,""],all_parents:[0,3,1,""],convert_to_string_graph:[0,1,1,""],get_corrected_pvalues:[0,1,1,""],get_graph_from_pmatrix:[0,1,1,""],get_lagged_dependencies:[0,1,1,""],iterations:[0,3,1,""],print_results:[0,1,1,""],print_significant_links:[0,1,1,""],pval_max:[0,3,1,""],return_parents_dict:[0,1,1,""],return_significant_links:[0,1,1,""],run_bivci:[0,1,1,""],run_fullci:[0,1,1,""],run_mci:[0,1,1,""],run_pc_stable:[0,1,1,""],run_pcalg:[0,1,1,""],run_pcalg_non_timeseries_data:[0,1,1,""],run_pcmci:[0,1,1,""],run_pcmciplus:[0,1,1,""],run_sliding_window_of:[0,1,1,""],symmetrize_p_and_val_matrix:[0,1,1,""],val_min:[0,3,1,""]},"tigramite.plotting":{plot_graph:[0,4,1,""],plot_lagfuncs:[0,4,1,""],plot_mediation_graph:[0,4,1,""],plot_mediation_time_series_graph:[0,4,1,""],plot_scatterplots:[0,4,1,""],plot_time_series_graph:[0,4,1,""],plot_timeseries:[0,4,1,""],plot_tsg:[0,4,1,""],setup_matrix:[0,0,1,""],setup_scatter_matrix:[0,0,1,""]},"tigramite.plotting.setup_matrix":{add_lagfuncs:[0,1,1,""],savefig:[0,1,1,""]},"tigramite.plotting.setup_scatter_matrix":{add_scatterplot:[0,1,1,""],adjustfig:[0,1,1,""]},"tigramite.toymodels":{structural_causal_processes:[0,2,0,"-"]},"tigramite.toymodels.structural_causal_processes":{links_to_graph:[0,4,1,""],structural_causal_process:[0,4,1,""],var_process:[0,4,1,""]},tigramite:{data_processing:[0,2,0,"-"],plotting:[0,2,0,"-"]}},objnames:{"0":["py","class","Python class"],"1":["py","method","Python method"],"2":["py","module","Python module"],"3":["py","attribute","Python attribute"],"4":["py","function","Python function"]},objtypes:{"0":"py:class","1":"py:method","2":"py:module","3":"py:attribute","4":"py:function"},terms:{"21st":0,"2xtau_max":0,"36th":0,"579_main_pap":0,"8485ae387a981d783f8764e508151cd9":0,"94e70705efae423efda1088614128d0b":0,"abstract":0,"boolean":0,"break":0,"case":0,"class":0,"default":0,"float":0,"import":0,"int":0,"long":0,"new":0,"null":0,"return":0,"static":0,"true":0,"var":0,"while":0,ACE:0,ACS:0,For:0,Its:0,Not:0,OLS:0,The:0,Then:0,There:0,These:0,Used:0,Useful:0,Uses:0,Using:0,Will:0,With:0,_get_single_residu:0,_run_ancestral_removal_phas:0,_run_dsep_removal_phas:0,_run_non_ancestral_removal_phas:0,about:0,abov:0,abs:0,absent:0,absmax:0,absolut:0,accept:0,accord:0,account:0,ace:0,across:0,acs:0,act:0,actual:0,adapt:0,add:0,add_lagfunc:0,add_lagfunc_arg:0,add_scatterplot:0,add_scatterplot_arg:0,add_to_null_dist:0,added:0,adding:0,addit:0,address:0,adj:0,adjac:0,adjust:0,adjustfig:0,adjustment_set:0,admg:0,adv:0,advanc:0,affect:0,after:0,again:0,ahead:0,aic:0,aip:0,akaik:0,algorithm:0,all:0,all_lag:0,all_par:0,all_result:0,alloc:0,allow:0,along:0,alpha:0,alpha_level:0,alreadi:0,also:0,altern:0,alternative_condit:0,although:0,alwai:0,ambigu:0,ambiguous_tripl:0,amc:0,among:0,analyt:0,analyz:0,anc_all_i:0,anc_all_x:0,anc_all_z:0,anc_i:0,anc_x:0,anc_xi:0,ancestor:0,ancestr:0,ani:0,anoth:0,apds_t:0,appli:0,applic:0,appropri:0,apr:0,arang:0,arbitrari:0,argument:0,around:0,arrai:0,array_lik:0,array_mask:0,arrohead:0,arrow:0,arrow_linewidth:0,arrowhead_s:0,articl:0,artifici:0,arxiv:0,assess:0,assign:0,associ:0,assum:0,assumpt:0,ast:0,asymptot:0,attribut:0,au_i:0,au_j:0,auai:0,auto:0,auto_first:0,autocorrel:0,autocovari:0,autodepend:0,automat:0,autoregress:0,auxadmg:0,auxiliari:0,avail:0,averag:0,avoid:0,axes:0,axi:0,backdoor:0,backward:0,bakirov:0,bandwidth:0,base:0,basemap:0,been:0,befor:0,beforehand:0,begin:0,being:0,below:0,benjamini:0,best:0,beta:0,beta_i:0,beta_x:0,better:0,between:0,bia:0,bias:0,bin:0,bincount:0,bindata:0,bivci:0,black:0,block:0,blue:0,bold:0,bool:0,boot_blocklength:0,boot_sampl:0,bootsrap:0,bootstrap:0,both:0,bottom:0,bound:0,box:0,breadth:0,break_once_separ:0,briefli:0,butterworth:0,call:0,callabl:0,can:0,canada:0,canon:0,cardin:0,care:0,caus:0,causaleffect:0,cdot:0,certain:0,chain:0,chao:0,check:0,check_optim:0,check_optimality_cond:0,check_shortest_path:0,check_sm_overlap:0,check_xys_path:0,child:0,choic:0,chosen:0,cite:0,ckdtree:0,clash:0,clean:0,cmap_edg:0,cmap_nod:0,cmi:0,cmiknn:0,cmisymb:0,coef1:0,coef2:0,coeff:0,coeffici:0,collid:0,collider_par:0,colliders_minimized_optim:0,colliders_onli:0,color:0,colorbar:0,colormap:0,column:0,com:0,combin:0,come:0,command:0,common:0,commun:0,compar:0,comparison:0,compat:0,complex:0,comprehens:0,comput:0,compute_ancestor:0,concret:0,cond_ind_test:0,condindtest:0,conditional_estim:0,conditional_model:0,conditions_data:0,conduct:0,conf_blocklength:0,conf_lev:0,conf_low:0,conf_matrix:0,conf_sampl:0,conf_upp:0,confer:0,confid:0,confidence_interv:0,conflict:0,conflict_resolut:0,confound:0,conserv:0,consid:0,consider:0,considerd:0,consist:0,constant:0,constrain:0,construct:0,construct_arrai:0,constructor:0,contain:0,contemp_collider_rul:0,contemp_cond:0,contemporan:0,content:0,continu:0,contrast:0,control:0,conveni:0,convert:0,convert_to_string_graph:0,coordin:0,correct:0,corrected_a:0,correl:0,correspond:0,cost:0,could:0,coupl:0,covari:0,creat:0,criteria:0,criterion:0,cross:0,cube:0,current:0,curv:0,curvatur:0,curved_radiu:0,cut_off:0,cutoff:0,cutperiod:0,cython:0,d_z:0,dag:0,dash:0,data_linewidth:0,data_transform:0,datafram:0,dataset:0,datatim:0,dcor:0,debug:0,decai:0,def:0,default_rng:0,defin:0,definin:0,degre:0,delai:0,denot:0,densiti:0,depend:0,dependence_measur:0,depict:0,deprec:0,depth:0,deriv:0,describ:0,descript:0,detail:0,detect:0,determin:0,deviat:0,dict:0,dictionari:0,differ:0,digamma:0,digest:0,dim:0,dimens:0,dimension:0,direct:0,direction:0,directli:0,disabl:0,discov:0,discoveri:0,discret:0,discuss:0,disk:0,dismiss:0,dist:0,distanc:0,distribut:0,do_check:0,doc:0,doe:0,doi:0,dpag:0,draw:0,drawn:0,driver:0,due:0,dummi:0,duplic:0,dure:0,eaau4996:0,each:0,easi:0,edg:0,edge_tick:0,effici:0,either:0,element:0,els:0,eman:0,embed:0,empti:0,end:0,ends_with:0,ensur:0,entir:0,entri:0,entropi:0,enumer:0,epsilon_:0,equal:0,equival:0,error:0,estim:0,estimate_confid:0,eta:0,etc:0,evalu:0,even:0,everi:0,exampl:0,except:0,exclud:0,exclude_contemporan:0,exclude_i:0,exclude_j:0,exclude_k:0,exclude_self_effect:0,execut:0,exist:0,expect:0,experi:0,experiment:0,explain:0,extern:0,extraz:0,f_x:0,f_y:0,factor:0,faculti:0,faith:0,fals:0,fancyarrowpatch:0,faster:0,fdr:0,fdr_bh:0,fdr_method:0,featur:0,feedback:0,fig:0,fig_ax:0,figsiz:0,figur:0,file:0,fill:0,filter:0,fine:0,first:0,fit:0,fit_bootstrap_of:0,fit_model:0,fit_result:0,fit_total_effect:0,fit_wright_effect:0,fix:0,fix_all_edges_before_final_orient:0,fixed_thr:0,flag:0,flaxman:0,flexibl:0,follow:0,fontsiz:0,forbidden_nod:0,forc:0,forecast:0,form:0,format:0,forward:0,found:0,four:0,frac:0,fraction:0,framework:0,free:0,freedom:0,frenzel:0,frequenc:0,frequent:0,friendli:0,from:0,full:0,fullci:0,fulli:0,func:0,further:0,futur:0,gabor:0,gatewai:0,gauss_pr:0,gaussian:0,gaussianprocessregressor:0,gaussprocreg:0,gaussprocregtorch:0,generate_and_save_nulldist:0,generate_nulldist:0,gerhardu:0,get:0,get_ac:0,get_all_ac:0,get_all_amc:0,get_amc:0,get_analytic_confid:0,get_analytic_signific:0,get_bootstrap_confid:0,get_c:0,get_ce_max:0,get_coef:0,get_coeff:0,get_conditional_entropi:0,get_confid:0,get_corrected_pvalu:0,get_dependence_measur:0,get_fit:0,get_fixed_thres_signific:0,get_general_fitted_model:0,get_general_predict:0,get_graph_from_dict:0,get_graph_from_link:0,get_graph_from_pmatrix:0,get_lagged_depend:0,get_links_from_graph:0,get_mc:0,get_measur:0,get_medi:0,get_mediation_graph_data:0,get_model_selection_criterion:0,get_optimal_set:0,get_predictor:0,get_shuffle_signific:0,get_signific:0,get_test_arrai:0,get_train_arrai:0,get_tsg:0,get_val_matrix:0,github:0,give:0,given:0,going:0,gp_param:0,gpdc:0,gpdctorch:0,gpytorch:0,graph:0,graph_bool:0,graph_data:0,graph_is_mag:0,graph_typ:0,graphic:0,greater:0,grei:0,grey_masked_sampl:0,grid:0,ground:0,guarante:0,guidanc:0,handl:0,hard:0,has:0,has_path:0,hash:0,have:0,head:0,heavisid:0,heigth:0,help:0,helper:0,henc:0,here:0,hidden:0,hidden_vari:0,high:0,higher:0,histogram:0,hochberg:0,horizont:0,how:0,howev:0,html:0,http:0,hyper:0,hyperparamet:0,hypothesi:0,hypothet:0,identifi:0,iint:0,implement:0,impli:0,importantli:0,improv:0,includ:0,include_lagzero_link:0,include_lagzero_par:0,include_neighbor:0,incom:0,index:0,indirect:0,individu:0,inf:0,infin:0,info:0,inform:0,inherit:0,initi:0,initial_valu:0,inner_edg:0,inner_edge_styl:0,inno_cov:0,innov:0,input:0,instanc:0,instanti:0,instead:0,instruct:0,integ:0,intellig:0,interdisciplinari:0,interest:0,intern:0,interpret:0,interv:0,interven:0,intervent:0,intervention_data:0,intervention_typ:0,introduc:0,introduct:0,inv_inno_cov:0,invalid:0,invers:0,inverse_transform:0,invit:0,irrelev:0,iter:0,its:0,itself:0,j_t:0,joint:0,journal:0,just:0,kei:0,kernel:0,kind:0,knn:0,kretschmer:0,kwarg:0,label:0,label_fonts:0,label_space_left:0,label_space_top:0,lag1:0,lag2:0,lag:0,lag_arrai:0,lag_mod:0,lag_unit:0,lagfunct:0,lagged_par:0,larg:0,larger:0,last:0,latent:0,later:0,latter:0,lead:0,learn:0,least:0,leav:0,left:0,legend:0,legend_fonts:0,legend_width:0,len:0,length:0,less:0,let:0,lett:0,level:0,lightgrei:0,like:0,likelihood:0,limit:0,lin_f:0,line:0,linear:0,linear_model:0,linearmedi:0,linearregress:0,linewidth:0,link:0,link_attribut:0,link_coeff:0,link_colorbar_label:0,link_frequ:0,link_label_fonts:0,link_matrix:0,link_width:0,links_coeff:0,links_to_graph:0,list:0,load:0,log:0,look:0,low:0,lower:0,lowhighpass_filt:0,made:0,mag:0,magnitud:0,mai:0,main:0,major:0,make:0,mani:0,map:0,margin:0,maria:0,mark:0,marker:0,markers:0,markov:0,mask:0,mask_typ:0,match:0,mathcal:0,matplotlib:0,matric:0,matrix:0,matter:0,max:0,max_combin:0,max_cond_px:0,max_conds_dim:0,max_conds_pi:0,max_conds_px:0,max_conds_px_lag:0,max_delai:0,max_lag:0,max_lag_or_tau_max:0,max_p_glob:0,max_p_non_ancestr:0,max_pds_set:0,max_q_glob:0,maxim:0,maximum:0,mce:0,mci:0,mean:0,measur:0,med:0,member:0,memori:0,method:0,method_arg:0,middl:0,might:0,minim:0,minimized_optim:0,minimum:0,minu:0,miss:0,missing_flag:0,mlr:0,mmr:0,mode:0,model_param:0,modul:0,modulo:0,momentari:0,more:0,most:0,most_frequent_link:0,mostli:0,motif:0,much:0,multi:0,multipl:0,multivari:0,must:0,mutual:0,n_preliminary_iter:0,n_symb:0,nail:0,name:0,nan:0,napds_t:0,natur:0,ncomms9502:0,nearest:0,necessari:0,need:0,neg:0,neighbor:0,nest:0,net_to_tsg:0,network:0,network_lower_bound:0,neural:0,neurip:0,never:0,nevertheless:0,new_data:0,niehgbor:0,no_apr:0,no_nois:0,no_non_ancestral_phas:0,node:0,node_aspect:0,node_colorbar_label:0,node_label_s:0,node_po:0,node_s:0,node_tick:0,nois:0,non:0,non_rep:0,none:0,nonlinear:0,nonstat:0,nonstationari:0,nonzero:0,normal:0,note:0,nowack:0,npz:0,null_dist:0,null_dist_filenam:0,nulldist:0,number:0,numer:0,numpi:0,object:0,observ:0,observed_var:0,occur:0,onc:0,one:0,onli:0,only_non_causal_path:0,opac:0,oper:0,opposit:0,optim:0,optimality_cond_des_ym:0,optimality_cond_i:0,optimz:0,option:0,oracl:0,oracleci:0,order:0,ordin:0,ordinal_patt_arrai:0,ordinari:0,org:0,orient:0,orient_comtemp:0,orient_contemp:0,origin:0,orrd:0,oset:0,oset_:0,other:0,otherwis:0,otion:0,ouput:0,out:0,outcom:0,output:0,over:0,overlaid:0,overlap:0,overrid:0,overwrit:0,p_matrix:0,packag:0,page:0,pair:0,pairwis:0,panel:0,paper:0,parallel:0,paramet:0,parametr:0,parcorr:0,parent:0,parent_node_id:0,parents_dict:0,parents_neighbors_coeff:0,parents_of_lag:0,part:0,partial:0,particular:0,pass:0,pass_period:0,path:0,path_node_arrai:0,path_val_matrix:0,pathwai:0,patt:0,patt_mask:0,patt_tim:0,pattern:0,pc1:0,pc_1:0,pc_alpha:0,pcmciplu:0,pdf:0,peak:0,pearl:0,pearson:0,percentil:0,perform:0,period:0,permut:0,perp:0,perspect:0,phase:0,phi:0,phy:0,physrev:0,pip:0,plai:0,pleas:0,plot_graph:0,plot_gridlin:0,plot_lagfunc:0,plot_mediation_graph:0,plot_mediation_time_series_graph:0,plot_scatterplot:0,plot_time_series_graph:0,plot_timeseri:0,plot_tsg:0,point:0,pomp:0,pos:0,posit:0,possibl:0,post:0,potenti:0,power:0,pq_matrix:0,practic:0,pre:0,precis:0,precomput:0,pred_param:0,predict_bootstrap_of:0,predict_total_effect:0,predict_wright_effect:0,prediction_model:0,predictor:0,prelim_onli:0,prelim_rul:0,prelim_with_collider_rul:0,preliminari:0,preprocess:0,present:0,preserv:0,press:0,previou:0,prime:0,print:0,print_array_info:0,print_info:0,print_result:0,print_significant_link:0,prior:0,priorit:0,prl:0,procedur:0,proceed:0,processor:0,project:0,proper:0,properti:0,provid:0,pseudcod:0,pseudoc:0,pseudocod:0,psi:0,purpos:0,pval:0,pval_max:0,pyplot:0,python:0,q_matrix:0,qualiti:0,quantifi:0,quantil:0,quantile_bin_arrai:0,quantiti:0,r10:0,r_x:0,r_y:0,rais:0,randn:0,random:0,randomst:0,rang:0,rank:0,rate:0,rather:0,ratio:0,rdbu_r:0,recal:0,recommend:0,reconstruct:0,recycle_residu:0,red:0,reduc:0,refer:0,regard:0,regress:0,regular:0,rel:0,relat:0,relationship:0,relev:0,remain:0,remember_only_par:0,remov:0,remove_missing_upto_maxlag:0,repeat:0,replac:0,repo:0,repres:0,requir:0,reset_lagged_link:0,residu:0,respect:0,restrict:0,result:0,return_cleaned_xyz:0,return_data:0,return_dict:0,return_further_pred_result:0,return_null_dist:0,return_parents_dict:0,return_path:0,return_separate_set:0,return_significant_link:0,rev:0,rho:0,richardson:0,right:0,rizzo:0,robust:0,role:0,row:0,rtype:0,rule:0,run:0,run_bivci:0,run_fullci:0,run_lpcmci:0,run_mci:0,run_pc_stabl:0,run_pcalg:0,run_pcalg_non_timeseries_data:0,run_pcmci:0,run_pcmciplu:0,run_sliding_window_of:0,run_test:0,run_test_raw:0,rung:0,runge18a:0,runtim:0,s41467:0,same:0,sampl:0,sample_s:0,saniti:0,save:0,save_iter:0,save_nam:0,savefig:0,scale:0,scatter:0,scatter_lag:0,scatterplot:0,sci:0,scienc:0,sciencemag:0,scikit:0,scipi:0,scitat:0,score:0,script:0,search:0,second:0,section:0,see:0,seed:0,seen:0,sejdinov:0,select:0,selected_link:0,selected_target:0,selected_vari:0,selection_var:0,self:0,separ:0,sepset:0,set:0,set_datafram:0,set_mask_typ:0,setter:0,setup:0,setup_arg:0,setup_matrix:0,setup_scatter_matrix:0,sever:0,shape:0,shift:0,shorter:0,should:0,show:0,show_colorbar:0,shown:0,shuffl:0,shuffle_neighbor:0,shuffle_test:0,side:0,sig_blocklength:0,sig_overrid:0,sig_sampl:0,sig_thr:0,sigma:0,signfic:0,signficic:0,signific:0,sim:0,simpl:0,simpli:0,sinc:0,size:0,skeleton:0,skip:0,skip_ticks_data_i:0,skip_ticks_data_x:0,sklearn:0,slice:0,slide:0,slightli:0,smaller:0,smooth:0,smooth_width:0,soft:0,some:0,sort:0,sound:0,sourc:0,space:0,spatial:0,spatio:0,special:0,special_nod:0,specif:0,specifi:0,spirt:0,squar:0,stack:0,standard:0,standard_color_link:0,standard_color_nod:0,standardscal:0,star:0,start:0,starts_with:0,stationar:0,statist:0,std:0,step:0,steps_ahead:0,still:0,stop:0,store:0,str:0,straight:0,strength:0,string:0,structur:0,structural_causal_process:0,student:0,style:0,sub:0,subplot:0,subset:0,subspac:0,suffici:0,suitabl:0,sum:0,sum_:0,summar:0,summari:0,summary_result:0,superset:0,supplement:0,suppli:0,support:0,sure:0,surrog:0,suscept:0,symb_arrai:0,symbol:0,symbolifi:0,symmetr:0,symmetrize_p_and_val_matrix:0,system:0,szeke:0,tail:0,take:0,taken:0,target:0,target_predictor:0,tau:0,tau_:0,tau_max:0,tau_min:0,tau_mix:0,taumax:0,techniqu:0,tempor:0,termin:0,test_indic:0,than:0,thei:0,them:0,themselv:0,theorem:0,theoret:0,thi:0,thm:0,those:0,threshold:0,through:0,tick:0,tickmark:0,tild:0,time_bin_length:0,time_bin_with_mask:0,time_label:0,time_lag:0,timelabel:0,togeth:0,top:0,toronto:0,total:0,toward:0,train:0,train_indic:0,transfer:0,transform:0,translat:0,tripl:0,true_par:0,true_parent_neighbor:0,truncat:0,truth:0,tsg:0,tsg_path_val_matrix:0,tsg_to_net:0,tune:0,tupl:0,tutori:0,twice:0,two:0,two_sided_thr:0,type:0,typic:0,uai2020:0,uai:0,uncertainti:0,unclear:0,uncondit:0,undecid:0,under:0,underli:0,undirect:0,uniform:0,uniqu:0,unit:0,unlik:0,unori:0,unrestrict:0,unshield:0,unshuffl:0,update_middle_mark:0,upper:0,use:0,use_a_pds_t_for_major:0,use_mask:0,used:0,useful:0,user:0,uses:0,using:0,v84:0,val:0,val_matrix:0,val_matrix_interv:0,val_matrix_mean:0,val_min:0,val_onli:0,valid:0,valu:0,var1:0,var2:0,var_nam:0,var_network:0,var_process:0,var_unit:0,vari:0,variabl:0,varianc:0,variant:0,varibl:0,variou:0,varlag:0,varx:0,vector:0,verbos:0,veri:0,vertic:0,via:0,view:0,visual:0,vmax_edg:0,vmax_nod:0,vmin_edg:0,vmin_nod:0,weight:0,weighted_avg_and_std:0,well:0,when:0,where:0,whether:0,which:0,whichev:0,wide:0,widehat:0,width:0,wildcard:0,window:0,window_length:0,window_step:0,within:0,without:0,work:0,worker:0,wrapper:0,wright:0,www:0,x_base:0,x_i:0,x_j:0,x_t:0,xyz:0,y_base:0,y_t:0,yield:0,you:0,z_i:0,z_j:0,z_t:0,zero:0},titles:["TIGRAMITE"],titleterms:{"function":0,analysi:0,causal:0,causal_effect:0,condit:0,data:0,data_process:0,effect:0,gener:0,independ:0,independence_test:0,indic:0,lpcmci:0,mediat:0,model:0,pcmci:0,plot:0,predict:0,process:0,seri:0,tabl:0,test:0,tigramit:0,time:0,toi:0,toymodel:0}}) \ No newline at end of file diff --git a/release_on_pip.sh b/release_on_pip.sh old mode 100644 new mode 100755 index 658bb556..d964c68a --- a/release_on_pip.sh +++ b/release_on_pip.sh @@ -1,5 +1,7 @@ #!/bin/bash +version="50111" + # Steps to move from github to pip # (Make sure pypi token exists) @@ -11,12 +13,12 @@ # tigramite$ git add docs/* # Create folder for next version (e.g., version 4.2.1.0 as edited in setup.py) -# mkdir v4210 -# cd v4210/ +mkdir /home/rung_ja/work/code/python_code/tigramite/tigramite_v4/tigramitepipdistribute/tigramitepypi/v$version +cd /home/rung_ja/work/code/python_code/tigramite/tigramite_v4/tigramitepipdistribute/tigramitepypi/v$version # Make sure to be in a clean anaconda -conda create --name tigramite-release-5001 python=3.9 -conda activate tigramite-release-5001 +conda create --name tigramite-release-$version python=3.9 anaconda -y +conda activate tigramite-release-$version # Pull tigramite github git clone https://github.com/jakobrunge/tigramite.git diff --git a/setup.py b/setup.py index f28176a0..460ec86d 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ def run(self): # Run the setup setup( name="tigramite", - version="5.0.1.10", + version="5.0.1.11", packages=["tigramite", "tigramite.independence_tests", "tigramite.toymodels"], license="GNU General Public License v3.0", description="Tigramite causal discovery for time series", From 95bf6581a119a79f62709749f8baa241677b507d Mon Sep 17 00:00:00 2001 From: jakobrunge Date: Sat, 9 Apr 2022 15:23:07 +0200 Subject: [PATCH 2/4] fixed bug in causal effects --- release_on_pip.sh | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/release_on_pip.sh b/release_on_pip.sh index d964c68a..077b3e20 100755 --- a/release_on_pip.sh +++ b/release_on_pip.sh @@ -1,6 +1,6 @@ #!/bin/bash -version="50111" +version="50112" # Steps to move from github to pip # (Make sure pypi token exists) diff --git a/setup.py b/setup.py index 460ec86d..0a82ff37 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ def run(self): # Run the setup setup( name="tigramite", - version="5.0.1.11", + version="5.0.1.12", packages=["tigramite", "tigramite.independence_tests", "tigramite.toymodels"], license="GNU General Public License v3.0", description="Tigramite causal discovery for time series", From 21c136bbd61247286669991764ec08a6708ee222 Mon Sep 17 00:00:00 2001 From: jakobrunge Date: Sat, 9 Apr 2022 15:31:25 +0200 Subject: [PATCH 3/4] fixed bug in causal effects --- release_on_pip.sh | 3 ++- setup.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/release_on_pip.sh b/release_on_pip.sh index 077b3e20..c5a0b877 100755 --- a/release_on_pip.sh +++ b/release_on_pip.sh @@ -1,6 +1,6 @@ #!/bin/bash -version="50112" +version="50113" # Steps to move from github to pip # (Make sure pypi token exists) @@ -18,6 +18,7 @@ cd /home/rung_ja/work/code/python_code/tigramite/tigramite_v4/tigramitepipdistri # Make sure to be in a clean anaconda conda create --name tigramite-release-$version python=3.9 anaconda -y +source ~/anaconda3/etc/profile.d/conda.sh conda activate tigramite-release-$version # Pull tigramite github diff --git a/setup.py b/setup.py index 0a82ff37..22ef5087 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ def run(self): # Run the setup setup( name="tigramite", - version="5.0.1.12", + version="5.0.1.13", packages=["tigramite", "tigramite.independence_tests", "tigramite.toymodels"], license="GNU General Public License v3.0", description="Tigramite causal discovery for time series", From 3d33b8f96d990b68ed2f0810aa6fd18467ee293a Mon Sep 17 00:00:00 2001 From: jakobrunge Date: Sat, 9 Apr 2022 15:35:49 +0200 Subject: [PATCH 4/4] fixed bug in causal effects --- release_on_pip.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/release_on_pip.sh b/release_on_pip.sh index c5a0b877..a46eeda2 100755 --- a/release_on_pip.sh +++ b/release_on_pip.sh @@ -1,6 +1,6 @@ #!/bin/bash -version="50113" +version="50114" # Steps to move from github to pip # (Make sure pypi token exists)